How to create sp_executesql to drop tables dynamicaly - sql

For some reasons, I am trying to create a dynamic script to drop tables that I created before. I couldnt do the syntax right and I need help for this matter.
When I run my script, it gives the error:
"Procedure expects parameter '#statement' of type 'ntext/nchar/nvarchar'."
and this is my script. It has an error in sp_executesql statement, I guess. How can I fix this?
DECLARE #sql VARCHAR(MAX);
DECLARE #tmpTableName VARCHAR(max);
SET #tmpTableName = '##gmAAA_COLLATION';
SET #sql = 'DROP TABLE #tmpTableName';
EXEC sp_executesql #sql, N'#tmpTableName NVARCHAR(max)', #tmpTableName;

You cannot do this with static SQL, i.e. a table name can never be a parameter in SQL statements like these. This is also true for column names, schema names etc.
If you want to do this using sp_executesql, you can build the SQL dynamically as follows:
SET #sql = 'DROP TABLE '+QUOTENAME(#tmpTableName);
EXEC sp_executesql #sql;
PS: The #stmt parameter of the sp_executesql procedure needs to be of type NVARCHAR(...).

SET #sql = 'DROP TABLE '+#tmpTableName;
EXEC sp_executesql #sql;

The sp_executesql requires nvarchar for the #stmt and #params parameters
so change the data Types of variables form varchar to be nvarchar as following
DECLARE #sql NVARCHAR(MAX);
DECLARE #tmpTableName VARCHAR(max);

Try the following query:-
SET #sql = 'DROP TABLE #tmpTableName'; EXEC (#sql)
OR
DECLARE #sql NVARCHAR(MAX);
DECLARE #tmpTableName NVARCHAR(max)
SET #tmpTableName = '##gmAAA_COLLATION';
SET #sql = 'DROP TABLE'+QUOTENAME(#tmpTableName);
EXEC sp_executesql #sql,N'#tmpTableName NVARCHAR(max)',#tmpTableName

Related

Invalid Column name error during execution of stored procedure

I am not able to execute the stored procedure. It is throwing an error
Invalid Column name 'DW201401'
Command used to execute the stored procedure:
exec RM_UTIL_MODE server,'DW201401'
Stored procedure code:
ALTER Procedure [dbo].[RM_UTIL_MODE]
#ServerName varchar(50),
#Value varchar(50)
As
Begin
declare #query nvarchar(max)
set #query = N'SELECT mode FROM ' + #ServerName +
N'.master.dbo.sysdatabases WHERE name =' + #Value
exec sp_executesql #query
End
But when I tried to run the query alone as shown below it is giving me result.
select mode, name
from server.master.dbo.sysdatabases
where name = 'DW201401'
Presumably, the issue is quotes around #Value:
declare #query nvarchar(max)
set #query = N'SELECT mode FROM '
+ #ServerName
+ N'.master.dbo.sysdatabases
WHERE name = '''+#Value+'''';
However, I would use parameter substitution instead:
declare #query nvarchar(max) ;
set #query = N'SELECT mode
FROM ' + #ServerName + N'.master.dbo.sysdatabases
WHERE name = #value';
exec sp_executesql #query, N'#value varchar(50)', #value = #value;
You are already using sp_executesql, so you might as well use it properly. Note: you cannot substitute the server name.
EDIT:
To elaborate on the comment, I would write the code this way:
declare #sql nvarchar(max) ;
set #sql = N'
SELECT mode
FROM #ServerName.master.dbo.sysdatabases
WHERE name = #value';
set #sql = replace(#sql, '#ServerName', quotename(#ServerName));
exec sp_executesql #sql, N'#value varchar(50)', #value = #value;
When using dynamic SQL, I no longer piece together the query using string concatenation. Instead, I put in place holders and use replace(). I find that concatenation is hard to maintain and often obscures what the SQL is doing. Although there is a bit more overhead in using replace() (and I often do it multiple times), it is worth it for preventing errors and maintaining the code (plus, my queries tend to run for a while anyway, so the overhead is minimal compared to the query time).
Your select looks like:
select mode, name from server.master.dbo.sysdatabases where name = DW201401
so you need to add escaped quotes in your dynamic query:
exec RM_UTIL_MODE cefmtqcfindv3,'DW201401'
ALTER Procedure [dbo].[RM_UTIL_MODE]
#ServerName varchar(50),#Value varchar(50)
As
Begin
declare #query nvarchar(max)
set #query = N'SELECT mode FROM '
+ #ServerName
+ N'.master.dbo.sysdatabases
WHERE name ='''+#Value+''''
exec sp_executesql #query
End
Just as a suggestion, when you are building a dynamic sql, try using PRINT instead of EXEC, then get what is printed and try it out. Most of the times you will know what went wrong.
Just as an example:
ALTER Procedure [dbo].[RM_UTIL_MODE]
#ServerName varchar(50),#Value varchar(50)
As
Begin
declare #query nvarchar(max)
set #query = N'SELECT mode FROM '
+ #ServerName
+ N'.master.dbo.sysdatabases
WHERE name ='''+#Value+''''
PRINT #query
--exec sp_executesql #query
End

Declare variable and use in query

Please consider the following
declare #MyField varchar(255);
set #MyField = 'MyDatabaseField';
select distinct Table.#MyField
from Table
This results in the error Incorrect syntax near #MyField. Then I tried:
select distinct Table.['+#MyField+']
from Table
However, this results in an Incorrect column name error.
How do I correctly use the #MyField in this query? I'm on SQL Server 2008.
Please try executing by building a string.
declare #MyField varchar(255);
set #MyField = 'MyDatabaseField';
exec ('select distinct Table.'+#MyField+' from Table')
Refer sp_executesql (Transact-SQL), Using sp_executesql
You should use dynamic SQL to achieve that. You can use sp_executesql stored proc to do that. Please not that I changed your variable declaration to **N**VARCHAR.
declare #MyField nvarchar(255)
set #MyField = N'MyDatabaseField'
declare #sql nvarchar(max) = N'select distinct ' + #MyField + N' from TableName'
exec sp_executesql #sql

Execute Stored Procedure from Stored Procedure w/ dynamic SQL capturing output

Inside a stored procedure (A) I need to call a stored procedure (X) inside a specific database and capture the output. X returns a single value.
From what I understand I need to provide the DB name of X to the stored procedure in A and I need to use dynamic SQL to build the query on execution targeting the desired database.
What am unable to figure out is how to capture output from X in A to work with the result.
You could use sp_executesql to dynamically call your nested Stored Procedure.
DECLARE #db AS SYSNAME
DECLARE #return_value AS INT
DECLARE #output_value AS INT
DECLARE #sql AS NVARCHAR(MAX)
-- Set your DB name
SET #db = N'mydb'
/*
Use sp_executesql to dynamically pass in the db and stored procedure
to execute while also defining the values and assigning to local variables.
*/
SET #sql = N'EXEC #rtn = ' + #db + '.dbo.[your_stored_procedure] #output OUTPUT'
EXEC sp_executesql #sql
, N'#rtn AS INT, #output AS INT OUTPUT'
, #return_value = #rtn
, #output_value = #output OUTPUT
Adding to the above answer, following is the way to call stored procedures dynamically by passing parameters.
DECLARE #SpName VARCHAR(1000)
SELECT #SpName = DeleteLiveSP FROM dbo.ArchivalInfo (NOLOCK) WHERE TableName = #TableName
DECLARE #SqlString nvarchar(2000)
DECLARE #ParamDef nvarchar(2000)
SET #SqlString = N'exec '+#SpName + ' #CriteriaParam'
SET #ParamDef = N'#CriteriaParam XML'
EXECUTE sp_executesql #SqlString ,#ParamDef, #CriteriaParam = #Criteria

How to pass a table variable using sp_executesql

I'm trying to create a table using sp_executesql but I keep getting an error that says "Incorrect syntax near '#_TableName'. Any idea what I'm doing wrong here?
Here's the code that I'm using:
DECLARE #SQLString NVARCHAR(MAX),
#ParamDefinition NVARCHAR(MAX),
#TableName NVARCHAR(MAX);
SET #TableName = N'[dbo].[MyTable]';
SET #SQLString = N'SELECT * FROM #_TableName;';
SET #ParamDefinition = N'#_TableName NVARCHAR(max)';
EXEC sp_executesql #SQLString, #ParamDefinition,
#_TableName = #TableName;
That yields the error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '#_TableName'.
If I hard code the table name and the column type (I have to do both) then the query works, otherwise I get the incorrect syntax message for both those variables.
In case you're wondering, I want to put this code inside a stored procedure, so that if anyone wants to create or modify a table then they call this stored procedure which can run additional validations.
Figured out the problem.
Apparently sp_executesql expects the parameter definition for a table to be of a table type (see this answer for an example: https://stackoverflow.com/a/4264553/21539).
An easier way to solve this problem was to insert the variables names directly into the SQLStatement string as follows:
DECLARE #SQLString NVARCHAR(MAX),
#TableName NVARCHAR(MAX);
SET #TableName = N'[dbo].[MyTable]';
SET #SQLString = N'SELECT * FROM ' + #TableName + ';';
SET #ParamDefinition = N'#_TableName NVARCHAR(max);
EXEC sp_executesql #SQLString;

Create table with instruction into #parameter in stored procedure

I want to create a table from this code in SQL Server, but the stored procedure returns an error
CREATE PROCEDURE Recovery_CountryCode (#NombreTabla SYSNAME)
AS
DECLARE #ParamDefinition nvarchar(500);
DECLARE #SQLString nvarchar (4000);
SET #SQLString=N'SELECT Name
INTO #TableName
FROM AdventureWorks2008R2.Production.Location';
SET #ParamDefinition=N'#TableName SYSNAME';
EXECUTE sp_executesql #SQLString, #ParamDefinition, #TableName=#NombreTabla;
GO
I want avoid define table
When I call the stored procedure:
EXEC Recovery_CountryCode #NombreTabla='Paises';
I get the follow message:
Mens. 102, Nivel 15, Estado 1, LĂ­nea 2
Sintaxis incorrecta cerca de '#TableName'.
You can just concatenate the SQL inside your procedure
CREATE PROCEDURE Recovery_CountryCode (#NombreTabla SYSNAME)
AS
DECLARE #ParamDefinition nvarchar(500);
DECLARE #SQLString nvarchar (4000);
SET #SQLString=N'SELECT Name INTO ' +
#NombreTabla +
' FROM AdventureWorks2008R2.Production.Location';
EXECUTE sp_executesql #SQLString
GO
You can't bind variables to table names in this way. You need to do something like
Declare #sql nvarchar(max), #NombreTable sysname = 'Test'
Set #sql = N'Select Name Into ' + #NombreTable +
N' From AdventureWorks2008R2.Production.Location
exec sp_executesql #sql
http://www.sommarskog.se/dynamic_sql.html is recommended reading.