Select data where condition matches and if none, then select all? - sql

select * from (values
('dept1','user1'),
('dept2','user2'),
('dept3','user3'),
('dept4','user4')
)table1([department],[user])
where [user] = #id
scenario1:
#id = 'user1'
dept1
scenario2:
#id = 'user5'
dept1
dept2
dept3
dept4
this is what it looks like from a noobish query
declare #id varchar(12) = 'user1'
declare #var int = (select count(*) from table1 where [user] = #id)
select * from table1 where [user] = #id or #var = 0

DECLARE #id VARCHAR(5) = 'user1';
--DECLARE #id VARCHAR(5) = 'user5';
WITH UsersAndDepartments
AS ( SELECT *
FROM ( VALUES ( 'dept1', 'user1'), ( 'dept2', 'user2'),
( 'dept3', 'user3'), ( 'dept4', 'user4') ) x ( [department], [user] )
)
SELECT *
FROM UsersAndDepartments ud1
WHERE ud1.[user] =
CASE
WHEN EXISTS ( SELECT 1 FROM UsersAndDepartments ud2 WHERE ud2.[user] = #id ) THEN #id
ELSE ud1.[user]
END
The above just checks on user column if any row exists for an id, else matches on all.

declare #tab table (id int , value varchar(10))
declare #id int = 4
insert into #tab
select 1,'Ajay'
union all
select 2,'Ajay1'
union all
select 3,'Ajay2'
union all
select 4,'Ajay3'
union all
select 5,'Ajay4'
select * from #tab
where id = case when exists (select * from #tab where id = #id) then #id else id end

I would do this with a simple OR, not a CASE expression in the WHERE.
In general, you want to avoid CASE expressions in the WHERE clause for several reasons:
The logic can almost be written concisely using basic boolean operations.
Adding additional constructs (in addition to AND, OR, and NOT) just makes the logic harder for people to follow.
It pretty much kills any optimization paths.
I would suggest:
with table1 as
select v.*
from (values ('dept1', 'user1'),
('dept2', 'user2'),
('dept3', 'user3'),
('dept4', 'user4')
) v([department], [user])
)
select t1.*
from table1 t1
where t1.[user] = #id or
not exists (select 1 from table1 t1 where t1.user = #id);

You may have to do a check first something like this
Declare #RowCount int
Select #RowCount = (select count(*) from [Table] Where [Column] = 'xxx')
If #RowCount > 0
begin
Select 1 -- put code here if records
end
else
begin
Select 2 -- put code here if no records
end

you can try this:
DECLARE #id varchar(12) = 'user1'
IF EXISTS(SELECT COUNT(*) FROM table1 WHERE [user] = #id)
BEGIN
SELECT * FROM table1 WHERE [user] = #id
END
ELSE
BEGIN
SELECT * FROM table1
END
you can also read more about "EXISTS" syntax on:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/exists-transact-sql?view=sql-server-2017

You can have a slightly better execution plan if you separate the "if exist" logic from the actual query:
DECLARE #id varchar(10) = 'user5'
DECLARE #table TABLE ([department] varchar(10), [user] varchar(10))
insert into #table values
('dept1','user1'),
('dept2','user2'),
('dept3','user3'),
('dept4','user4')
DECLARE #exists BIT =
(SELECT 1 FROM #table WHERE [user] = #id)
SELECT department FROM #table
WHERE [user] = CASE #exists WHEN 1 THEN #id ELSE [user] END

Related

While loop taking so much time in SQL Server

In my stored procedure, I have 2 while loops and I need to avoid those loops and use cursor or recursive cte
create procedure Parent_Child_UserDetails_Schedule
as
begin
Set nocount on
create table #temptab(id int, userid int, parentid int)
select userid, 1 as valid
into #users
from userdetails
where isactive = 1
truncate table Parent_Child_UserDetails
while(select count(*) from #users where valid = 1) > 0
begin
declare #userid int
select top 1 #userid = userid
from #users
where valid = 1
truncate table #temptab
insert into #temptab(id, userid, parentid)
values(1, #userid, #userid)
declare #id int
set #id = 1
while((select count(*) from userdetails
where parentid in (select userid from #temptab where id=#id ) and isactive = 1) > 0)
begin
insert into #temptab (id, userid, parentid)
select #id + 1, userid, #userid
from userdetails
where parentid in (select userid from #temptab where id = #id)
and isactive = 1
set #id= #id + 1
end
insert into Parent_Child_UserDetails(Parentid, Userid)
select parentid, userid
from #temptab
update #users
set valid = 0
where userid = #userid
end
drop table #temptab
drop table #users
Set nocount off
end
Please help me .....
Following our conversation in the comments, what you need is to insert to the Parent_Child_UserDetails table all the parent ids and user ids where both are active,
you can replace that RBAR nightmare of a code with a single insert....select statement, like this:
insert into Parent_Child_UserDetails(Parentid, Userid)
select parentid, userid
from userdetails as t0
where isactive = 1
and exists
(
select 1
from userdetails as t1
where t1.isavtice = 1
and t1.userId = t0.ParentId
)

Outer apply with INSERT statement

I want to do something like this
CREATE TABLE #tempFacilitiesAssociated
(
FacilityID BIGINT,
FacilityName VARCHAR(MAX),
IsPrimary BIT
)
-- Insert statements for procedure here
;WITH CTE_RESULT AS
(
SELECT
usr_id, t.name AS Title,
usr_fname, usr_lname, primaryAddress.add_suburb,
CASE
WHEN primaryAddress.add_suburb = #suburb THEN 1
WHEN t.name = #Title THEN 2
ELSE 3
END AS MatchOrder
FROM
core_users u
LEFT JOIN
RIDE_ct_title t ON t.title_id = u.usr_title
OUTER APPLY
(INSERT INTO #tempFacilitiesAssociated
EXEC dbo.[sp_Common_Get_AllFacilitiesForSupervisor] usr_id, 5
SELECT TOP 1 fa.*
FROM CORE_Facilities f
LEFT JOIN CORE_FacilityAddresses fa ON fac_id = fa.add_owner
WHERE fac_id = (SELECT TOP 1 FacilityID
FROM #tempFacilitiesAssociated
WHERE IsPrimary = 1)) primaryAddress
WHERE
u.usr_fname = #FirstName AND usr_lname = #LastName
)
So, first I want to get all facilities of that user through a stored procedure, and then use it to outer apply and select its suburb
UPDATE
I tried using function instead
CREATE FUNCTION fn_GetAddressForUserFacility
(#UserID BIGINT)
RETURNS #Address TABLE (FacilityID BIGINT,
add_address NVARCHAR(MAX),
add_addressline2 NVARCHAR(MAX),
add_suburb NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #FacilitiesAssociated TABLE
(FacilityID BIGINT,
FacilityName NVARCHAR(MAX),
IsPrimary BIT)
INSERT INTO #FacilitiesAssociated
EXEC dbo.[sp_Common_Get_AllFacilitiesForSupervisor] #UserID, 5
INSERT INTO #Address
SELECT TOP 1
fa.add_owner, fa.add_address, fa.add_addressline2, fa.add_suburb
FROM
CORE_Facilities f
LEFT JOIN
CORE_FacilityAddresses fa ON f.fac_id = fa.add_owner AND add_type = 5
WHERE
fac_id = (SELECT TOP 1 FacilityID
FROM #FacilitiesAssociated
WHERE IsPrimary = 1)
RETURN
END
But now its returning
Invalid use of a side-effecting operator 'INSERT EXEC' within a function.

Subquery in ISNULL,IIF,CASE statements

Subquery that is give as a parameter in ISNULL or IIF or CASE gets executed irrespective of the condition
To explain what I mean, consider the below example. When I run the below query and look in the execution plan, I find that even if the variable #Id not NULL, the second condition gets executed always.
Can anyone explain Why does the subquery gets executed in Query 1,2,3?
--Create a Temp table
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL DROP TABLE #TempTable
CREATE TABLE #TempTable
(
ID INT
)
--Insert some data
INSERT INTO #TempTable VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
DECLARE #Id INT = 1
--Query 1: ISNULL
SET #Id= ISNULL(#Id, (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1))
SELECT #Id AS ID
--Query 2: IIF
SET #Id= IIF(#Id IS NULL,(SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1),#Id)
SET #Id= IIF(#Id IS NOT NULL,#Id,(SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1))
SELECT #Id AS ID
--Query 3: CASE
SET #Id= CASE WHEN #Id IS NULL THEN (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1) ELSE #Id END
SET #Id= CASE WHEN #Id IS NOT NULL THEN #Id ELSE (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1) END
SELECT #Id AS ID
---Query 4: IF
IF #Id IS NULL
BEGIN
SET #Id = (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1)
SELECT #Id AS ID
END
ELSE
BEGIN
SELECT #Id AS ID
END
If you want the subquery to execute only when the null condition is met, use an IF instead of ISNULL
if #Id is null
set #id = (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1)
instead of
SET #Id= ISNULL(#Id, (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1))

Subquery returned more than one value error

I am using the following query, but it is throwing an error. It is working fine for some scenarios, depending on the id, but not for all.
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
Set #NoOfRows = (Select COUNT(*) from #TempT)
While #i <= #NoOfRows
Begin
SET #Voucher_No=( select V_No from #TempT where RowID=#i)
SET #Voucher_Type_No=( select voucher_type_no from #TempT where RowID=#i)
SET #Voucher_Id=( select Voucher_Id from #TempT where RowID=#i)
set #strPartyName=''
set #strPartyName = (Select Party_Name from Cheque_Book where Voucher_No= #Voucher_No and Voucher_Type_No= #Voucher_Type_No and Company_No= #Comp_No and Bank_Account_No= #dbc_Account )
if NULLIF(#strPartyName,'') IS NULL
begin
set #strPartyName =(Select a.account_name from Voucher v inner join account a on v.Account_No = a.account_No where v.Voucher_Id= #Voucher_Id)
Update #TempT Set Party_Name =#strPartyName Where RowID =#i
set #i=#i+1
end
End
Select * from #TempT
Rather than setting variable using sub-query, set variable as shown below.
SELECT #NoOfRows = COUNT(*) FROM #TempT
WHILE #i <= #NoOfRows
BEGIN
SELECT #Voucher_No = V_No FROM #TempT WHERE RowID=#i
SELECT #Voucher_Type_No = voucher_type_no FROM #TempT WHERE RowID=#i
SELECT #Voucher_Id = Voucher_Id FROM #TempT where RowID=#i
SET #strPartyName=''
SELECT #strPartyName = Party_Name FROM Cheque_Book WHERE Voucher_No = #Voucher_No AND Voucher_Type_No = #Voucher_Type_No AND Company_No= #Comp_No AND Bank_Account_No= #dbc_Account
IF NULLIF(#strPartyName,'') IS NULL
BEGIN
SELECT #strPartyName = a.account_name FROM Voucher v INNER JOIN account a ON v.Account_No = a.account_No WHERE v.Voucher_Id= #Voucher_Id
UPDATE #TempT SET Party_Name = #strPartyName WHERE RowID = #i
SET #i = #i + 1
END
END
SELECT * FROM #TempT
Its show that your sub-query return more than one value.
You have to modify your sub-query with TOP keyword or give filter (where condition and order by ) more which return only one value.
While #i <= #NoOfRows
Begin
SET #Voucher_No=( select top 1 V_No from #TempT where RowID=#i)
SET #Voucher_Type_No=( select top 1 voucher_type_no from #TempT where RowID=#i)
SET #Voucher_Id=( select top1 Voucher_Id from #TempT where RowID=#i)
......
END
To resolve the problem, you just only run the actual select query in while loop which gives the result of more than 2 value like
While #i <= #NoOfRows
Begin
--SET #Voucher_No=(
select V_No from #TempT where RowID=#i --)
--SET #Voucher_Type_No=(
select voucher_type_no from #TempT where RowID=#i --)
--SET #Voucher_Id=(
select Voucher_Id from #TempT where RowID=#i --)
......
END
UPDATED
This is sample data to understand what happened with you and how to resolve it.
declare #department table (deptid int, name varchar(50))
declare #emp table (id int, name varchar(50), deptid int)
insert into #department values (1,'d1'), (2,'d2'),(3,'d3'),(4,'d4')
insert into #emp values(1,'ajay',1), (2,'ajay1',1),(3,'ajay3' ,2),(4,'ajay4' ,3),(5,'ajay5' ,4)
select * from #department where deptid = 1
/* suppose your sub-query like */
--1. this give result
select * from #department where deptid = (select deptid from #emp where id = 1)
--2. this give result, but may be get wrong result as it take top 1.
select * from #department where deptid = (select top 1 deptid from #emp )
--3. this give error same you have
select * from #department where deptid = (select deptid from #emp)
--to resolve the above error, just uncomment below sub-query.
--select deptid from #emp
I see answers here for the issue where the following queries fail because their subqueries return multiple values:
SET #Voucher_No = (SELECT [V_No] FROM #TempT WHERE [RowID] = #i);
SET #Voucher_Type_No = (SELECT [voucher_type_no] FROM #TempT WHERE [RowID] = #i);
SET #Voucher_Id = (SELECT [Voucher_Id] FROM #TempT WHERE [RowID] = #i);
There are mainly two proposed solutions in those answers:
SET #Variable = (SELECT TOP (1) [Field] FROM [Table] WHERE ...);, or
SELECT #Variable = [Field] FROM [Table] WHERE ...);.
To my surprise, the second approach is considered to be the preferred approach. There are a few important things to consider, however.
First: if the SELECT-query returns multiple results, the value of #Variable will become the last retrieved value from the query's result set. This has to be regarded when an ORDER BY clause is specified.
So the query below will return 5 instead of 1:
DECLARE #TempTable TABLE ([ID] INT);
INSERT INTO #TempTable VALUES (1), (3), (2), (5), (4);
DECLARE #Variable INT = 42;
SELECT #Variable = [ID] FROM #TempTable ORDER BY [ID];
SELECT #Variable AS [#Variable];
Second: if #Variable already contains a value and the SELECT query does not produce any results (0 rows), the value of #Variable remains unchanged!
So the query below will produce result 42 instead of NULL:
DECLARE #TempTable TABLE ([ID] INT);
INSERT INTO #TempTable VALUES (1), (3), (2), (5), (4);
DECLARE #Variable INT = 42;
SELECT #Variable = [ID] FROM #TempTable WHERE [ID] = 6;
SELECT #Variable AS [#Variable];
For all these reasons, my personal preference lies with the SET #Variable = (SELECT TOP (1) ...) approach.

SQL query to find Missing sequence numbers

I have a column named sequence. The data in this column looks like 1, 2, 3, 4, 5, 7, 9, 10, 15.
I need to find the missing sequence numbers from the table. What SQL query will find the missing sequence numbers from my table? I am expecting results like
Missing numbers
---------------
6
8
11
12
13
14
I am using only one table. I tried the query below, but am not getting the results I want.
select de.sequence + 1 as sequence from dataentry as de
left outer join dataentry as de1 on de.sequence + 1 = de1.sequence
where de1.sequence is null order by sequence asc;
How about something like:
select (select isnull(max(val)+1,1) from mydata where val < md.val) as [from],
md.val - 1 as [to]
from mydata md
where md.val != 1 and not exists (
select 1 from mydata md2 where md2.val = md.val - 1)
giving summarised results:
from to
----------- -----------
6 6
8 8
11 14
I know this is a very old post but I wanted to add this solution that I found HERE so that I can find it easier:
WITH Missing (missnum, maxid)
AS
(
SELECT 1 AS missnum, (select max(id) from #TT)
UNION ALL
SELECT missnum + 1, maxid FROM Missing
WHERE missnum < maxid
)
SELECT missnum
FROM Missing
LEFT OUTER JOIN #TT tt on tt.id = Missing.missnum
WHERE tt.id is NULL
OPTION (MAXRECURSION 0);
Try with this:
declare #min int
declare #max int
select #min = min(seq_field), #max = max(seq_field) from [Table]
create table #tmp (Field_No int)
while #min <= #max
begin
if not exists (select * from [Table] where seq_field = #min)
insert into #tmp (Field_No) values (#min)
set #min = #min + 1
end
select * from #tmp
drop table #tmp
The best solutions are those that use a temporary table with the sequence. Assuming you build such a table, LEFT JOIN with NULL check should do the job:
SELECT #sequence.value
FROM #sequence
LEFT JOIN MyTable ON #sequence.value = MyTable.value
WHERE MyTable.value IS NULL
But if you have to repeat this operation often (and more then for 1 sequence in the database), I would create a "static-data" table and have a script to populate it to the MAX(value) of all the tables you need.
SELECT CASE WHEN MAX(column_name) = COUNT(*)
THEN CAST(NULL AS INTEGER)
-- THEN MAX(column_name) + 1 as other option
WHEN MIN(column_name) > 1
THEN 1
WHEN MAX(column_name) <> COUNT(*)
THEN (SELECT MIN(column_name)+1
FROM table_name
WHERE (column_name+ 1)
NOT IN (SELECT column_name FROM table_name))
ELSE NULL END
FROM table_name;
Here is a script to create a stored procedure that returns missing sequential numbers for a given date range.
CREATE PROCEDURE dbo.ddc_RolledBackOrders
-- Add the parameters for the stored procedure here
#StartDate DATETIME ,
#EndDate DATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Min BIGINT
DECLARE #Max BIGINT
DECLARE #i BIGINT
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
BEGIN
DROP TABLE #TempTable
END
CREATE TABLE #TempTable
(
TempOrderNumber BIGINT
)
SELECT #Min = ( SELECT MIN(ordernumber)
FROM dbo.Orders WITH ( NOLOCK )
WHERE OrderDate BETWEEN #StartDate AND #EndDate)
SELECT #Max = ( SELECT MAX(ordernumber)
FROM dbo.Orders WITH ( NOLOCK )
WHERE OrderDate BETWEEN #StartDate AND #EndDate)
SELECT #i = #Min
WHILE #i <= #Max
BEGIN
INSERT INTO #TempTable
SELECT #i
SELECT #i = #i + 1
END
SELECT TempOrderNumber
FROM #TempTable
LEFT JOIN dbo.orders o WITH ( NOLOCK ) ON tempordernumber = o.OrderNumber
WHERE o.OrderNumber IS NULL
END
GO
Aren't all given solutions way too complex?
wouldn't this be much simpler:
SELECT *
FROM (SELECT row_number() over(order by number) as N from master..spt_values) t
where N not in (select 1 as sequence union
select 2 union
select 3 union
select 4 union
select 5 union
select 7 union
select 10 union
select 15
)
This is my interpretation of this issue, placing the contents in a Table variable that I can easily access in the remainder of my script.
DECLARE #IDS TABLE (row int, ID int)
INSERT INTO #IDS
select ROW_NUMBER() OVER (ORDER BY x.[Referred_ID]), x.[Referred_ID] FROM
(SELECT b.[Referred_ID] + 1 [Referred_ID]
FROM [catalog].[dbo].[Referrals] b) as x
LEFT JOIN [catalog].[dbo].[Referrals] a ON x.[Referred_ID] = a.[Referred_ID]
WHERE a.[Referred_ID] IS NULL
select * from #IDS
Just for fun, I decided to post my solution.
I had an identity column in my table and I wanted to find missing invoice numbers.
I reviewed all the examples I could find but they were not elegant enough.
CREATE VIEW EENSkippedInvoicveNo
AS
SELECT CASE WHEN MSCNT = 1 THEN CAST(MSFIRST AS VARCHAR (8)) ELSE
CAST(MSFIRST AS VARCHAR (8)) + ' - ' + CAST(MSlAST AS VARCHAR (8)) END AS MISSING,
MSCNT, INV_DT FROM (
select invNo+1 as Msfirst, inv_no -1 as Mslast, inv_no - invno -1 as msCnt, dbo.fmtdt(Inv_dt) AS INV_dT
from (select inv_no as invNo, a4glidentity + 1 as a4glid
from oehdrhst_sql where inv_dt > 20140401) as s
inner Join oehdrhst_sql as h
on a4glid = a4glidentity
where inv_no - invno <> 1
) AS SS
DECLARE #MaxID INT = (SELECT MAX(timerecordid) FROM dbo.TimeRecord)
SELECT SeqID AS MissingSeqID
FROM (SELECT ROW_NUMBER() OVER (ORDER BY column_id) SeqID from sys.columns) LkUp
LEFT JOIN dbo.TimeRecord t ON t.timeRecordId = LkUp.SeqID
WHERE t.timeRecordId is null and SeqID < #MaxID
I found this answer here:
http://sql-developers.blogspot.com/2012/10/how-to-find-missing-identitysequence.html
I was looking for a solution and found many answers. This is the one I used and it worked very well. I hope this helps anyone looking for a similar answer.
-- This will return better Results
-- ----------------------------------
;With CTERange
As (
select (select isnull(max(ArchiveID)+1,1) from tblArchives where ArchiveID < md.ArchiveID) as [from],
md.ArchiveID - 1 as [to]
from tblArchives md
where md.ArchiveID != 1 and not exists (
select 1 from tblArchives md2 where md2.ArchiveID = md.ArchiveID - 1)
) SELECT [from], [to], ([to]-[from])+1 [total missing]
From CTERange
ORDER BY ([to]-[from])+1 DESC;
from to total missing
------- ------- --------------
6 6 1
8 8 1
11 14 4
DECLARE #TempSujith TABLE
(MissingId int)
Declare #Id Int
DECLARE #mycur CURSOR
SET #mycur = CURSOR FOR Select Id From tbl_Table
OPEN #mycur
FETCH NEXT FROM #mycur INTO #Id
Declare #index int
Set #index = 1
WHILE ##FETCH_STATUS = 0
BEGIN
if (#index < #Id)
begin
while #index < #Id
begin
insert into #TempSujith values (#index)
set #index = #index + 1
end
end
set #index = #index + 1
FETCH NEXT FROM #mycur INTO #Id
END
Select Id from tbl_Table
select MissingId from #TempSujith
Create a useful Tally table:
-- can go up to 4 million or 2^22
select top 100000 identity(int, 1, 1) Id
into Tally
from master..spt_values
cross join master..spt_values
Index it, or make that single column as PK.
Then use EXCEPT to get your missing number.
select Id from Tally where Id <= (select max(Id) from TestTable)
except
select Id from TestTable
You could also solve using something like a CTE to generate the full sequence:
create table #tmp(sequence int)
insert into #tmp(sequence) values (1)
insert into #tmp(sequence) values (2)
insert into #tmp(sequence) values (3)
insert into #tmp(sequence) values (5)
insert into #tmp(sequence) values (6)
insert into #tmp(sequence) values (8)
insert into #tmp(sequence) values (10)
insert into #tmp(sequence) values (11)
insert into #tmp(sequence) values (14)
DECLARE #max INT
SELECT #max = max(sequence) from #tmp;
with full_sequence
(
Sequence
)
as
(
SELECT 1 Sequence
UNION ALL
SELECT Sequence + 1
FROM full_sequence
WHERE Sequence < #max
)
SELECT
full_sequence.sequence
FROM
full_sequence
LEFT JOIN
#tmp
ON
full_sequence.sequence = #tmp.sequence
WHERE
#tmp.sequence IS NULL
Hmmmm - the formatting is not working on here for some reason? Can anyone see the problem?
i had made a proc so you can send the table name and the key and the result is a list of missing numbers from the given table
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create PROCEDURE [dbo].[action_FindMissing_Autoincremnt]
(
#tblname as nvarchar(50),
#tblKey as nvarchar(50)
)
AS
BEGIN
SET NOCOUNT ON;
declare #qry nvarchar(4000)
set #qry = 'declare #min int '
set #qry = #qry + 'declare #max int '
set #qry = #qry +'select #min = min(' + #tblKey + ')'
set #qry = #qry + ', #max = max('+ #tblKey +') '
set #qry = #qry + ' from '+ #tblname
set #qry = #qry + ' create table #tmp (Field_No int)
while #min <= #max
begin
if not exists (select * from '+ #tblname +' where '+ #tblKey +' = #min)
insert into #tmp (Field_No) values (#min)
set #min = #min + 1
end
select * from #tmp order by Field_No
drop table #tmp '
exec sp_executesql #qry
END
GO
SELECT TOP 1 (Id + 1)
FROM CustomerNumberGenerator
WHERE (Id + 1) NOT IN ( SELECT Id FROM CustomerNumberGenerator )
Working on a customer number generator for my company. Not the most efficient but definitely most readable
The table has one Id column.
The table allows for Ids to be inserted at manually by a user off sequence.
The solution solves the case where the user decided to pick a high number