I am trying to avoid adding a certain game's data to my table more than once so I am trying to make an if statement that would check if that game's ID is already in the table, however for some reason the if statement is always false. This is my code:
$a = $_GET['id'];
$colname = $_GET['colname'];
$b = "SELECT count(*)
FROM table
WHERE gameid = ".$a;
if($dup = mysqli_query($dbc, $b)){
if(mysqli_num_rows($dup)==0){
$insrt = "INSERT INTO table ($colname)
VALUES ($a)";
mysqli_query($dbc, $insrt);
}
}
If I were you, instead of using logic within your program to avoid creating duplicate entries, I would simply tell MySQL that your ID column should be unique. Take a look at the info on column definitions in the MySQL Reference Manual, specifically the keywords UNIQUE or PRIMARY KEY.
If you specify that your ID column should be a unique index, then MySQL will prevent another entry with the same ID value from being added. That way, in your program, you can simply attempt to add the data, and the procedure will automatically fail if it is a duplicate. As an added bonus, this means you'll only have to do one query from your program instead of two.
A SELECT COUNT().... query, barring exceptional circumstances, is generally going to return at least one row (more if there is a GROUP BY clause that would indicate otherwise); you need to check that the field value is 0, not that there are no rows in the result.
Change your query to remove the aggregate, and just return a column, e.g.
SELECT gameid
FROM table
WHERE gameid = ?
LIMIT 1
You don't need a count of rows, you just need to know whether a row is returned.
Or, you could add a HAVING clause to your query to not return a row when the COUNT is zero...
SELECT COUNT(*)
FROM table
WHERE gameid = ?
HAVING COUNT(*) > 0
There's no need for you to retrieve the value of the column from the row that's returned, just return an empty resultset, and test whether the resultset is empty, like your code is doing.
Related
return multiple data
why?
mysql sql :
select * from t_book where id=(select round(max(id)*rand()) from t_book)
As suggested by #Tarek you might have duplicated id values. To find out which you can run this query:
SELECT id, COUNT(*) c FROM t_book GROUP BY id HAVING c > 1;
On the assumption that "id" is a unique primary key value, it shouldnt return multiple values. In the returned values do all of the "id" fields match, or is it returning multiple varying ids?
You have a Syntax error,
The function Round takes the form:
ROUND(N,[D]);
The problem is not with your id column's uniqueness.
select round(max(id)*rand()) from t_book
This will return various number of ids, at least in mysql 5.6. I don't know why, but it's really weird.
You can try this, for selecting a random record from your table:
select * from t_book order by rand() limit 1;
If you stick with this round-max-random method, keep in mind that round can return 0 too and it's unlikely that you have a 0 id.
First I thought this is caused by duplicate id values. You can try this fiddle, and see what happens: http://sqlfiddle.com/#!9/7fc510/1.
For multiple runs I got 0, 1 or 2 result records.
Is it possible to write a SELECT statement, which returns dataset with zero rows and zero columns?
A dataset will always have at least 1 column, even if it contains no data.
SELECT NULL;
EDIT:
As pointed out by #eggyal , above syntax will return a null row.
His query select null from dual where false; wont return a row.
Not possible in my opinion. You will get at least one column, but no rows.
Select null from yourTable where 1 = 2;
This works for postgresql:
create table test22 ();
select * from test22;
it's normally used for Creating empty Table from an Existing Table
CREATE TABLE NEW_TABLE_NAME AS
SELECT *
FROM EXISTING_TABLE_NAME
where 1=2
No, but it is possible to return a query with no rows. In order to do this without referencing any tables, you can use a subquery:
SELECT NULL FROM (SELECT NULL) AS temp WHERE false;
This query will have one (empty) column, but no rows.
I've used the above construct when there is a query that is different in different cases, followed by a code loop that iterates through the results, and under some conditions you want to make it skip the loop. Replacing the query with the one above is a way of returning empty results and thus skipping the loop without an if block. Because the query contains no table names, that aspect of the code never needs to be changed, and for this reason I prefer it to adding a condition like WHERE false in an existing query.
I prefer this solution to the more concise one referencing dual because that construct is not supported in PostgreSQL; this solution works with any backend that supports subqueries.
Limit 0, 1000 returns the first 1,000 results, but LIMIT 0 returns 0 results.
That's not very intuitive imho. For example, dumb old me thought that removing the 1000 would remove the upper limit to the SELECT query, thus returning all of the results.
Why would anybody even want to query MySQL for 0 results?
From the MySQL documentation
LIMIT 0 quickly returns an empty set. This can be useful for checking the validity of a query. When using one of the MySQL APIs, it can also be employed for obtaining the types of the result columns.
limit 0 can be used to get the same columns types of other tables
create table newtable
select col1 from table1 limit 0;
That way, a hard-coded description of the columns types for newtable is not needed, ensuring that the columns types will still match even if a change occurs in the description of table1 before creating newtable
It also works with a more complete statement, involving indexes, engine, multiple tables, etc
create table newtable (primary key (col1)) engine=memory
select col1,col2,col3 from table1,table2 limit 0;
*Polite corrections are welcomed and appreciated if I am incorrect here, but:
My understanding is that LIMIT 0, 1000 is telling SQL that you want to start with the first set of 1000 results in a given database, for the given criteria. For example, if there are 10,000 resulting rows in a dataset, LIMIT 0, 1000 would show you the first set of 1000 results. The zero is like the index of an array in JavaScript - the code starts ITS count with zero, rather than one, when referencing an array item. So item #1 is actually item #0, item #2 is actually item #1, and so on.
In addition to the answers already given, it is also useful when you want to make operations to a table based on the number of rows present in that table.
I.e. using PHP, if you want to delete all entries except for the one with the greatest id from table "myTable":
<?php
$con = mysqli_connect("hostname", "username", "password", "database"); // Connect
$totalRows = mysqli_query($con, "SELECT COUNT(*) FROM myTable"); // Get total row count
$mysqli_query($con, "DELETE FROM myTable WHERE id >= 0 LIMIT ($totalRows - 1);"); // Delete
?>
It's really useful because if you already only have 1 row left, you'll be left with LIMIT 0, which is what you want.
I want to write a query to pull a certain set of results. While doing that I want to be able to keep a count of number of occurrences of a certain value in a certain field. I'm trying to pull a record of part-numbers from a table for devices, There are various partnumbers that are pulled from tables.
For instance this is my result set
CISCO1841
CISCO2610
CISCO2650
CISCO2610
CISCO2650
CISCO2500
I should keep track that
CISCO1841 occured one time, CISCO2610 occured twice, CISCO2650 occured twice and CISCO2500 occured once. I need to store this count and set another column value based on this count. Is there an efficient way to do this in MYSQL?
Group your query and COUNT() the results:
SELECT myColumn, COUNT(*) FROM myTable GROUP BY myColumn
See it on sqlfiddle.
You can use a trigger on the table where your data is inserted and that trigger will keep count of the occurrences by updating the counter for each word (ex : CISCO2650) in a separate table.
Or you can try a query like below but its not dynamic :
SELECT
SUM(IF(M_PART_NBR = 'CISCO2610',1,0)) as NBR1,
SUM(IF(M_PART_NBR = 'CISCO2811',1,0)) as NBR2,
SUM(IF(M_PART_NBR = 'CISCO2911',1,0)) as NBR3
FROM
C2_INST_PRODUCT WHERE M_PART_NBR LIKE '%CISCO2%'
update [db2].dbo.tblASDF
set deviceID = (select db1.deviceID FROM [database1].[dbo].[device] as db1,[database2].[dbo].[device] as db2 where db1.name = db2.name)
where exists (select * FROM [database1].[dbo].[device] as db1,[database2].[dbo].[device] as db2 where db1.name = db2.name)
Question/Statement1: It's not important that I'm selecting * in the "where exists", what's important is that my "where db1.name = db2.name" clause is returning the rows which meet this condition, because these rows hold the unique keys to help my update to operate? IE, whether I've selected one or 20 columns is irrelevant.
Question2: I'm pulling from 2 databases, db1 and db2. Does the "exists" know to use the unique keys from db1/db2 to update db2's tblASDF.deviceID column? ie, it doesn't matter that there are 2 sets of unique keys (the ones for the db1, and the ones for the db2) returned from the "where db1.name = db2.name"?
Q1 Correct.
I always do this:
if exists (select 1 from attachments WHERE ID<6) ...
To the reader, it's clearly not relevant WHAT is being returned. In this case if there are any records with an ID of less than 6, then something exists.
Q2
The WHERE Exists clause will resolve to either zero records or more than zero records.
In the first case, zero records, the UPDATE will do nothing. Because nothing exists.
In the second case, you can replace WHERE EXISTS... with nothing.
Your query resolves to
update [db2].dbo.tblASDF
set deviceID = (select db1.deviceID FROM [database1].[dbo].[device] as db1
,[database2].[dbo].[device] as db2 where db1.name = db2.name)
The inner query will not return two sets of unique keys. It will return one set of db1.deviceID IDs where the name is the same in each table.
The update will only take place where DB2's DeviceID column in its tblASDF table contains an ID that exists in DB1's equivalent table db1.deviceID in db1.tblASDF.
It will ignore the db2.deviceID column so the IDs in that field are irrelevant.
It must be said that duplicating the two identical pieces of T-SQL is unnessary and it makes the code harder to read. Often I come across SQL with a very, very subtle difference between the two pieces of code, (eg a 1 instead of a 2) thereby introducing a bug.
The "join" is being performed by the WHERE db1.name = db2.name clause
exists returns only true or false, it doesn't have anything to do with keys. Imagine it like it returns true whenever more than one row is returned from the subquery and false when 0 rows returned.
You could replace exists (select * FROM... with exists (select 1 FROM... so that you don't select any column (you can't use the data anyways).
I hope this answers your questions. Please correct me if I'm wrong :)