I want to make an algorithm for generate next series number by specified last series number in sql like below:
Last Number Next Number
> AAAA095 AAAA096
> AAAA999 AAAB001
> AAAB001 AAAB002
> AAAZ999 AABA001
After some try, Finally i got an algorithm & create it to SQL Scalar-valued function for this question as below
CREATE FUNCTION GetNextSeries ( #lastSeriesNo VARCHAR(8))
RETURNS VARCHAR(8)
AS
BEGIN
DECLARE #nextSeriesNo VARCHAR(8)
DECLARE #CHAR1 CHAR=SUBSTRING(#lastSeriesNo,1,1)
DECLARE #CHAR2 CHAR=SUBSTRING(#lastSeriesNo,2,1)
DECLARE #CHAR3 CHAR=SUBSTRING(#lastSeriesNo,3,1)
DECLARE #CHAR4 CHAR=SUBSTRING(#lastSeriesNo,4,1)
DECLARE #n INT=SUBSTRING(#lastSeriesNo,5,3)
SET #n = #n + 1
IF(#n>999)
BEGIN
SET #n=1
IF(#CHAR4<>'Z')
BEGIN
SET #CHAR4=CHAR(UNICODE(#CHAR4)+1)
END
ELSE IF(#CHAR3<>'Z')
BEGIN
SET #CHAR4='A'
SET #CHAR3=CHAR(UNICODE(#CHAR3)+1)
END
ELSE IF(#CHAR2<>'Z')
BEGIN
SET #CHAR4='A'
SET #CHAR3='A'
SET #CHAR2=CHAR(UNICODE(#CHAR2)+1)
END
ELSE IF(#CHAR1<>'Z')
BEGIN
SET #CHAR4='A'
SET #CHAR3='A'
SET #CHAR2='A'
SET #CHAR1=CHAR(UNICODE(#CHAR1)+1)
END
END
SET #nextSeriesNo=#CHAR1+#CHAR2+#CHAR3+#CHAR4+(CASE LEN(#n) WHEN 1 THEN '00' WHEN 2 THEN '0' ELSE '' END)+convert(VARCHAR(3),#n)
RETURN #nextSeriesNo
END
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
The Camel scalar-valued function does not work when using variables
declare #primary_supervisor_name varchar(2000)
declare #lastname varchar(2000)
declare #containComma int
declare #position int
declare #result varchar(200)
DECLARE ts_cursor CURSOR FOR
select primary_supervisor_name from Test
OPEN ts_cursor
FETCH NEXT FROM ts_cursor INTO #primary_supervisor_name
WHILE ##FETCH_STATUS = 0
BEGIN
set #containComma = CHARINDEX(',', #primary_supervisor_name)
Begin
IF (#containComma = 0)
set #position = CHARINDEX(' ' , #primary_supervisor_name)
set #lastName = substring(#primary_supervisor_name, #position + 1, len(#primary_supervisor_name))
set #lastName = LOWER(#lastName)
print dbo.CamelCase('test') -- WORKS and PRINTs "Test"
print dbo.CamelCase(#lastName) -- does not do anything..no seeing any print output in console.
end
FETCH NEXT FROM ts_cursor INTO #primary_supervisor_name
END
CLOSE ts_cursor
DEALLOCATE ts_cursor
The camel function does not work for #lastName.
Using the Camel function from https://www.sqlservercentral.com/scripts/function-returns-string-in-proper-case-camelcase
I think the problem may be your program structure. Your BEGIN and END seem odd and off a bit.
WHILE ##FETCH_STATUS = 0
BEGIN
set #containComma = CHARINDEX(',', #primary_supervisor_name)
Begin
...
IF (#containComma = 0)
end
FETCH NEXT FROM ts_cursor INTO #primary_supervisor_name
END
I would think you were going for the code block below
WHILE ##FETCH_STATUS = 0
BEGIN
set #containComma = CHARINDEX(',', #primary_supervisor_name)
IF (#containComma = 0) BEGIN -- <--- Begin on this line?
...
end
FETCH NEXT FROM ts_cursor INTO #primary_supervisor_name
END
I have to generate a very long procedure every time for a reporting system, so i created a template for my procedure and replacing the parts are needed to, but i could do it with Concat or +(&)
for example:
set #query = '... and (
--#InnerQueries
)'
set #query = replace(#query,'--#InnerQueries',#otherValues)
vs
set #query += ' and exists (...)'
if(#xxx is not null)
set #query += 'and not exists (...)'
with replace approach it's more readable and maintainable for me, but for sake of optimization, what about Concat and attaching string together?
with replace: there are a lot of searching but less string creation
and with concat: lot's of string creation but no searching
so any idea?
I assume you're talking about using CONCAT or REPLACE to build an SQL then run it. If ultimately you'll process fewer than 100 REPLACEments, I'd go with that approach rather than CONCAT because it's more readable.
If however, you're talking about using concat/replace to create report output data and you will e.g. be carrying out 100 REPLACE operations per row on a million rows, I'd do the CONCAT route
update 2:
there could be something missing here:
if i change first variable :#sourceText_Replace
to a max value of 8000 character, and continue to add to it:
set #sourceText_Replace += '8000 character length'
set #sourceText_Replace +=#sourceText_Replace
set #sourceText_Replace +=#sourceText_Replace
set #sourceText_Replace +=#sourceText_Replace
set #sourceText_Replace +=#sourceText_Replace
set #sourceText_Replace +=#sourceText_Replace
set #sourceText_Replace +=#sourceText_Replace
it works fine, even if go up until: 16384017 character length
so any idea here is as good as mine
orginal answer:
to summarize (and if i didnt make any mistakes):
if you are searching in a long text, dont even think about using replace, it took seconds not milliseconds, but for concat obviously does not make any difference
in the blew code, in first try(small text), i just used variables default values and did not append to them,
but for second try(long Text) , i just append result from previous loop run
for long text, i did not bothered to run the loop more than 20 time, because it took over minutes.
smallText: set #destSmallText_Replace =
longText: set #destSmallText_Replace +=
here is the code for test:
SET NOCOUNT ON
drop table if exists #tempReplace
drop table if exists #tempConcat
create table #tempReplace
(
[txt] nvarchar(max) not null
)
create table #tempConcat
(
[txt] nvarchar(max) not null
)
declare #sourceText_Replace nvarchar(max) = 'small1 text to replace #textToBeReplaced after param text'
declare #text_Replace nvarchar(max) = #sourceText_Replace
declare #textToSearch nvarchar(max) = '#textToBeReplaced'
declare #textToReplace nvarchar(max) = 'textToBeReplaced'
declare #concat_Start nvarchar(max) = 'small1 text to replace'
declare #concat_End nvarchar(max) = 'after param text'
declare #text_Concat nvarchar(max) = #concat_Start
declare #whileCounter int =0
declare #maxCounter int = 5
declare #startTime datetime = getdate();
declare #endTime datetime = getdate();
begin
set #startTime = getDate();
while(#whileCounter <=#maxCounter)
begin
--long text
set #text_Replace += replace(#sourceText_Replace,#textToSearch,#textToReplace + convert(nvarchar(10), #whileCounter)) + #textToSearch
--small text
--set #text_Replace = replace(#sourceText_Replace,#textToSearch,#textToReplace + convert(nvarchar(10), #whileCounter)) + #textToSearch
--print #destSmallText_Replace
insert into #tempReplace values(#text_Replace)
set #whileCounter+=1
end
set #endTime = getDate();
print 'passedTime ' + Convert(nvarchar(20), DATEPART(millisecond, #endTime) - DATEPART(millisecond, #startTime))
end
begin
set #whileCounter = 0;
set #startTime = getDate();
while(#whileCounter <=#maxCounter)
begin
set #text_Concat += concat(#concat_Start,#textToReplace + convert(nvarchar(10), #whileCounter),#concat_End) + #textToSearch
--print #sourceSmallText_Concat
insert into #tempConcat values(#text_Concat)
set #whileCounter+=1
end
set #endTime = getDate();
print 'passedTime ' + Convert(nvarchar(20), DATEPART(millisecond, #endTime) - DATEPART(millisecond, #startTime))
end
Thank you in advance for your help here.
I want to insert incremental numbers as strings to load some bulk test numbers into a db, here is what i'm using:
Declare
#Serialcounter bigint
set #Serialcounter = 0
while #Serialcounter < 10
insert into [TrackTrace].[dbo].[TAB_ELEMENT] ([Serial], [Batch], [Batch_Id], [QCSample], [StationID])
values(Convert(varchar(60), #Serialcounter), 'test', 8989, 0, 1)
set #Serialcounter = (#Serialcounter + 1)
but when I do this it does not increment the counter and I just insert duplicate numbers and do not stop. I think my problem is that my variable is incremented outside of the while loop, but I am not sure how to rectify this.
Declare
#Serialcounter bigint
set #Serialcounter = 0
while #Serialcounter < 10
BEGIN
PRINT #Serialcounter
--insert into [TrackTrace].[dbo].[TAB_ELEMENT]
--([Serial]
--,[Batch]
--,[Batch_Id]
--,[QCSample]
--,[StationID])
--Values(Convert(varchar(60),#Serialcounter),'test',8989,0,1)
set #Serialcounter = (#Serialcounter +1 )
END
You not giving begin and end so as for all loops only first statement is considered
I was missing BEGIN and END statements
DECLARE
#Serialcounter BIGINT
SET #Serialcounter = 0
WHILE #Serialcounter < 10
BEGIN -- here
INSERT INTO [TrackTrace].[dbo].[TAB_ELEMENT]
([Serial]
,[Batch]
,[Batch_Id]
,[QCSample]
,[StationID])
VALUES(Convert(varchar(60),#Serialcounter),'test',8989,0,1)
SET #Serialcounter = (#Serialcounter +1 )
END -- and here
I want to create automatic code example:
B001, B002, B003, B004 .....
I have create the function for that:
CREATE FUNCTION AUTO_CODE()
RETURNS CHAR (4)
AS
BEGIN
DECLARE #KODE CHAR(4)
SELECT #KODE = COUNT (KODE_BARANG)FROM BARANG
IF #KODE>0
BEGIN
SELECT #KODE = RIGHT(KODE_BARANG,4) FROM BARANG
SET #KODE = #KODE+1
END
ELSE SET #KODE=1
RETURN 'B' + LEFT('00',3-LEN(#KODE))+(#KODE)
END
The function above only works for B001 through B010, beyond that it was back to B001. It won't work for B011, B012 or B120.
After that I have try to do with if else:
...
DECLARE KODENYA CHAR (5)
IF #KODE >= 0 AND #KODE <=9
BEGIN
SET #KODENYA = 'B' + LEFT('00',4-LEN(#KODE))+(#KODE)
END
ELSE IF #KODE >= 10 AND #KODE <=99
BEGIN
SET #KODENYA = 'B' + LEFT('0',4-LEN(#KODE))+(#KODE)
END
ELSE IF #KODE >= 100 AND #KODE <=999
BEGIN
SET #KODENYA = 'B' + LEFT('',4-LEN(#KODE))+(#KODE)
END
RETURN #KODENYA
The result is still the same and somehow I get #KODE if it was beyond 9 it return to null and SQL SERVER read it as 0.
Is there another way to create this kind of code in SQL SERVER?
There is no need for multiple if/case just simple FORMAT:
CREATE TABLE #tab(KODE INT);
INSERT INTO #tab(KODE) VALUES (1),(2),(10),(99),(101),(100),(999);
SELECT FORMAT(KODE, 'B00#')
FROM #tab;
LiveDemo
You can easily tweak it for longer codes by changing format string 'B000#'
And in your case:
CREATE FUNCTION [dbo].[AUTO_CODE]()
RETURNS CHAR(4)
AS
BEGIN
DECLARE #KODE INT = (SELECT COUNT(KODE_BARANG)FROM BARANG);
RETURN FORMAT(#KODE, 'B00#');
END
Warning:
You function may return duplicates/create gaps when many concurrent calls occur.
SqlFiddleDemo
Depending on your needs you may consider adding calculated column to your BARANG table:
CREATE TABLE BARANG(ID INT IDENTITY(1,1) PRIMARY KEY,
col2 VARCHAR(120) NOT NULL,
...
KODE AS (FORMAT(ID, 'B00#'))
);
I have a store procedure where I pass a path to the file like:
EXEC spMyPathFile
#PFile = 'C:\TFiles\Paths\Test_1.1_Version.txt'
What I'd like to do it loop through and be able to pass a number of versions of the file like 1.1 and 1.2 etc using:
DECLARE #intLp INT
DECLARE #a varchar(2)
SET #intLp = 1 WHILE (#intLp <2)
BEGIN IF #intLp = 1 BEGIN
SET #a = '1.1'
END
ELSE IF #intLp = 2
BEGIN
SET #a = '1.2'
END
EXEC spMyPathFile
#PFile = 'C:\TFiles\Paths\Test_'+#a+'_Version.txt'
SET #intLp = #intLp + 1
END
For some reason I get "Incorrect syntax near '+'." which is just before the #a. I'm obviously not joining my variable to my string properly.
Could someone give me an example of how this should look?
Change
EXEC spMyPathFile
#PFile = 'C:\TFiles\Paths\Test_'+#a+'_Version.txt'
to
declare #FileName varchar(100) = 'C:\TFiles\Paths\Test_' + #a + '_Version.txt'
EXEC spMyPathFile
#PFile = #FileName
Edit:
From MSDN - Specify Parameters
The parameter values supplied with a procedure call must be constants or a variable; a function name cannot be used as a parameter value. Variables can be user-defined or system variables such as ##spid.