Fastest way to determine if record exists - sql

As the title suggests... I'm trying to figure out the fastest way with the least overhead to determine if a record exists in a table or not.
Sample query:
SELECT COUNT(*) FROM products WHERE products.id = ?;
vs
SELECT COUNT(products.id) FROM products WHERE products.id = ?;
vs
SELECT products.id FROM products WHERE products.id = ?;
Say the ? is swapped with 'TB100'... both the first and second queries will return the exact same result (say... 1 for this conversation). The last query will return 'TB100' as expected, or nothing if the id is not present in the table.
The purpose is to figure out if the id is in the table or not. If not, the program will next insert the record, if it is, the program will skip it or perform an UPDATE query based on other program logic outside the scope of this question.
Which is faster and has less overhead? (This will be repeated tens of thousands of times per program run, and will be run many times a day).
(Running this query against M$ SQL Server from Java via the M$ provided JDBC driver)

EXISTS (or NOT EXISTS) is specially designed for checking if something exists and therefore should be (and is) the best option. It will halt on the first row that matches so it does not require a TOP clause and it does not actually select any data so there is no overhead in size of columns. You can safely use SELECT * here - no different than SELECT 1, SELECT NULL or SELECT AnyColumn... (you can even use an invalid expression like SELECT 1/0 and it will not break).
IF EXISTS (SELECT * FROM Products WHERE id = ?)
BEGIN
--do what you need if exists
END
ELSE
BEGIN
--do what needs to be done if not
END

SELECT TOP 1 products.id FROM products WHERE products.id = ?; will outperform all of your suggestions as it will terminate execution after it finds the first record.

Nothing can beat -
SELECT TOP 1 1 FROM products WHERE id = 'some value';
You don't need to count to know if there is a data in table. And don't use alias when not necessary.

SELECT CASE WHEN EXISTS (SELECT TOP 1 *
FROM dbo.[YourTable]
WHERE [YourColumn] = [YourValue])
THEN CAST (1 AS BIT)
ELSE CAST (0 AS BIT) END
This approach returns a boolean for you.

Don't think anyone has mentioned it yet, but if you are sure the data won't change underneath you, you may want to also apply the NoLock hint to ensure it is not blocked when reading.
SELECT CASE WHEN EXISTS (SELECT 1
FROM dbo.[YourTable] WITH (NOLOCK)
WHERE [YourColumn] = [YourValue])
THEN CAST (1 AS BIT)
ELSE CAST (0 AS BIT) END

You can also use
If EXISTS (SELECT 1 FROM dbo.T1 WHERE T1.Name='Scot')
BEGIN
--<Do something>
END
ELSE
BEGIN
--<Do something>
END

Below is the simplest and fastest way to determine if a record exists in database or not
Good thing is it works in all Relational DB's
SELECT distinct 1 products.id FROM products WHERE products.id = ?;

SELECT COUNT(*) FROM products WHERE products.id = ?;
This is the cross relational database solution that works in all databases.

For those stumbling upon this from MySQL or Oracle background - MySQL supports the LIMIT clause to select a limited number of records, while Oracle uses ROWNUM.

For MySql you can use LIMIT like below (Example shows in PHP)
$sql = "SELECT column_name FROM table_name WHERE column_name = 'your_value' LIMIT 1";
$result = $conn->query($sql);
if ($result -> num_rows > 0) {
echo "Value exists" ;
} else {
echo "Value not found";
}

create or replace procedure ex(j in number) as
i number;
begin
select id into i from student where id=j;
if i is not null then
dbms_output.put_line('exists');
end if;
exception
when no_data_found then
dbms_output.put_line(i||' does not exists');
end;

I've used this in the past and it doesn't require a full table scan to see if something exists. It's super fast...
UPDATE TableName SET column=value WHERE column=value
IF ##ROWCOUNT=0
BEGIN
--Do work
END

SQL SERVER 2012+
SELECT IIF((SELECT TOP 1 1 FROM dbo.[YourTable] WHERE [YourColumn] = [YourValue]) IS NULL, 0, 1)

May you wanna try my way:
IF (SELECT TOP 1 1 FROM [TableName]) = 1
BEGIN
--Do work
END

Related

SQL Server Empty Result

I have a valid SQL select which returns an empty result, up and until a specific transaction has taken place in the environment.
Is there something available in SQL itself, that will allow me to return a 0 as opposed to an empty dataset? Similar to isNULL('', 0) functionality. Obviously I tried that and it didn't work.
PS. Sadly I don't have access to the database, or the environment, I have an agent installed that is executing these queries so I'm limited to solving this problem with just SQL.
FYI: Take any select and run it where the "condition" is not fulfilled (where LockCookie='777777777' for example.) If that condition is never met, the result is empty. But at some point the query will succeed based on a set of operations/tasks that happen. But I would like to return 0, up until that event has occurred.
You can store your result in a temp table and check ##rowcount.
select ID
into #T
from YourTable
where SomeColumn = #SomeValue
if ##rowcount = 0
select 0 as ID
else
select ID
from #T
drop table #T
If you want this as one query with no temp table you can wrap your query in an outer apply against a dummy table with only one row.
select isnull(T.ID, D.ID) as ID
from (values(0)) as D(ID)
outer apply
(
select ID
from YourTable
where SomeColumn = #SomeValue
) as T
alternet way is from code, you can check count of DataSet.
DsData.Tables[0].Rows.count > 0
make sure that your query matches your conditions

How to return 0 if table empty, 1 otherwise

In postgreSQL, how can i return a table containing 0 if my table is empty and a table containing 1 if my table has rows?
I need to do it in SQL, not using any other language
Use:
SELECT CASE
WHEN EXISTS (SELECT * FROM foo LIMIT 1) THEN 1
ELSE 0
END
EDIT: Added LIMIT 1 to speed up query.
Might be a hack, but it works.
SELECT count(*) FROM (SELECT 1 FROM table LIMIT 1) AS t;
The 1 selected in the sub-query could be whatever, it is just a place holder.
The LIMIT 1 should make the sub-query very fast, regardless of table-size.
Edit: Rewrote a bit. Previous use of LIMIT was wrong (didn't help on large tables as I intended).
Try:
select sign(count(*)) from mytable
maybe this is what you are looking for?
select min( c ) from (
select count(*) c
from mytab
union
select 1
from mytab
having count(*) > 1 )
SELECT, COUNT and LIMIT should do it.
-- see below SELECT COUNT(*) FROM X LIMIT 1
Edit: This doesn't work in Postgres (8.x at least). Please see the comments and here: http://postgresql.1045698.n5.nabble.com/window-function-count-and-limit-td3233588.html
Happy SQL'ing.
You can put this request in a stored procedure, with the table name as parameter :
CREATE OR REPLACE FUNCTION isEmpty(tableName text, OUT zeroIfEmpty integer) AS
$func$
BEGIN
EXECUTE format('SELECT COALESCE ((SELECT 1 FROM %s LIMIT 1),0)', tableName)
INTO zeroIfEmpty;
END
$func$ LANGUAGE plpgsql;
Then run this function like this :
SELECT * FROM isEmpty('my_table_name');
So you can call it with any of your table's name
I don't think that's possible using nothing but SQL. Why can't you use any other language?

Check whether a table contains rows or not sql server 2005

How to Check whether a table contains rows or not sql server 2005?
For what purpose?
Quickest for an IF would be IF EXISTS (SELECT * FROM Table)...
For a result set, SELECT TOP 1 1 FROM Table returns either zero or one rows
For exactly one row with a count (0 or non-zero), SELECT COUNT(*) FROM Table
Also, you can use exists
select case when exists (select 1 from table)
then 'contains rows'
else 'doesnt contain rows'
end
or to check if there are child rows for a particular record :
select * from Table t1
where exists(
select 1 from ChildTable t2
where t1.id = t2.parentid)
or in a procedure
if exists(select 1 from table)
begin
-- do stuff
end
Like Other said you can use something like that:
IF NOT EXISTS (SELECT 1 FROM Table)
BEGIN
--Do Something
END
ELSE
BEGIN
--Do Another Thing
END
FOR the best performance, use specific column name instead of * - for example:
SELECT TOP 1 <columnName>
FROM <tableName>
This is optimal because, instead of returning the whole list of columns, it is returning just one. That can save some time.
Also, returning just first row if there are any values, makes it even faster. Actually you got just one value as the result - if there are any rows, or no value if there is no rows.
If you use the table in distributed manner, which is most probably the case, than transporting just one value from the server to the client is much faster.
You also should choose wisely among all the columns to get data from a column which can take as less resource as possible.
Can't you just count the rows using select count(*) from table (or an indexed column instead of * if speed is important)?
If not then maybe this article can point you in the right direction.
Fast:
SELECT TOP (1) CASE
WHEN **NOT_NULL_COLUMN** IS NULL
THEN 'empty table'
ELSE 'not empty table'
END AS info
FROM **TABLE_NAME**

Check number of records in a database table other than count(*)

I want to check if there are any records in a table for a certain entry. I used COUNT(*) to check the number of records and got it to work. However, when the number of records for an entry is very high, my page loads slowly.
I guess COUNT(*) is causing the problem, but how do I check if the records exist without using it? I only want to check whether any records exist for the entry and then execute some code. Please help me find an alternative solution for this.
Thanks for any help.
There are several ways that may work. You can use exists, which lets the database optimise the method to get the answer:
if exists(select * from ...)
You can use top 1 so that the database can stop after finding the first match:
if (select count(*) from (select top 1 * from ...)) > 0
use select top 1 and check is there is an row
You can try selecting the first entry for given condition.
SELECT id FROM table WHERE <condition> LIMIT 1
I'm not sure if this will be quicker but you can try.
Other possible solution. How do you use count? COUNT(*)? If yes, then try using COUNT(id). As I remember this should be faster.
I would recommend testing to see if at least 1 record exists in the table, that meets your criteria then continue accordingly. For example:
IF EXISTS
(
SELECT TOP 1 Table_Name --Or Your ColumnName
FROM INFORMATION_SCHEMA.Tables -- Or your TableName
)
BEGIN
PRINT 'At least one record exists in table'
END
I found this on codeproject. It's quite handy.
-- Author,,Md. Marufuzzaman
SELECT SYS_OBJ.NAME AS "TABLE NAME"
, SYS_INDX.ROWCNT AS "ROW COUNT"
FROM SYSOBJECTS SYS_OBJ, SYSINDEXES SYS_INDX
WHERE SYS_INDX.ID = SYS_OBJ.ID
AND INDID IN(0,1) --This specifies 'user' databases only
AND XTYPE = 'U' --This omits the diagrams table of the database
--You may find other system tables will need to be ommitted,
AND SYS_OBJ.NAME <> 'SYSDIAGRAMS'
ORDER BY SYS_INDX.rowcnt DESC --I found it more useful to display
--The following line adds up all the rowcount results and places
--the final result into a separate column [below the first resulting table]
COMPUTE SUM(SYS_INDX.ROWCNT)
GO
you should use
select count(1) from
If you are saying (*) it will expand all the column's and then count

Best way to write a named SQL query that returns if row exists?

So I have this SQL query,
<named-query name="NQ::job_exists">
<query>
select 0 from dual where exists (select * from job_queue);
</query>
</named-query>
Which I plan to use like this:
Query q = em.createNamedQuery("NQ::job_exists");
List<Integer> results = q.getResultList();
boolean exists = !results.isEmpty();
return exists;
I am not very strong in SQL/JPA however, and was wondering whether there is a better way of doing it (or ways to improve it). Should I for example, write (select jq.id from job_queue jq) instead of using a star??
EDIT:This call is very performance critical in our app.
EDIT:Did some performance testing, and while the differences were almost negligible, I finally decided to go with:
select distinct null
from dual
where exists (
select null from job_queue
);
IF you are using EXISTS Oracle I recommend using null:
select null
from dual where exists (select null from job_queue);
The following will be the one with lower cost on Oracle:
select null
from job_queue
where rownum = 1;
Update: To include the case when there are no rows on table you can run the following query:
select count(*)
from (select null
from job_queue
where rownum = 1);
With this query you have a optimum plan and only two possible results: 1 if there are rows and 0 if there are no rows.
If you do an "exists" then it will stop looking as soon as it finds a match. This can stop it from doing a full table scan. Same with TOP 1 if you don't have an ORDER BY. If you do a TOP 1 ID and ID is in an index it might use the index and not even go to the table at all. Stopping the full table scan is where the biggest saving in performance is.
Another small savings is that if you do "SELECT 1" or "SELECT COUNT(1)" instead of "SELECT * " or "SELECT COUNT(*)" it saves the work of getting the table structure.
So I would go with:
SELECT TOP 1 1 AS Found
FROM job_queue
Then:
return !results.isEmpty();
This is the least amount of work that I can think of.
For Oracle it would be:
SELECT 1
FROM job_queue
WHERE rownum<2;
Or:
Set Rowcount 1
SELECT 1
FROM job_queue
Why not just do:
select count(*) as JobCount from job_queue
If JobCount = 0, then there's your answer!