April 27, 2007 at 4:02 pm
I have a SP that gets me the next customer number for a web app.
I store a number out in a table, when the SP is called it gets the number in the table, increments, updates the table with the new number, then returns the number to the user. I only generate about 20 numbers per day so not a big load at this point.
My question/concern is returning duplicate numbers. I’ve looked thru BOL but couldn’t find the answer. When multiple connections are accessing that SP, is it asynchronous or synchronous? Does one connection have to wait until the SP executes before it gets it, or does another instance of the SP execute. In my current situation with the low load it would be hard to create duplicate numbers but in a very heavy load environment it looks like it could be easy if its asynchronous. Is there any way to make it synchronous?
Thanks
Allen
Thanks
April 27, 2007 at 4:16 pm
First question would be... Why aren't you using an IDENTITY column to do this along with Scope_Identity.
Next question would be... Please post your SP...
--Jeff Moden
Change is inevitable... Change for the better is not.
April 27, 2007 at 4:29 pm
Here most of the sp. I left a little bit out, I'm creating two different cust no's, one has to start with a M, they both have different starting places for the numbering sequence, reason not using an identity column. There will only be two rows in the table ever. Its an internal app.
I was mostly just curious about the synchronous part.
DECLARE @lastNumber AS CHAR(6),
@numberToIncrement AS INT,
@newNumber AS VARCHAR(6),
@len_newNumber AS INT
SELECT @lastNumber = last_cust_no
FROM mm_CompanyNo
WHERE company = @strCompany
SELECT @numberToIncrement = CAST( (RIGHT(@lastNumber, 5)) AS INT)
SELECT @numberToIncrement = @numberToIncrement + 1
SELECT @len_newNumber = LEN(CAST((@numberToIncrement) AS VARCHAR))
IF @len_newNumber = 4
SELECT @newNumber = '0' + CAST(@numberToIncrement AS VARCHAR(5))
ELSE
IF @len_newNumber = 3
SELECT @newNumber = '00' + CAST(@numberToIncrement AS VARCHAR(5))
ELSE
IF @len_newNumber = 2
SELECT @newNumber = '000' + CAST(@numberToIncrement AS VARCHAR(5))
ELSE
IF @len_newNumber = 1
SELECT @newNumber = '0000' + CAST(@numberToIncrement AS VARCHAR(5))
ELSE
SELECT @newNumber = CAST(@numberToIncrement AS VARCHAR(5))
IF @strCompany = 'ABC'
SELECT @newNumber = '0' + @newNumber
ELSE
SELECT @newNumber = 'M' + @newNumber
UPDATE mm_CompanyNo
SET last_cust_no = @newNumber
WHERE company = @strCompany
SELECT @returnNumber = @newNumber
Thanks
April 27, 2007 at 5:39 pm
Try this and see if you can use it. It should take care of when the procedure is used heavily, but I'll leave that to someone else to prove or disprove.
-- create table mm_CompanyNo (last_cust_no varchar(6), company varchar(50))
-- insert into mm_CompanyNo values ('000001', 'ABC')
-- insert into mm_CompanyNo values ('M00100', 'DEF')
declare @strCompany varchar(50),
@returnNumber varchar(6)
set @strCompany = 'ABC'
DECLARE @lastNumber AS CHAR(6),
@numberToIncrement AS INT,
@newNumber AS VARCHAR(6),
@len_newNumber AS INT
update mm_CompanyNo set
@returnNumber = last_cust_no = (select substring(last_cust_no, 1, 1) +
replicate(0, 5 - len(cast(substring(last_cust_no, 2, 5) as int) + 1)) +
cast(cast(substring(last_cust_no, 2, 5) as int) + 1 as varchar(5)) from mm_CompanyNo where company = @strCompany)
where
company = @strCompany
SELECT @returnNumber = @newNumber
select @returnNumber
-- drop table mm_CompanyNo
-- select * from mm_CompanyNo
April 27, 2007 at 6:25 pm
Lynn's should work, however this may be a little more simplified
DECLARE @strCompany varchar(50),
@returnNumber varchar(6)
UPDATE
dbo.mm_CompanyNo
SET
@returnNumber = last_cust_no = (CASE WHEN @strCompany = 'ABC' THEN '0' ELSE 'M' END) + RIGHT('00000' + CAST(CAST((RIGHT(last_cust_no, 5)) AS INT) + 1 AS varchar(6)),5)
WHERE
@strCompany
SELECT @returnNumber
April 27, 2007 at 7:21 pm
Allen,
First, there is no reason, whatsoever, to store the "M" in the sequence table. All it does is slow everything down with unneccessary character conversions.
Using the good example that Mr. Pettis started, with some mods... the blue stuff is the actual proc I think you need... guaranteed not to return dupes... guaranteed not to deadlock...
--==============================================================================================
-- Setup for the test
--==============================================================================================
--===== Create sequence table similar to Allen's
CREATE TABLE dbo.mm_CompanyNo (Last_Cust_No INT, Company VARCHAR(50))
--===== Seed the table with starting values for each company
-- This will be the "0" company in this example
INSERT INTO mm_CompanyNo VALUES ( 0,'ABC') --First new id will be "000001"
-- This will be the "M" company in this example
INSERT INTO mm_CompanyNo VALUES (100,'DEF') --First new id will be "M00101"
GO
--===== Create a procedure to get a new customer number depending on the company
CREATE PROCEDURE dbo.GetNextCustNo (@Company VARCHAR(50), @NewCustNo VARCHAR(6) OUTPUT)
AS
DECLARE @NextID INT
SET NOCOUNT ON
UPDATE dbo.mm_CompanyNo
SET @NextID = Last_Cust_No = Last_Cust_No+1
WHERE Company = @Company
SET @NewCustNo = CASE @Company
WHEN 'DEF'
THEN 'M'+REPLACE(STR(@NextID,5),' ','0')
ELSE REPLACE(STR(@NextID,6),' ','0')
END
GO
--==============================================================================================
-- Demo how to use this bugger
--==============================================================================================
--===== Declare local variables for the test
DECLARE @Company VARCHAR(50)
DECLARE @NewCustNo VARCHAR(6)
SET @Company = 'ABC'
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
SET @Company = 'DEF'
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
EXEC dbo.GetNextCustNo @Company,@NewCustNo OUT
PRINT @NewCustNo
--Jeff Moden
Change is inevitable... Change for the better is not.
April 28, 2007 at 7:25 am
Thank you all for great improvements, it's been a great learning experience.
Thanks
Allen
Thanks
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply