I am trying to insert a few values into a table using EXECUTE statement.
I have found few examples, however, those does not answer my question.
Note: sources given below are code from the procedure. All mentioned variables was declared and initialized.
First way I tried:
results in:
Error: Procedure or function has too many arguments specified.
And I completely understand why I am getting this. Because sp_executesql does not allow to have more than 4 arguments, and it cannot recognise which goes where.
Second try (where I only want to get the output using execute statement into the variable, and then put that into the table):
And I get:
Must declare scalar variable "#crlf"
and actually this variable is declared in the top of this procedure, but this one is not that clear for me, why it still complains...
What would be the most sufficient way to get the execution statement and the number(additional value) into the table?
As an only workaround I can suggest using a temporary table. Should be quite simple:
SELECT TOP (0) column1
INTO #TemporaryResults
FROM [master].[dbo].[table_1];
INSERT INTO #TemporaryResults
EXECUTE sp_executesql #sql, N'#object_id INT, #crlf CHAR(2)', #object_id, #crlf;
INSERT INTO [master].[dbo].[table_1] (column1, column2)
SELECT column1, 1
FROM #TemporaryResults;
Create a copy of column1 from [table_1] column1
Insert records, produced by SP into it
Insert records to actual table
Please try according with following example
DECLARE #IntVariable int;
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #max_title varchar(30);
SET #IntVariable = 197;
SET #SQLString = N'SELECT #max_titleOUT = max(JobTitle)
FROM AdventureWorks2012.HumanResources.Employee
WHERE BusinessEntityID = #level';
SET #ParmDefinition = N'#level tinyint, #max_titleOUT varchar(30) OUTPUT';
EXECUTE sp_executesql #SQLString, #ParmDefinition, #level = #IntVariable, #max_titleOUT=#max_title OUTPUT;
SELECT #max_title;
OBSERVATION
SQL query needs a parameter #level that is why we have declare it as parameter
again the SQL query returns the output at #max_titleOUT. So we also have declare it as parameter. so the final parameter list is
SET #ParmDefinition = N'#level tinyint, #max_titleOUT varchar(30) OUTPUT';
now we have to send the #level value to dynamic query that's why we use #level = #IntVariable that sends the #IntVariable value to #level
Finally by #max_titleOUT = #max_title OUTPUT we take the output of dynamic query that saves at #max_titleOUT, copy the value to #max_title
Related
I have written a stored procedure Where I have written a query to get userid. There is a separate database for every userid. So I am trying to run a select query based on this userid obtained from my previous select query in a loop.
And I am trying to assign the columns in this select query to variables declared and use them further. But I am not understanding how to assign these to variables as I am getting errors
USE DATABASE1
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [User].[update_client_details]
AS
DECLARE
#clientdata CURSOR,
#clientid INT,
#SQL VARCHAR(2000),
#uid INT
#isactive INT,
#createdDate Date
BEGIN
SET #clientdata = CURSOR FOR
SELECT clientuserid FROM User.queen_client
OPEN #clientdata
FETCH NEXT
FROM #clientdata INTO #clientid
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = N'SELECT #uid=userid, #isactive=isactive, #createdDate=createddate FROM ['+CAST(#clientid AS NVARCHAR(20))+'].User.queen_user';
EXEC (#SQL)
IF(#isactive = 1)
BEGIN
//do someting//
END
END
CLOSE #clientdata
DEALLOCATE #clientdata
END
if the execute the store procedure it is getting executed and not stopping. If I force stop the execution then I am getting the error as "must declare the scalar variable "uid""
Query Which I tried
EXEC sys.sp_executesql N'SELECT #uid=userid, #isactive=isactive, #createdDate=createddate FROM ' +QUOTENAME(#clientid)+'.QueenBase.queen_user', N'#clienid int, #uid int OUTPUT, #createDate date OUTPUT';
Variables only persist and exist within the scope that they are declared in. Therefore both the following batches will fail:
DECLARE #I int = 1;
EXEC (N'SELECT #i;');
GO
EXEC (N'DECLARE #I int = 1;');
SELECT #i;
When using dynamic SQL, don't use EXEC(#SQL);, use sp_executesql. Then you can parametrise the statement. For example:
DECLARE #I int = 1;
EXEC sys.sp_executesql N'SELECT #i;', N'#i int', #i;
This returns 1. If you need to return a value to the outer SQL, as a parameter, you need to use OUTPUT parameters:
DECLARE #I int = 10;
DECLARE #O int;
EXEC sys.sp_executesql N'SELECT #O = #I / 2;', N'#I int, #O int OUTPUT', #I, #O OUTPUT;
SELECT #O;
This assigns the value 5 to the variable #O (which is then selected).
Also, don't use N'...[' + #SomeVariable + N'] ...' to inject dynamic values, it's not injection safe. Use QUOTENAME: N'...' + QUOTENAME(#SomeVariable) + N'...'
Additional note. The fact that you need to do something like N'FROM ['+CAST(#clientid AS NVARCHAR(20))+'].User.queen_user' suggests a severe design flaw, but that's a different topic.
If you do fancy additional reading, I cover a lot of considerations you need to take into account in my article Dos and Don'ts of Dynamic SQL.
For your attempt, it's not working as you use an expression for the first parameter (not a literal or variable) and then don't pass any of the parameters you define:
DECLARE #SQL nvarchar(MAX) = N'SELECT #uid=userid, #isactive=isactive, #createdDate=createddate FROM ' +QUOTENAME(#clientid)+'.QueenBase.queen_user;';
EXEC sys.sp_executesql #SQL, N'#isactive int OUTPUT, #uid int OUTPUT, #createDate date OUTPUT', #isactive OUTPUT, #uid OUTPUT, #createDate OUTPUT;
My Dynamic SQL queries have been placed inside a table. I want to read these from the table (in SQL server), do a parameter substitution, then execute the dynamic query.
i.e. Column GetFieldServerSQL contains the following:
SELECT top 1 Tenancy.LeadName
FROM Tenancy
RIGHT OUTER JOIN Property ON Tenancy.KeyProperty = Property.KeyProperty
WHERE (Tenancy.EndDate IS NULL) and Property.KeyProperty = #PropertyID
This is what I have tried:
declare #sql nvarchar(1000)
declare #sql2 nvarchar(1000)
declare #res nvarchar(1000)
declare #result nvarchar(1000)
set #sql = 'SELECT [GetFieldServerSQL]
FROM [SVSCentral].[dbo].[SVSSurvey_ExternalField] where ID=5'
exec #res = sys.sp_executesql #sql
print #res
This returns my query in the Results window, but I want it as a variable. #res only contains a 0 (for success)
Once I have it as a variable, I want to do a substitution. Something like:
set #sql2 = REPLACE(#result,'#propertyID','1003443')
(supposing #result is where my results is stored)
And then execute it:
exec (#sql2)
Instead of doing this:
exec #res = sys.sp_executesql #sql
You need to insert the results into a table, then select from that table, like this:
DECLARE #resTable TABLE (res nvarchar(1000))
INSERT INTO #resTable (res)
exec (#sql)
SELECT #res=res from #resTable
print #res
I have a procedure with following code
CREATE PROCEDURE customer_panel_insert(
#Panel_Name VARCHAR(200),
#Panel_description VARCHAR(5000),
#Type_of_change CHAR(5))
AS
DECLARE #data_set VARCHAR(MAX);
DECLARE #sql VARCHAR(MAX);
begin
set #sql = 'select * from customer_details where panel_type = 1 AND PANEL_DATATYPE = ''VARCHAR'''
exec #sql
END
I want to change the varchar datatype to nvarchar and char to nchar. Change the varchar variable with size more than 4000 characters to NVARCHAR(MAX). I want to change with help of a query.
Is there any query that can replace
Hope this works for you. Be careful before executing it.
update sys.sql_modules set definition = REPLACE(definition,'VARCHAR(5000)','NVARCHAR(MAX)')
where definition like '%VARCHAR(5000)%'
I'm trying to verify a job number exists on a linked server and get back a variable (#JobExists) indicating whether it does or not (1 for yes, 0 for no).
To do this I'm trying to use OPENQUERY along with sp_executesql as I have to pass in a parameter for the job number. I've tried the code below but get the error 'Procedure expects parameter '#statement' of type 'ntext/nchar/nvarchar'. For testing purposes I've declared and set the variable #JobNumber.
DECLARE #JobNumber as varchar(50)
SET #JobNumber = '2112111'
DECLARE #JobExists as BIT
DECLARE #JobCount as int
DECLARE #ParmDefinition as varchar(100)
DECLARE #sql as varchar(500)
SET #JobExists = 0
SET #ParmDefinition = N'#Result int output'
SET #sql = 'SELECT #Result = SELECT COUNT(*) FROM OPENQUERY(MYLINKEDSVR,''SELECT JOB_NUMBER FROM PROD.tbl1 WHERE JOB_NUMBER = ''''' + UPPER(RTRIM(LTRIM(#JobNumber))) + ''''''')'
exec sp_executesql #sql, #ParmDefinition, #Result = #JobCount output
IF #JobCount > 0
SET #JobExists = 1
SELECT #JobExists
I've read up sp_executesql here: http://technet.microsoft.com/en-us/library/ms188001.aspx
I've also done various searches but haven't come across any answers that work for me.
Is there something I'm missing?
The error message is clear: you must declare #sql as nvarchar and not as varchar.
The same for #ParamDefinition:
DECLARE #ParmDefinition as nvarchar(100)
DECLARE #sql as nvarchar(500)
Is there any way to pass a tsql function a database name so it can perform selects on that database
ALTER function [dbo].[getemailjcp]
(
#DB_Name varchar(100)
)
Returns varchar(4000)
AS
BEGIN
DECLARE #out varchar (4000);
DECLARE #in varchar (1000);
Set #out =
(select substring
((select ';' + e.email from
(SELECT DISTINCT ISNULL(U.nvarchar4, 'NA') as email
FROM [#DB_Name].dbo.Lists ...
In order to create dynamic SQL statement you should store procedure. For example:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+#DatabaseName+'].[dbo].[SourceTable]'
EXECUTE sp_executesql #DynamicSQLStatement,#ParmDefinition,#FirstID=#FirstID OUTPUT
SELECT #FirstID
In this example:
#DatabaseName is the passed as parameter to your procedure.
#FirstID is output parameter - this value might be return from your procedure.
Here you can find more information about "sp_executesql":
http://msdn.microsoft.com/en-us/library/ms188001.aspx
a better solution might be to replace "#DatabaseName" (a char variable)with:
"DB_NAME(<#DBId>)".
You can then continue to pass in the db names, but 1st converting them to IDs in the fcn. Also kinda resolves the contradiction of building a SQL stmt w/ a char variable in it, if using "sp_executesql" to help guard against SQL injection ("DB_NAME()" isn't a variable/can't be substituted).
So you'd have this:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
DECLARE #DBId INT
SET #DBId = DB_ID(#Db_Name) --raise the proper security/robustness** concern if this doesn't resolve.
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+DB_NAME(#DBId)+'].[dbo].[SourceTable]'