Given the following variables in beginning of a procedure:
DECLARE #Flow_ID INT
,#Flow_ID_Varchar NVARCHAR(10)
,#Flow_Table_Name VARCHAR(200);
Through my procedure I want #Flow_ID_Varchar and #Flow_Table_Name to always be:
SET #Flow_ID_Varchar = CAST(#Flow_ID AS NVARCHAR(10));
SET #Flow_Table_Name = 'Flow_'+#Flow_ID_Varchar';
My procedure has several blocks, each populates #Flow_ID differently and may not be accessed in a given run.
Is there a way to force #Flow_ID_Varchar and #Flow_Table_Name to be computed dynamically when #Flow_ID changes without me using the SET commands each time?
Related
Consider the following stored procedure:
ALTER PROCEDURE Administration.SetAndRetrieveNewPurchaseOrderNumber
#PurchaseOrderNumber INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
UPDATE Administration.KeyNumbers
SET PurchaseOrderNumber += 1
WHERE RowId = 1
SET #PurchaseOrderNumber = (SELECT kn.PurchaseOrderNumber
FROM Administration.KeyNumbers kn
WHERE kn.RowId = 1)
END
GO
I can use this easily from within my application by simply executing the procedure and passing in by reference a suitably named parameter.
I now find myself wanting to execute the procedure listed above in another stored procedure. I tried the following, but it doesn't appear to work (either with or without the # symbol in the parameter part of the stored procedure being called;
DECLARE #PurchaseOrderNumber INT
EXEC Administration.SetAndRetrieveNewPurchaseOrderNumber(#PurchaseOrderNumber)
What is the correct way to do this, or in reality should there be a separate procedure for use in circumstances like this that only produces a scalar result?
You need to add the output keyword when passing in the parameter.
For example:
Declare #output int;
Exec storedproc(#parameter output)
I am using quite a long dynamic SQL Statement (a bit more than 13000 characters) but when I am trying to execute it, I am noticing that the exec isn't reading the statement completly and cuts the last part off.
I am using:
DECLARE #Statement nvarchar(max)
SET #Statement = N'[LONG STATEMENT]'
EXEC (#Statement)
I did notice, that it could read even less characters, if I am not using the the brackets in EXEC (#Statement)
I also tried using EXEC sp_executesql #Statement
It just stops reading the statement after 12482 characters...
I have the problems with SQL-Server 2008 R2 and SQL Server 2014
EDIT: OK, now I noticed something different. It seems, that the lenght itself of the statement is not exactly the problem. As I mentioned in a comment below, I am using this long dynamic sql statement, because I am creating an update script, which adds a new stored procedure and within this procedure I am using table names, which can differ. So I created variables, which contain the table names and used these variables with the dynamic sql statement, so I don't need to change the table names within the procedures and functions I am adding with this update script, but just changing the content of the variables.
However, if I am NOT using these variables and use the table names "hardcoded" in the statement, the statement can be executed successfully...
I guess the answer is here:
So I created variables, which contain the table names and used these
variables with the dynamic sql statement, so I don't need to change
the table names within the procedures and functions I am adding with
this update script, but just changing the content of the variables.
I guess, your dynamic T-SQL statement is built using string concatenation. So, let's say we have something like this:
DECLARE #DynamicSQLSTatement NVARCHAR(MAX);
DECLARE #TableName01 NVARCHAR(128) = 'T01';
DECLARE #TableName02 NVARCHAR(128) = 'T02';
DECLARE #TSQL NVARCHAR(4000) = REPLICATE(N'X', 4000);
SET #DynamicSQLSTatement = #TableName01 + #TSQL + #TableName02;
We have three short strings (length < max) and when they are concatenated, we expect that the new NVARCHAR(MAX) value will be capable of storing the whole new string (it is with max length, after all).
So, the following statement will give as T02, right?
SELECT RIGHT(#DynamicSQLSTatement, 3);
But no, the output is XXX. So, the question is why the whole concatenation text is not preserved?
When you are concatenating nvarchar(1-4000) strings they output string is not converted to max if it is not possible to store all the data.
In order to fix this, we can cast the first part of the string to nvarchar(max):
SET #DynamicSQLSTatement = CAST(#TableName01 AS NVARCHAR(MAX)) + #TSQL + #TableName02
SELECT RIGHT(#DynamicSQLSTatement, 3);
I'd imagine your hitting a limit of about 16K (8K used to be the most data you could hold in a variable before nvarchar(max) etc was invented. You could try using varchar(max) instead of nvarchar as that will be half the size (unicode is 16-bit, ascii is 8-bit). I have a feeling that won't help much though.
Really though, you're hitting this issue because whatever you're trying to do shouldn't really be done like that, super long SQL statements are a sign that you've gone down the wrong path. Find a way to break down your query or operations. If this is a query, consider if you could restrict your data set over a few steps rather than in one query.
I want to use dinamic query with exec clause to set some variable in sql server, but not work properly.
My code is like this :
DECLARE
#ProjectCode varchar(25),
#TypeCode varchar(25),
#BomDate varchar(25),
#TbNameBom varchar(25),
#BomProgressCal int
SET #ProjectCode = 'PRO160604'
SET #TypeCode = 'PS-BPRG15AGW'
SET #BomDate = '8/19/2016'
SET #TbNameBom = 'z'+#TypeCode
EXEC('
SET #BomProgressCal = (SELECT AVG([Bod Progress]) FROM [PMLite].[dbo]. ['+#TbNameBom+']
WHERE ([Project Code] = #ProjectCode) AND
([Type Code] = #TypeCode) AND
([Bom Date] = #BomDate))
')
PRINT #BomProgressCal
This error appears:
Msg 137, Level 15, State 2, Line 3
Must declare the scalar variable "#ProjectCode".
You're trying to set #BomProgressCal within context of EXEC function, so you can't update it directly as it's not visible.
You can implement INSERT INTO "temp table" EXEC (sql_code) method to retrieve any data from dynamic sql query. Then just query that temp table.
To pass parameters to dynamic query, you can use sp_execute_sql or just use REPLACE function to replace tokens (like '#TypeCode' with actual value) - don't forget here to replace ' with '' for any varchar/char/nvarchar values.
You can't pass variables willy nilly between dynamic sql (which you do not at all need in this example anyway) and the outer code ... when the dynamic sql is executed it has no idea what #BomProgressCal is because that is a different context.
If you have to use dynamic sql, rather than the EXEC command, I would suggest using sp_executesql which allows you to pass variable values through regular and output parameters.
In general, I would suggest not using dynamic sql unless that is really your only option because almost always (like this example) its use is unwarranted.
I am trying to put comma separated values as parameter to stored procedure, but when I am pressing "Enter" key for continuing the values so that it can be seen in single screen (without scrolling) , SP is not accepting the values which are provided after "Enter" key is pressed(means in new line)
USP_SAMPLE_SP #YEAR, #EMPIDS
If I am executing stored procedure as below :
USP_SAMPLE_SP '2016','111,222,333,444,555'
It is executing properly
But if I am trying to execute like below :
USP_SAMPLE_SP '2016','111,222,
333,444,555'
It is accepting all values however it is showing values up to '222' after that it is not considering any value.
Referring to "Newline" I mean is it is accepting like below :
USP_SAMPLE_SP '2016','111, 222,333,444,555'
But if I am pressing "Enter" it is not accepting values after that
If any one can explain this scenario it will be helpful.
Note: Sometimes I need to pass large number of values(ex. 1000 or above).
Please suggest if any one knows better and efficient way to do this.
First I am creating User-Defined Table Type as EMPType
CREATE TYPE [dbo].[EMPType] AS TABLE(
FinStartYear varchar(4),
EmpId nvarchar(max) NULL
)
Then I am trying to pass those values for altering my stored procedure as below :
ALTER PROCEDURE [USP_SAMPLE_SP]
-- Add the parameters for the stored procedure here
#FinStartYear EMPType readonly ,
#EmpIDs EMPType readonly
AS
But when I hover mouse over the parameter it shows me below error :
The Parameter '#FinStartYear' cannot be declared READONLY since it is not table valued parameter.
The Parameter '#EmpIDs' cannot be declared READONLY since it is not table valued parameter.
But when I am trying to alter the stored procedure it is showing me below error :
Must declare the scalar variable "#EmpIDs".
Must declare the scalar variable "#FinStartYear"
When I hover over 'EMPType' it shows me below error :
Parameter or variable '#FinStartYear' has an invalid datatype.
NOTE : Under Programmability -> Types -> User-Defined Table Types ->dbo.EMPType
It is showing me EMPType has been created.
It's not possible to be certain without seeing the code of your stored procedure, but I suspect that the newline character somehow breaks the code which is used to split the delimited string into a result set; the newline character is interpreted as a terminator and all the values following it are ignored.
There are several possible solutions.
One is to build your list of input values from a series of shorter strings, enabling you to control how the list appears on the screen without affecting its content. Note that this requires the use of a variable:
-- I am guessing the data type of the #EMPIDS parameter. Use a matching type for #IDS
DECLARE #IDS VARCHAR(MAX) = '111,222,'
+ '333,444,555'
EXEC USP_SAMPLE_SP #YEAR = '2016', #EMPIDS = #IDS
Another would be to amend the code of the stored procedure to strip out newline characters before splitting the delimited list. I wouldn't recommend this, since this behaviour might be relied on by other users of the code.
Edit
Here's an example of how to replace newline characters:
DECLARE #EMPID varchar(100) = '111,222,
333,444,555'
SET #EMPID = REPLACE(REPLACE(#EMPID,CHAR(13),''),CHAR(10),'')
SELECT #EMPID
Before you use this, make sure you're not going to affect any other users of this code who might rely on the current behaviour.
Another solution would be to amend the stored procedure to accept a table-valued parameter rather than a delimited list. This is a little more complex to set up but likely to perform than better than splitting a delimited string, especially if the string contains thousands of values.
Edit 2
I think you might have misunderstood how a table-valued parameter works. It enables you to completely avoid the concatenated list of EMPIDs, and instead work with a table variable containing one EMPID per row which can be passed as an argument to a stored procedure.
Here's a worked example:
CREATE TYPE dbo.EMPType AS TABLE(
EmpId int NOT NULL PRIMARY KEY
)
GO
-- I don't know what your procedure does so I've created a simple stub
-- which shows how to use the table-valued parameter like a table
CREATE PROCEDURE dbo.USP_SAMPLE_SP
#FinStartYear varchar(4),
#empids EMPType readonly
AS
SELECT #FinStartYear AS out_year, EmpId
FROM #empids
ORDER BY EmpId
GO
-- use the code from here to the end of the example every time
-- you want to execute the procedure (setting the list of EMPID values appropriately
DECLARE #in_emp EMPType --declare an instance of EMPType as a variable
INSERT #in_emp(EmpId) VALUES (111),(333),(222),(555),(444) --insert some values into the variable
EXEC dbo.USP_SAMPLE_SP #FinStartYear = '2016',#empids = #in_emp --pass the variable as a parameter to the stored procedure
GO
I'm just started using MSSQL and need to understand.
While I was reading few sample code that I might use in near future
found
CREATE PROCEDURE [dbo].[SP_Set_LMS_BY_ERW] #UPA nvarchar(30) = NULL
Question is what's the difference between #UPA above
Declare #count nvarchar(30)?
Thank you
#UPA nvarchar(30) = NULL is the procedure argument/parameter (in this case, an optional parameter though since it's being declared like that having NULL as the default value. So while calling procedure if you don't supply #UPA, it will assume NULL) that you need to supply while calling the procedure like
exec [dbo].[SP_Set_LMS_BY_ERW] #UPA=N'test123'
whereas Declare #count nvarchar(30) is a local variable that's going to be use for some intermediary calculation or manipulation or to store some local data within your procedure body.