SQL - Trying to add variable into string - sql

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.

Related

sql server concating or replacing, which one is better (faster)

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

Algorithm for auto generated series number in sql

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

Recursive Stored Procedures

I found this code snipped (Source):
CREATE PROCEDURE rec_fib(n INT, OUT out_fib INT)
BEGIN
DECLARE n_1 INT;
DECLARE n_2 INT;
IF (n=0) THEN
SET out_fib=0;
ELSEIF (n=1) then
SET out_fib=1;
ELSE
CALL rec_fib(n-1,n_1);
CALL rec_fib(n-2,n_2);
SET out_fib=(n_1 + n_2);
END IF;
END
This code works with MySQL. In how far do I have to modify it to run on DB2? I cannot seem to find a running minimal example of an recursive stored procedure for DB2.
This works for me: (I haven't done more than make it work, so alternative coding could also work.)
First, add these two lines:
DECLARE n_3 INT;
DECLARE n_4 INT;
Then modify this small section:
ELSE
set n_3 = n - 1;
set n_4 = n - 2;
CALL rec_fib(n_3,n_1);
CALL rec_fib(n_4,n_2);
That's all. Runs on IBM i 6.1 DB2 UDB.
The following code is from SQL tips for DB2, written by Serge Rielau
CREATE OR REPLACE FUNCTION Fib(n INTEGER) RETURNS DECIMAL(31, 0)
BEGIN
DECLARE res DECIMAL(31, 0);
CASE WHEN n = 0 THEN
SET res = 0;
WHEN n = 1 THEN
SET res = 1;
WHEN n > 1 THEN
BEGIN
DECLARE stmt STATEMENT;
PREPARE stmt FROM 'SET ? = Fib(? - 1) + Fib(? - 2)';
EXECUTE stmt INTO res USING n, n;
END;
ELSE
SIGNAL SQLSTATE '78000' SET MESSAGE_TEXT = 'Bad input';
END CASE;
RETURN res;
END;
/
For more information, please check the source page of this code: https://www.ibm.com/developerworks/community/blogs/SQLTips4DB2LUW/entry/recursive_sql_pl?lang=en

Returning values from dynamic SQL by using sp_executesql with an output variable (Or) Error in appending the variable data at the end name dynamically

I just face a problem while working on a stored procedure,
My situation is as below,
I'm calling a stored procedure inside another stored procedure like for example,
EXEC [SP_ADMIN_INSERT_ITEM_STOCK_DETAILS]
#stk_tran_no = #cash_purchase_no,
#stk_tran_date = GetDate(),
#tran_type = 'Cash Purchase',
#item_code = #item_code,
#quantity = #quantity
Currently in the above code we are passing current date to the parameter #stk_tran_date.
But now I need to pass date to #stk_tran_date by fetching that from some other table like,
select #stk_tran_date = Convert(datetime,cash_purchase_date,103) from Cash_Purchase_14 where cash_purchase_no = 'GOH-9/2014'
If you observe my table name is like Cash_Purchase_14 where 14 is a dynamic value which changes every year, as this is 2014 financial year so it looks like Cash_Purchase_14, next year it will be Cash_Purchase_15.
Because of this i use to write these quires first as string then I'll execute them as shown below,
declare #SQL nvarchar(4000)
set #SQL =N' Declare #cash_purchase_date1 datetime
set #cash_purchase_date1 = (select cash_purchase_date from Cash_Purchase_'+ #Financialyearpart +' where cash_purchase_no = ''' + #cash_purchase_no + ''')
print #cash_purchase_date1'
exec executesql #SQL
But I need the value of the variable #cash_purchase_date1 outside this block like below,
EXEC [SP_ADMIN_INSERT_ITEM_STOCK_DETAILS]
#stk_tran_no = #cash_purchase_no,
#stk_tran_date = #cash_purchase_date1,
#tran_type = 'Cash Purchase',
#item_code = #item_code,
#quantity = #quantity
but it is giving an error like, "declare the variable #cash_purchase_date1"
In Other case i tried like calling the stored procedure in side the string like,
SET #SQL =' Declare #cash_purchase_date1 datetime
set #cash_purchase_date1 = (select cash_purchase_date from Cash_Purchase_'+ #Financialyearpart +' where cash_purchase_no = ' + #qt + #cash_purchase_no + #qt +')
print #cash_purchase_date1
EXEC [SP_ADMIN_INSERT_ITEM_STOCK_DETAILS]
#stk_tran_no = ' + #qt + #cash_purchase_no + #qt +',
#stk_tran_date = #cash_purchase_date1,
#tran_type = ''Cash Purchase'',
#item_code = ' + #qt + #item_code + #qt +',
#quantity = ' + #quantity
exec executesql #SQL
In this scenario the value of #cash_purchase_date1 is not replacing it simply retains the same.
Please help to get the value of the variable outside the block.
Or
How can I append the value 14 at the end of the table name dynamically using a variable.
I Tried like
Declare #cash_purchase_date1 datetime
set #cash_purchase_date1 = cash_purchase_date from Cash_Purchase_+ #Financialyearpart
I think i made the problem bit complicated while explaining. Please help me in solving the issue.
Thanks in advance.
You can return values from dynamic sql by using sp_executesql with an output variable:
declare #SQL nvarchar(4000);
declare #cash_purchase_date datetime;
set #SQL = N'select #cash_purchase_date = cash_purchase_date from Cash_Purchase_' + #Financialyearpart + ' where cash_purchase_no = ''' + #cash_purchase_no + '''';
exec sp_executesql #SQL, N'#cash_purchase_date datetime OUTPUT', #cash_purchase_date = #cash_purchase_date OUTPUT;
I think this will solve your problem.

How to set two local variables with the same value in sql server?

This question must be really silly, but I haven't found an answer for it yet.
I'm making a program in C # that dynamically writes a script to run on SQL Server. I declared two variables that receive the values returned from two calls exec 'procedure_name'.
In the next block of the script, I want these variables to be set to zero.
How to do this using a SET?
would be something like this:
SET # a, # b = 0?
You can do it via SELECT:
SELECT #a = 0, #b = 0
With SET you need 2 SET commands:
SET #a = 0; SET #b = 0
Method 1
set #a = 0
set #b = 0
Method 2
Select #a = 0, #b = 0
Select #a = 0
select #b = 0
OR
Set #a=0
Set #b= #a
Or
set #a = 0
set #b= 0