iterative loop to select row - sql

I need to be able to SELECT a specific row because SET only holds one row.
On line 5, I have to declare #json so that OPENJSON can work.
And that's why i need the RowNo at this point in the query. However, at this point, RowNo is not defined.
How would i go about fixing this problem? It seems that it doesn't matter how i spin it, something is always gonna be undefined. How would i point to a specific row on line 5 as desired?
DECLARE #loopCounter INT = 0;
WHILE #loopCounter < (SELECT count(Id) FROM ProcessEventMessages)
BEGIN
PRINT 'Changing...';
DECLARE #json NVARCHAR(MAX) = (SELECT Data FROM ProcessEventMessages WHERE RowNo = #loopCounter) -- here
SELECT * FROM OPENJSON(#json)
WITH (
message varchar(200) '$.message',
machineId varchar(200) '$.machineId',
machineName int '$.machineName',
ipAddress varchar(200) '$.ipAddress',
LocalTime datetime2(7) '$.time'
) AS ChangeTime;
;WITH CTE AS(
SELECT *,ROW_NUMBER() OVER(Order by Id ASC) AS RowNo
FROM ProcessEventMessages
)
UPDATE CTE
SET Data = JSON_MODIFY(#json,'$.time', FORMAT(DATEADD(hour,-2,JSON_VALUE(#json,'$.time')),'yyyy-MM-ddTHH:mm:ss.fff'))
WHERE RowNo = #loopCounter
SET #loopCounter = #loopCounter + 1;
END;
PRINT 'Done';
GO

You can use CROSS APPLY instead of a loop. Try:
WITH CTE AS (
SELECT
LocalTime
, Data
FROM dbo.ProcessEventMessages
CROSS APPLY OPENJSON(Data)
WITH (
LocalTime datetime2(7) '$.time'
) AS ChangeTime
)
UPDATE CTE
SET Data = JSON_MODIFY(Data,'$.time', FORMAT(DATEADD(hour,-2,LocalTime),'yyyy-MM-ddTHH:mm:ss.fff'));

Related

Cursor in SQL Server: Use loop / condition to find and replace a value

I have a issue with my table in SQL Server. Sometime during a insert a normal value (20-50-80) changed by 1000000. It's really rare but to secure the average i need to make a fix before finding a new solution.
I want to take the value that exceeds 1000000 and replace them by the average of the value between it.
This picture show the problem.
I'm looking at the Cursor in SQL.
Here a exemple of my code. Some issue about the result.
CREATE PROCEDURE [dbo].[Avg_Kwh_TagValuesArchive]
AS
BEGIN
DECLARE #tagId INT
DECLARE #localTime DATE
DECLARE #tagValue FLOAT
DECLARE #limit FLOAT
DECLARE #temp FLOAT
DECLARE #tagValueBefore FLOAT
DECLARE #tagValueAfter FLOAT
SET #limit = 999999.9
DECLARE Cursor_FalseValues CURSOR
FOR
SELECT TagID, LocalTime, TagValue
FROM TagValuesArchive
ORDER BY LocalTime DESC
OPEN Cursor_FalseValues
FETCH Cursor_FalseValues
INTO #tagId, #localTime, #tagValue
WHILE(##FETCH_STATUS = 0)
BEGIN
IF (#tagValue>=#limit)
BEGIN
SET #tagValueBefore =
(
SELECT TOP 1 TagValue
FROM TagValuesArchive
WHERE LocalTime < #localTime
AND TagID = #tagID
AND TagValue IS NOT NULL
ORDER BY LocalTime DESC
)
SET #tagValueAfter =
(
SELECT TOP 1 TagValue
FROM TagValuesArchive
WHERE LocalTime > #localTime
AND TagID = #tagID
AND TagValue IS NOT NULL
ORDER BY LocalTime DESC
)
UPDATE dbo.TagValuesArchive
SET TagValue= ((SUM( #tagValueBefore + #tagValueAfter ))/2)
FROM dbo.TagValuesArchive
WHERE LocalTime = #localTime
AND TagID = #tagID
FETCH NEXT FROM Cursor_FalseValues
INTO #tagId, #localTime, #tagValue
END
ELSE
BEGIN
-- Fetch of the Cursos increment the line
FETCH NEXT FROM Cursor_FalseValues
INTO #tagId, #localTime, #tagValue
END
-- Fetch of the Cursos increment the line
--FETCH NEXT FROM Cursor_FalseValues
--INTO #tagId, #localTime, #tagValue
END
CLOSE Cursor_FalseValues
DEALLOCATE Cursor_FalseValues
END
I think my problem is a good example to use Cursor, but it's not very clear in my head.
I can take the wrong value and the values between it. But the Update in the database doesn't work.
I don't know if it's a cursor problem or a update. Maybe just a code syntax problem.
Thanks for any informations.
You can try something like this:
DECLARE #t TABLE (
id int,
val float
)
INSERT INTO #t (id, val)
VALUES
(1,.5),
(2,.7),
(3,.3),
(4,.74),
(5,.2341234),
(6,10000000),
(7,.9),
(8,.8),
(9,.87123),
(10,100000000),
(11,.99)
SELECT * FROM #t
DECLARE #limit FLOAT = 1000000;
;WITH OutOfOBoundsValues AS (
SELECT id FROM #t WHERE val >= #limit
), Neighbourvalues AS (
SELECT O.id, (t1.val+t2.val)/2 newval FROM OutOfOBoundsValues O
JOIN #t t1 ON t1.id = O.id-1
JOIN #t t2 ON t2.id = O.id+1
)
UPDATE #t
SET val = N.newval
FROM #t t
JOIN Neighbourvalues N ON t.id = N.Id
SELECT * FROM #t
What happens here is that we select the data same as and above the limit.
Then we get the neighbouring values and calculates the mean value from them.
Lastly we update the out of bounds values with the mean value.
This should be much faster than your cursor.

declaring multiple columns in a count value

I am trying to define multiple count values for a counter and corresponding value. Here is my code:
DECLARE #RequestDate AS DATE = '2017-04-20'
;
DECLARE #POCounter INT;
DECLARE #POMax INT;
DECLARE #NewDate DATE;
SET #POCounter = 0;
SET #POMax =
(
SELECT
CUSTOMERPONUMBER,
(
SELECT
COUNT(CUSTOMERPONUMBER)
FROM DailyOpenOrders$
WHERE
RequestDate < #RequestDate
)
FROM DailyOpenOrders$
WHERE
RequestDate < #RequestDate
GROUP BY
CUSTOMERPONUMBER
)
The #POMax counter is to help me update the date that many times for a specific customerPO. I intend to increase the POCounter in a loop until it reaches the #POmax counter for each customerPOnumber.
Am i doing this wrong? can someone help?
#POMax is a scalar variable and can only hold one value at a time.
If you want to hold a collection of values, a table variable is a good tool for that:
DECLARE #MyTable TABLE
(
ID int PRIMARY KEY IDENTITY(1,1),
CustomerNumber varchar(50),
[TheCount] int
)
INSERT INTO #MyTable(CustomerNumber, [TheCount])
SELECT CustomerNumber, COUNT(*)
FROM SomeTable
GROUP BY CustomerNumber
Now you can loop over #MyTable, and for each CustomerNumber, loop from 1 to TheCount...
DECLARE #MyID int
SET #MyID = (SELECT MIN(ID) FROM #MyTable)
WHILE #MyID is not null
BEGIN
SELECT * FROM #MyTable WHERE ID = #MyID
SET #MyID = (SELECT MIN(ID) FROM #MyTable WHERE #MyID < ID)
END

dynamic alias in sql server

I want query field with different alias in stored procedure
select COUNT(EmpCode) as CountEmp+#para
result shoud be
CountEmp1
45
CountEmp2
54
CountEmp1
76
Query loop in c# code:
select COUNT(EmpCode) where something = #something as CountEmp+#para
Approach without dynamic SQL:
--I create temp table for demonstration
DECLARE #some_table TABLE (
Something int,
EmpCode INT
)
INSERT INTO #some_table (Something, EmpCode)
VALUES (1, 10),(1, 22),(1, 12),(2, 12),(2, 30),(3, 65),(3, 15),(3, 11),(3, 5)
--Declare parameter we want to search
DECLARE #param int = 1
--Query
--In cte we select what we need based on parameter
;WITH cte AS (
SELECT 'CountEmp'+CAST(#param as nvarchar(10)) as SomeThing,
CAST(COUNT(EmpCode) as nvarchar(10)) as EmpCodeCount,
ROW_NUMBER() OVER (ORDER BY SomeThing ) as rn
FROM #some_table
WHERE SomeThing = #param
GROUP BY SomeThing
)
--And here comes UNION
SELECT SomeThing as Result
FROM (
SELECT SomeThing,rn
FROM cte
UNION ALL
SELECT EmpCodeCount ,rn
FROM cte
) as t
ORDER BY rn, SomeThing DESC
Output:
Result
------------------
CountEmp1
3
(2 row(s) affected)
Please try to make use of below code. Its working fine with SQL Server 2012.
IF OBJECT_ID ('temp..#Mytable') IS NOT NULL
CREATE TABLE #Mytable (ID INT IDENTITY (1,1),EmpCode INT)
DECLARE #max int ,#count int
SET #max =0;
DECLARE #str varchar(10)
INSERT #Mytable
(EmpCode)
VALUES
(10),
(45),
(35),
(63),
(56),
(65)
SET #count = (SELECT COUNT (ID) FROM #Mytable )
WHILE #count > #max
BEGIN
SET #max = #max+1
SET #str = CONVERT(varchar(10),#max)
EXEC('SELECT EmpCode AS Empcode'+#str+ ' FROM #Mytable WHERE ID = '+#str)
END

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