solution for generating a running sequence number by using stored procedure in sql server 2008 - sql

how to generate a running sequence number from 0001 to 9999 by through using a function in sql server, if u call that function in sql server, it should to be provide a running sequence number when ever if it reach 9999 again it should to be reset 0001
can any help on this please to perform this above task

There are plenty of good articles about that. Try Google.
For instance see here and there

A function can't update, insert or delete, so you can't store the variable and check it's value next time you call the function. So there is no way of doing this using a function.

You can simply get the sequence number using following procedure:
CREATE PROCEDURE proc_GetSeqNumber
AS
BEGIN
DECLARE #idt INT
SET #idt = 0
WHILE (#idt < 9999)
BEGIN
SELECT #idt = #idt + 1
PRINT #idt
END
END

The only way a database can remember a value is if it is stored in a table (in Oracle, you could use a sequence, but SQL Server doesn't use those.) So I would create a single table with a single value and the function would read the value, increment it, and if need be reset it.

if #ItemsCount=0
begin
set #generatedSeNumber=1
end
else
begin
SET #sql= 'insert into Senumber values(('+#SeNumber+'))'
Exec (#sql)

Related

Same query, different result after removing USE DatabaseName GO

My function GetProductDesc (when called) returns a different result after commenting out USE DatabaseName GO. I don't even know where to start debugging this. The pictures tell the story. I had to blur out a lot but you can see that the results are clearly different. Keep in mind that the pictures are not the function code, they are calling the function GetProductDesc
So strange. Any suggestions? I have an expert helping me later today but I had to share.
EDIT:
The function uses another lookup table in the same database. There is no Top or Order By clause. It calculates the product description based on the input components (numbers). It will return a different result if the input numbers are different, but here the input numbers are the same!
The function has been in place and working for over 5 years. I believe the problem started at about the time the version of SQL Server was updated recently.
EDIT 2 with partial answer:
The problem is caused by ##RowCount. It appears to be a breaking change caused by our recent migration to SQL Server 2019 although I haven't found the problem documented. The function returns a different product description based on ##RowCount following a Select statement. Internally the function does something like this:
SELECT Fields FROM Table WHERE Field = #Variable
IF ##Rowcount = 1
Return ProdDesc1
ELSE
Return ProdDesc2
After the SQL Server migration ##RowCount here was different depending on whether
USE DatabaseName
GO
was present.
The solution was to replace ##Rowcount with a variable #RowCount. This new code works:
DECLARE #RowCount INT = 0
SELECT Fields, #RowCount = #RowCount + 1
FROM Table WHERE Field = #Variable
IF #RowCount = 1
Return ProdDesc1
ELSE
Return ProdDesc2
If you have SQL Server 2019 installed try this to recreate the problem:
USE Master
GO
Select ##ROWCOUNT
The result here is ##ROWCOUNT = 0
Now comment out the two top lines:
--USE Master
--GO
Select ##ROWCOUNT
The result is now ##ROWCOUNT = 1
Anybody know why?
There is a SQL Server 2019 cumulative update from Microsoft that fixes this problem.

How to rollback stored procedure that updates a table

Why doesn't this ROLLBACK TRANSACTION statement work?
BEGIN TRANSACTION;
DECLARE #foo INT
EXECUTE [database].[dbo].[get_counter] #CounterID='inventory_records', #nextValue=#foo OUTPUT;
ROLLBACK TRANSACTION;
Background
I'm inserting records into a customer's ERP system built on SQL Server 19. The ERP database doesn't have auto-incrementing primary keys. It instead uses a table called counters where each row has a counterID field and an integer value field.
To insert a new row into a table like inventory_record, I first need to call a stored procedure like this:
EXECUTE get_counter #counterID='inventory_record'
This procedure returns an OUT parameter called #nextValue which I then INSERT into the inventory_record table as its uid.
I need to ROLLBACK this stored procedure's behavior if my insert fails. That way the counter doesn't increase boundlessly on failed INSERT attempts.
Contents of get_counter stored procedure
It's dirt simple but also subject to copyright. I've summarized and truncated here. The counters are stored as sequences in the DB. So get_counter calls sp_sequence_get_range after checking that the requested counter is legitimate.
ALTER PROCEDURE get_counter
#strCounterID varchar(64),
#iIncrementValue integer = 1,
#LastValue BIGINT = NULL OUTPUT
AS
SET NOCOUNT ON
BEGIN
DECLARE
#nextSeqVar SQL_VARIANT
, #lastSeqVar SQL_VARIANT
-- code that confirms valid counter name
BEGIN TRY
-- code that calls [sp_sequence_get_range]
END TRY
BEGIN CATCH
THROW
END CATCH
RETURN(#LastValue)
END
The Problem
The inventory_record counter always increments. I can't roll it back.
If I run the SQL at the top of this question from SSMS, then SELECT value FROM counters WHERE counterID = 'inventory_record', the counter increments each time I execute.
I'm new to transaction handling in SQL Server. Any ideas what I'm missing?
re-post comments as answer for better readability.
The get_counter is using Sequence Numbers (sp_sequence_get_range). Please refer to documentation on Limitation section.
Sequence numbers are generated outside the scope of the current
transaction. They are consumed whether the transaction using the
sequence number is committed or rolled back
You may see a simple demo here

How to get row count of a stored procedure?

I have a stored procedure which accepts a Client number and returns certain data. I have another stored procedure which internally calls the first one and needs to use the Row count from the first stored procedure.
Is there anywhere I can achieve this without using a temporary table (to get the result set) or using an OUT parameter in the first stored procedure.Thanks.
Since you already calling your stored procedure from first one, you already have ability to get number of rows returned by using ##ROWCOUNT function. Below is example of using `##RowCount
CREATE PROC test1
AS
BEGIN
SELECT *
FROM sys.tables
END
CREATE PROC Test2
AS
BEGIN
SET NOCOUNT ON;
EXEC Test1
PRINT ##ROWCOUNT
END
EXEC Test2
In my example I just printed that value out, but you can just as simply assign that to a variable in second procedure and use it for something else.

SQL session/connection variables

I'm trying to find some equivalent to session variables in SQL. I want to be able to store and retrieve just a number but each connection to the database has a different number. It needs to persist from one batch to the next on the same connection.
I did have a solution that used a global cursor like this.
IF (SELECT CURSOR_STATUS('global','ChangeSet')) >= 0
BEGIN --Close and deallocate the cursor
Close ChangeSet
DEALLOCATE ChangeSet
END
--Create a new cursor
DECLARE ChangeSet CURSOR GLOBAL STATIC FOR
SELECT ChangeSet = #ChangeSet
--Open the cursor
OPEN ChangeSet
Each connection would have a different cursor so it worked, but this is not usable inside of a view. I guess if somebody can show me how to read this in a view that would be cool too.
I'm using MS SQL Server btw.
The CONTEXT_INFO property may be what you're looking for - it enables you to set and read a connection-specific binary value.
You could encode your numeric value to binary and store it in this property.
Starting from SQL 2016
EXEC sys.sp_set_session_context #key = N'language', #value = 'English';
SELECT SESSION_CONTEXT(N'language');
A temporary table survives a batch (including go). It's still connection specific:
create table #temp (val float)
insert #temp values (3.14)
go
select * from #temp

SQL stored proc - help me write this one, please! (part 2)

I have the following table with the value 501 in it..
CREATE TABLE _Numbers(
Number numeric(20,0) NOT NULL PRIMARY KEY
)
INSERT INTO _Numbers VALUES(501)
How can I write a stored proc on this which returns me 501 and increments Number to next in sequence (i.e. 502)? I would like this behaviour repeated every time the stored proc is called.
(Also, how can I call this stored proc from any query?)
Part of my previous question 3151056.
Thanks,
Voodoo
Use an IDENTITY column which takes care of numbering and incrementing for you.
Any returned number is liable to be already used by another connection/client/process
You're importing data from old tables, right?
What if you import data from old tables with identity off and after that you set the identity with the highest number+1 and continue your life using identity.
Other approach is using a trigger at insert that would check if NumberItem is null and it will add the Max+1 if it's null. If not, do nothing.
I don't think that SP is a good solution. And I'm pretty sure you don't need all that stuff.
CREATE OR REPLACE PROCEDURE read_and_increment (number_just_read OUT NUMBER)
IS
BEGIN
DECLARE
stored_number NUMBER DEFAULT NULL;
BEGIN
SELECT number
INTO stored_number
FROM _numbers
WHERE ROWNUM = 1;
number_just_read := stored_number;
UPDATE _numbers
SET number = number + 1;
COMMIT;
END;
END read_and_increment;