SQL server updating records where they exist - sql-server-2008

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 :)

Related

Query to see if row exists based on data without selecting fields

So i know how to check a row exists from a set of data. But a lot of examples i find entails selecting a row and bunch of fields - something i don't need in this case.
In my case i just need to know it exists. I was wondering if there is a way to check a row exists without selecting/getting the row since thats some what redundant data ?
If not i will stick to using my SELECT id approach but wanted to see if i had missed a better approach just to ping the existence of a row.
Currently i am doing:
SELECT uid FROM users WHERE sessionID = ? AND uid = ?
Then i am checking if row count is == 1 afterwards. But i am still needlessly getting uid which i already technically have. It seems inefficient. So perhaps there is a better way built into mySQL?
You can do:
select (exists (select 1 from t) ) as exists_flag
This returns 1 if the row exists or 0 if no row exists. You can add a where clause to the subquery if you want a particular row.

Trying to avoid duplicate SQL entries

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.

Check what table a record belongs in using MySQL

I have a requirement to check what table a record belongs in out of 2 tables and set a variable depending on the returned table.
e.g. I have 2 tables (tbl_registered_users, tbl_unregistered_users). If I search for an email address that existed in tbl_registered_users I would like the query to return 'tbl_registered_users' so I can set a variable $whatTable = ... (for example).
I know I could do this with 2 queries or even 1 if I can guarantee the record will exist in at least one table however I would potentially like to use the query on 3/4/5/10 tables and on records that may not exist in any.
Thanks
You can use a UNION for that with a subquery:
SELECT *
FROM (
SELECT 'Registered' WhichTable, Email
FROM tbl_registered_users
UNION
SELECT 'UnRegistered', Email
FROM tbl_unregistered_users
) t
WHERE Email = 'emailaddress'
SQL Fiddle Demo
Using UNION ALL would yield a better performance, but it won't remove duplicates (in case you have duplicated data in either single table).

What does it mean by select 1 from table?

I have seen many queries with something as follows.
Select 1
From table
What does this 1 mean, how will it be executed and, what will it return?
Also, in what type of scenarios, can this be used?
select 1 from table will return the constant 1 for every row of the table. It's useful when you want to cheaply determine if record matches your where clause and/or join.
SELECT 1 FROM TABLE_NAME means, "Return 1 from the table". It is pretty unremarkable on its own, so normally it will be used with WHERE and often EXISTS (as #gbn notes, this is not necessarily best practice, it is, however, common enough to be noted, even if it isn't really meaningful (that said, I will use it because others use it and it is "more obvious" immediately. Of course, that might be a viscous chicken vs. egg issue, but I don't generally dwell)).
SELECT * FROM TABLE1 T1 WHERE EXISTS (
SELECT 1 FROM TABLE2 T2 WHERE T1.ID= T2.ID
);
Basically, the above will return everything from table 1 which has a corresponding ID from table 2. (This is a contrived example, obviously, but I believe it conveys the idea. Personally, I would probably do the above as SELECT * FROM TABLE1 T1 WHERE ID IN (SELECT ID FROM TABLE2); as I view that as FAR more explicit to the reader unless there were a circumstantially compelling reason not to).
EDIT
There actually is one case which I forgot about until just now. In the case where you are trying to determine existence of a value in the database from an outside language, sometimes SELECT 1 FROM TABLE_NAME will be used. This does not offer significant benefit over selecting an individual column, but, depending on implementation, it may offer substantial gains over doing a SELECT *, simply because it is often the case that the more columns that the DB returns to a language, the larger the data structure, which in turn mean that more time will be taken.
If you mean something like
SELECT * FROM AnotherTable
WHERE EXISTS (SELECT 1 FROM table WHERE...)
then it's a myth that the 1 is better than
SELECT * FROM AnotherTable
WHERE EXISTS (SELECT * FROM table WHERE...)
The 1 or * in the EXISTS is ignored and you can write this as per Page 191 of the ANSI SQL 1992 Standard:
SELECT * FROM AnotherTable
WHERE EXISTS (SELECT 1/0 FROM table WHERE...)
it does what it says - it will always return the integer 1. It's used to check whether a record matching your where clause exists.
select 1 from table is used by some databases as a query to test a connection to see if it's alive, often used when retrieving or returning a connection to / from a connection pool.
The result is 1 for every record in the table.
To be slightly more specific, you would use this to do
SELECT 1 FROM MyUserTable WHERE user_id = 33487
instead of doing
SELECT * FROM MyUserTable WHERE user_id = 33487
because you don't care about looking at the results. Asking for the number 1 is very easy for the database (since it doesn't have to do any look-ups).
Although it is not widely known, a query can have a HAVING clause without a GROUP BY clause.
In such circumstances, the HAVING clause is applied to the entire set. Clearly, the SELECT clause cannot refer to any column, otherwise you would (correct) get the error, "Column is invalid in select because it is not contained in the GROUP BY" etc.
Therefore, a literal value must be used (because SQL doesn't allow a resultset with zero columns -- why?!) and the literal value 1 (INTEGER) is commonly used: if the HAVING clause evaluates TRUE then the resultset will be one row with one column showing the value 1, otherwise you get the empty set.
Example: to find whether a column has more than one distinct value:
SELECT 1
FROM tableA
HAVING MIN(colA) < MAX(colA);
If you don't know there exist any data in your table or not, you can use following query:
SELECT cons_value FROM table_name;
For an Example:
SELECT 1 FROM employee;
It will return a column which contains the total number of rows & all rows have the same constant value 1 (for this time it returns 1 for all rows);
If there is no row in your table it will return nothing.
So, we use this SQL query to know if there is any data in the table & the number of rows indicates how many rows exist in this table.
If you just want to check a true or false based on the WHERE clause, select 1 from table where condition is the cheapest way.
This means that You want a value "1" as output or Most of the time used as Inner Queries because for some reason you want to calculate the outer queries based on the result of inner queries.. not all the time you use 1 but you have some specific values...
This will statically gives you output as value 1.
I see it is always used in SQL injection,such as:
www.urlxxxxx.com/xxxx.asp?id=99 union select 1,2,3,4,5,6,7,8,9 from database;
These numbers can be used to guess where the database exists and guess the column name of the database you specified.And the values of the tables.
it simple means that you are retrieving the number first column from table ,,,,means
select Emply_num,Empl_no From Employees ;
here you are using select 1 from Employees;
that means you are retrieving the Emply_num column.
Thanks
The reason is another one, at least for MySQL. This is from the MySQL manual
InnoDB computes index cardinality values for a table the first time that table is accessed after startup, instead of storing such values in the table. This step can take significant time on systems that partition the data into many tables. Since this overhead only applies to the initial table open operation, to “warm up” a table for later use, access it immediately after startup by issuing a statement such as SELECT 1 FROM tbl_name LIMIT 1
This is just used for convenience with IF EXISTS(). Otherwise you can go with
select * from [table_name]
Image In the case of 'IF EXISTS', we just need know that any row with specified condition exists or not doesn't matter what is content of row.
select 1 from Users
above example code, returns no. of rows equals to no. of users with 1 in single column

Mysql Joins - How to know which row is retrieved from which table...?

Consider i am using join on three tables to get a desired result-set...
Now in that result set, is there anyway that i can find out which row comes from which table...?
Update :
I see that i have phrased the question rather wrongly.... As pointed in one of the answers below, a result-set returned by join may will contain a row made up columns from multiple talbes...
So the question should actually be "Consider i am using union on three tables to get a desired result-set..."
You can add a table identifier column to each:
select 'A' as table_name, col1, col2 from A
union
select 'B' as table_name, col1, col2 from B
union
...
This returns a single result set which is handled by your application as any ordinary select statement:
while ( rows available ) {
row = fetchrow
if row.table_name == 'A' then
do special handling for table A
else if row.table_name == 'B' then
do special handling for table B
else if ...
}
The actual syntax is dependent on the language you are using, but most procedural languages follow the scheme above.
If you are asking this question, then your database is probably not structured correctly. (correctly being a subjective term).
A proper SQL query on a normalized database should not depend, nor be concerned with, where the data comes from.
Each row would be a combination of all tables, with null values being inserted in columns for left/right/outer joins which do not match the joining criteria. You could perhaps test if a column (from a particular table) is null, and derive from that that the non-null values must originate from the opposite table(s).
Then again, if you were actually performing an UNION, as Marcelo suggested, you would have to look at ancillary columns to determine the source of the data, as that information is lost in the combination.