Dynamic SQL Server Nested EXEC - sql

I'm trying to EXEC a stored procedure inside an nvarchar that I a them executing.
I receive the following error, Msg 2812, Level 16, State 62, Procedure Map.AdminServiceLoad, Line 127 [Batch Start Line 2]
Could not find stored procedure ''.
The stored procedures I am referencing exist, I had re-started MSSQL, am I unable to EXEC with an EXEC ?
DECLARE #NewStoredProc nvarchar(max) = '
create procedure [Map].[Load'+#TableName+']
as
begin
DECLARE #MapTable nvarchar(100) = [Map].['+#TableName+']
DECALRE #MapDevlTable nvarchar(100) = [MapDevl].['+#TableName+']
DECLARE #ShapesAreValid bit
DECLARE #PointsAreValid bit
EXEC #ShapesAreValid = Map.AdminServiceValidateShapes #TableName = #MapDevlTable
EXEC #PointsAreValid = Map.AdminServiceValidatePoints #TableName = #MapDevlTable
if(#ShapesAreValid = 1 and #PointsAreValid = 1)
begin
INSERT INTO [Map].['+#TableName+'] SELECT('+#ColsToLoad+') FROM [MapDevl].['+#TableName+']
end
end
'
EXEC #NewStoredProc
return 1

It would need to be EXEC(#cmd) not EXEC #cmd.
Without the parentheses it looks to find a stored procedure with the same name as the string inside #cmd.

Related

Create trigger in CREATE DATABASE stored procedure

We have a stored procedure that creates a database for each of our customers. This stored procedure runs in the context of master. A database name is passed in as a parameter to the stored procedure.
I am trying to modify the stored procedure to add a trigger to a table. I understand the stored procedure must switch to the new database to create triggers, so have appended the following to the stored procedure:
SET #str = ('USE ' + QUOTENAME (#db_name) + ' GO
CREATE TRIGGER ...')
EXEC (#str);
I get the error
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near 'GO'.
Msg 111, Level 15, State 1, Line 4
'CREATE TRIGGER' must be the first statement in a query batch.
Now I assume the second error is a consequence of the first, but I am blowed if I can work out how to switch databases in the stored procedure in order to create the triggers.
We are using SQL Server 2019. How do I create triggers in a create database stored procedure?
Another approach is to execute statement one after another.
DECLARE #str VARCHAR(MAX)
DECLARE #db_name SYSNAME = 'YourDBName'
SET #str = 'USE ' + QUOTENAME (#db_name)
EXEC (#str)
SET #str = 'CREATE TRIGGER ...'
exec (#str);
For completeness, as mentioned by #DaleK, adding the approach mentioned by Aaron Bertnard in the Stackexchange link
DECLARE #str VARCHAR(MAX)
DECLARE #db_name SYSNAME = 'master'
SET #str = 'EXEC '+ #db_name + '..sp_executesql #stmt=N''CREATE PROCEDURE usp_test AS SELECT 1;'''
exec (#str);

Dynamic Query is not working with cursor in SqlServer 2008 Stored Procedure

I am building a stored procedure in Sql Server 2008. Stored Procedure has two arguments which are the column names of a table. In stored procedure I used dynamic query for fetching data of these two columns with the help of Cursor.
Code:
Create PROCEDURE TestSP
(
#firstAttribute nvarchar(max),
#secondAttribute nvarchar(max)
)
AS
DECLARE #x FLOAT
DECLARE #y INT
DECLARE #query nvarchar(max)
DECLARE #cursor_query nvarchar(max)
DECLARE #result_Cursor as cursor
BEGIN
SET #query = 'Select '+ #firstAttribute+','+#secondAttribute+' from TBL_TEST_DATA_NEW'
SET #cursor_query =' set #cursor = cursor for ' + #query +' open #cursor;'
PRINT 'CURSOR_QUERY'+#cursor_query
exec sys.sp_executesql
#cursor_query
,N'#cursor cursor output'
,#result_Cursor output
FETCH NEXT FROM result_Cursor INTO #x, #y
But when I am executing this SP it is giving me following error
Msg 16916, Level 16, State 1, Procedure TestSP, Line 33
A cursor with the name 'result_Cursor' does not exist.
Execute Command :
Exec TestSP "Column_1","Column_2"
Can someone tell me why I am getting this error
Please Help..
Thanks
The error is saying that Cursor does not exist. You can't start with "set cursor". Also cursor name is without #.
So try using
declare cursorNameHere cursor for SELECT ...
open cursorNameHere
#result_Cursor is a variable, just change your last line to
FETCH NEXT FROM #result_Cursor INTO #x, #y
see example on sql fiddle demo
change
PRINT 'CURSOR_QUERY'+#cursor_query
to
PRINT 'CURSOR_QUERY '+#cursor_query

How Can i Let Stored Procedure Returns Varchar Value?

Here is my sample:
ALTER PROCEDURE EmpFirstName
#myParam int,
#empFName varchar(20) output
AS
BEGIN
SET NOCOUNT ON;
SELECT #empFName = empfname
FROM FE_QEMP
WHERE empno = #myParam
END
GO
myParam is the input and empFName will carry the output, so the procedure
should only take 1 parameter since empFName is the output, but in my case
i get this error:
Msg 201, Level 16, State 4, Procedure
EmpFirstName, Line 0 Procedure or
function 'EmpFirstName' expects
parameter '#empFName', which was not
supplied.
This is the way i called the procedure:
DECLARE #returnValue varchar(20)
EXEC #returnValue = EmpFirstName 10
SELECT 'Return Value ' = #returnValue
Return values and output parameters are two different things. If you want to call it with an output parameter, you'd do it like this:
EXEC EmpFirstName 10, #returnValue OUTPUT
SELECT 'Return Value ' + #returnValue
If you want to call it in the manner that you described in your example, then you need to alter the stored procedure to state RETURNS VARCHAR(20) and remove the output parameter. To return a value, you have to explicitly call return. In your example, you'd declare a variable, assign it in the select statement, then call return #varName.
Thanks. My aha moment came with this post. Did not realise that output parameters need to be qualified with the "output" identifier too when executed, not just in the procedure!
Here are my test workings for my fellow sql server noobs. I am using sqlcmd with sql server 2005.
The stored procedure:
/* :r procTest.sql */
if exists (select name from sysobjects where name="procTest" and type="P")
drop procedure procTest;
go
create procedure procTest
/* Test stored procedure elements. */
(#i_pt_varchar varchar(20),
#o_pt_varchar varchar(20) output)
as
begin
print "procTest";
set #o_pt_varchar = "string coming out";
print "#i_pt_varchar " + #i_pt_varchar;
print "#o_pt_varchar " + #o_pt_varchar;
return (0);
end
go
The test call:
/* :r procTest.test.sql */
declare #returnFlag int;
declare #i_varchar varchar(20);
declare #o_varchar varchar(20);
set #i_varchar = "string going in";
set #o_varchar = null;
execute #returnFlag = procTest #i_varchar, #o_varchar output
print "#returnFlag " + cast(#returnFlag as varchar(20));
print "after call";
print "#i_varchar " + #i_varchar;
print "#o_varchar " + #o_varchar;
go

Dynamically call a stored procedure from another stored procedure

I want to be able to pass in the name of a stored procedure as a string into another stored procedure and have it called with dynamic parameters. I'm getting an error though.
Specifically I've tried:
create procedure test #var1 varchar(255), #var2 varchar(255) as
select 1
create procedure call_it #proc_name varchar(255)
as
declare #sp_str varchar(255)
set #sp_str = #proc_name + ' ''a'',''b'''
print #sp_str
exec #sp_str
exec call_it 'test'
So procedure call_it should call procedure test with arguments 'a', and 'b'.
When I run the above code I get:
Msg 2812, Level 16, State 62, Procedure call_it, Line 6
Could not find stored procedure 'test 'a','b''.
However, running test 'a','b' works fine.
you need parentheses
exec (#sp_str)
if the proc didn't exists the message would be this
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'test'.
it would not be Could not find stored procedure 'test 'a','b''
Although still a bad idea with SQL injection, try using sp_executeSQL and use parameters, see here about query plan reuse: Changing exec to sp_executesql doesn't provide any benefit if you are not using parameters correctly
You should use the "sp_executesql" procedure. Look at MSDN - sp_executesql.
You don't need any kind of dynamic SQL (EXEC() or sp_executesql) at all to achieve this result:
create procedure test #var1 varchar(255), #var2 varchar(255)
as
BEGIN
select #var1, #var2;
END;
create procedure call_it #proc_name varchar(255)
as
BEGIN
declare #param1 VARCHAR(255) = 'a'
,#param2 VARCHAR(255) = 'b';
exec #proc_name #param1, #param2; --it isn't dynamic-SQL(simple procedure call)
END;
exec call_it #proc_name = 'test';
DBFiddle Demo
From EXECUTE:
[ { EXEC | EXECUTE } ]
{
[ #return_status = ]
{ module_name [ ;number ] | #module_name_var }
#module_name_var
Is the name of a locally defined variable that represents a module name.
This can be a variable that holds the name of a natively compiled, scalar user-defined function.

Use database dynamically

This execution is giving me the following error:
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'go'.
Msg 111, Level 15, State 1, Line 11
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
If i remove the "GO" it gives me just the second one.
Any hints of what am I missing?
declare #dbname varchar(500)
set #dbname='master'
Exec ('
Use ' + #dbname + '
go
create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu =
''CREATE DATABASE '' + #dbname
exec (#stringu)
End
')
Answer
declare #dbname varchar(500)
set #dbname='kontabel'
Exec(
'Use ' + #dbname +'
Exec (''
create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu =
''''create DATABASE '''' + #dbname
exec (#stringu)
End
'')
')
Actually I tried like this and it worked but I had to change quotes.
The real procedure that I would like to use is more than 50000 lines and I can't go and manually change the quotes to everything.
Is there a better way?
Two issues:
Using "GO" is incorrect... there is no SQL keyword called "GO"... that's just a hack that SQL Server Management Studio is performing for you.
You need to the CREATE PROCEDURE command in it's own context... simple.
Here's the slight modification to your script:
declare #dbname varchar(500)
set #dbname='master'
Exec ('
Use ' + #dbname + '
EXECUTE(''create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu =
''''CREATE DATABASE '''' + #dbname
exec (#stringu)
End'')
')
So the answer is to put another "EXECUTE" command inside the first EXECUTE command. I do this all the time, a lot of times in an "sp_msforeachdb". You can nest those bad boys as long as you want.
Sometime ago I had code which was updating database structure based on scripts.
I end up with split file by 'go' and execute separately each fragment. Can you try this?
So, first exec use statement, and than exec createprocedure.
Be sure to verify that it is created in proper database
My mistake, I didn't notice something.
maybe it's the Exec inside the Exec that's causing the error?
or because your'e assigning a nvarchar(2000) to a nvarchar(100)
"Msg 102, Level 15, State 1, Line 5 Incorrect syntax near 'go'. Msg 111, Level 15, State 1, Line 11 'CREATE/ALTER PROCEDURE' must be the first statement in a query batch. " If i remove the "GO" it gives me just the second one.
try this without any use or go: create PROCEDURE '+#dbname+'.[dbo].[krijo_database] #dbname nvarchar(2000)
You can't use GO like that
It isn't a SQL command
It tells SSMS to split the batch
If you remove it, then you'll get "first in batch" error which is expected
In this case, why not just do this...
Use master
GO
create PROCEDURE [dbo].[krijo_database] #dbname nvarchar(2000), #Direktoria varchar(4000)
AS
BEGIN
declare #stringu nvarchar(100)
set #stringu = 'CREATE DATABASE ' + #dbname
exec (#stringu)
End
GO
Why do need dynamic SQL to create a stored procedure?
USE master
GO
CREATE PROCEDURE dbo.create_database #name nvarchar(100)
AS
DECLARE #sql nvarchar(100)
SET #sql = 'CREATE DATABASE ' + QUOTENAME(#name)
EXEC (#sql)
GO
What you're after can't be done I don't think.
See this article for reference
The Real procedure that i would like to use it is a very big one, more dhan 50000 lines and i can't go on an changing the quotes to everything
Microsoft SQL Server has a maximum length of varchar of 8000 characters.
http://www.databasejournal.com/features/mssql/article.php/3788256/Data-Types-in-SQL-Server-2008.htm
you should create stored procedure with that portion with variable.
I used SQl DMO!
Great feature both for 32 and 64 bit,compatible with both SQL express and server!