use master
Declare #CID integer = 1114
Declare #dbname varchar(50)
set #dbname = (select DatabaseName from [Clients].[dbo].[Client] where clientid = #CID)
select #dbname
alter database #dbname
set single_user with rollback immediate
drop database #dbname
delete from [Clients].[dbo].[client] where clientid = #CID
But I get errors
Msg 102, Level 15, State 1, Line 7
Incorrect syntax near '#dbname'.
Msg 319, Level 15, State 1, Line 7
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
Msg 102, Level 15, State 1, Line 7
Incorrect syntax near 'immediate'.
your problem isn't with the declaration, it's with the usage here
alter database #dbname set single_user with rollback immediate
There are places where you can use variables in sql statements, typically in the where clause, but there are some limitations on where you can use them.
You could go with something like this
use master
Declare #CID integer = 1114
Declare #dbname nvarchar(50)
set #dbname = (select DatabaseName from [Clients].[dbo].[Client] where clientid=#CID)
select #dbname
declare #sql nvarchar (2000) = N'alter database '+ #dbname + N' set single_user with rollback immediate'
exec sp_executeSql #sql
select #sql = N'drop database ' + #dbname
exec sp_executeSql #sql
delete from [Clients].[dbo].[client] where clientid=#CID
Please try following script first on a development or test instance before you use it on a productive one
use master
Declare #CID integer = 1114
Declare #dbname varchar(50)
set #dbname = (select DatabaseName from [Clients].[dbo].[Client] where clientid=#CID)
--select #dbname
declare #sql nvarchar(max)
set #sql = 'use ' + #dbname + '
alter database ' + #dbname + ' set single_user with rollback immediate
use master
drop database ' + #dbname
print #sql
-- exec sp_executesql #sql
delete from [Clients].[dbo].[client] where clientid=#CID
Please note that before I drop the database, I switch to master database using "USE master"
To drop database uncomment "exec sp_executesql #sql" statement
I used a PRINT command so that you can see what you will execute before hand.
You can find info on how to run dynamic sql using sp_executesql at given tutorial with sample
Related
I use dynamic sql to create database an tables
this is sql script
DECLARE #DatabaseName VARCHAR(50) = N'test';
EXECUTE ('CREATE DATABASE [' +#DatabaseName+']');
EXECUTE('USE ' + #DatabaseName)
GO
CREATE SCHEMA [Framework]
GO
the error I get
Msg 2714, Level 16, State 6, Line 1
There is already an object named 'Framework' in the database.
Msg 2759, Level 16, State 0, Line 1
CREATE SCHEMA failed due to previous errors
.
this error because EXECUTE('USE ' + #DatabaseName) not work
I try to use
SET #SQL02 = 'USE ['+ convert(nvarchar(50),#DatabaseName) +']; SELECT DB_NAME();'
exec sp_executesql #SQL02
but not work
what I can do?
DECLARE #Query VARCHAR(200);
SET #Query = CONCAT('USE ', QUOTENAME('<MyDatabase>'), '; ', 'select DB_NAME();');
EXECUTE (#Query);
This will return <MyDatabase> as long as you remain within one EXECUTE.
I prefer this form for remote execution:
declare #sql nvarchar(max) = N'select Db_Name()';
<DatabaseName>.sys.sp_executesql #sql;
You can put this logic into a more convenient form by making into a stored procedure:
create procedure dbo.usp_ExecuteSqlCommand (
#databaseName sysname
, #sqlCommand nvarchar(max)
)
as
begin;
set nocount on;
set xact_abort on;
declare #innerStatement nvarchar(max) = #sqlCommand;
declare #outerStatement nvarchar(max);
set #databaseName = QuoteName(ParseName(#databaseName, 1), N'[');
set #outerStatement = #databaseName + N'.sys.sp_executesql #stmt = #innerStatement;';
execute sys.sp_executesql
#stmt = #outerStatement
, #params = N'#innerStatement nvarchar(max)'
, #innerStatement = #innerStatement;
end;
Usage is obvious:
execute dbo.usp_ExecuteSqlCommand
#databaseName = N'master'
, #sqlCommand = N'select Db_Name();';
Try this:(if you use execute, the db context will change only for that execute only)
DECLARE #DatabaseName VARCHAR(50) = N'test';
EXECUTE ('CREATE DATABASE [' +#DatabaseName+']');
use [test]
go
CREATE SCHEMA [Framework]
GO
Consider the following queries, where only database name differs (on same server)
Select * from sampledev.dbo.Sample
Select * from sampleqa.dbo.Sample
The above queries are part of a procedure. Every time I have to run the procedure, I have to make sure it references the correct database (and do rename, if it is not).
I want to pass the database name as a parameter to the stored procedure. The question is, is it possible? If yes, how?
You can accomplish this using sp_executesql
DECLARE #Database NVARCHAR(255),
#Query NVARCHAR(MAX)
SET #Database = 'Database'
SET #Query = N'SELECT * FROM ' + #Database + '.dbo.Table'
EXEC sp_executesql #Query
Something as simple as: ?
CREATE PROC GetData
(
#DatabaseName VARCHAR(255)
)
AS
BEGIN
IF #DatabaseName = 'sampledev'
SELECT * FROM sampledev.dbo.Sample
ELSE IF #DatabaseName = 'sampleqa'
SELECT * FROM sampleqa.dbo.Sample
END
Use:
exec GetData 'sampledev'
Results
dev data
(1 row(s) affected)
exec GetData 'sampleqa'
Results
qa data
(1 row(s) affected)
Just like the leading answer but without SQL injection vulnerability.
First you must query the sys.databases in order to be sure to get the real Database name while not counting on the users text:
SELECT #Database = [name]
FROM sys.databases
WHERE [name] = #Database;
Now perform the query using sp_executesql:
DECLARE #Query nvarchar(200);
SET #Query = N'SELECT * FROM ' + #DBName + '.dbo.sample';
EXEC sp_executesql #Query
Full Stored procedure:
CREATE PROCEDURE [MyScheme].[MyStoredProcedure]
(
#DBName sysname
)
AS
BEGIN
SET NOCOUNT ON;
SELECT #DBName = [name]
FROM sys.databases
WHERE [name] = #DBName;
DECLARE #Query nvarchar(200);
SET #Query = N'SELECT * FROM ' + #DBName + '.dbo.sample';
EXEC sp_executesql #Query
END
GO
dECLARE #LS_SQL CHAR(100)
dECLARE #SQL varCHAR(max)
SET #LS_SQL=ltrim('''STOCK IN HAND'',''STORE'',''PRODUCT''')
set #SQL='SELECT * FROM ITEM WHERE GROUPNAME IN(' + rtrim(#LS_SQL) + ')'
PRINT #SQL
execute #SQL
result
SELECT * FROM ITEM WHERE GROUPNAME IN('STOCK IN
HAND','STORE','PRODUCT') Msg 2812, Level 16, State 62, Line 9 Could
not find stored procedure 'SELECT * FROM ITEM WHERE GROUPNAME
IN('STOCK IN HAND','STORE','PRODUCT')'.
This command
execute #SQL
run a procedure. If you wan to run dynamic sql you should use below command:
exec (#SQL)
you can also use
execute sp_sqlexec #SQL
I suggest to use sp_executesql, like:
exec sp_executesql #stmt = #SQL
you can see more help here Dynamic SQL - EXEC(#SQL) versus EXEC SP_EXECUTESQL(#SQL)
try this
dECLARE #LS_SQL CHAR(100)
dECLARE #SQL varCHAR(max)
SET #LS_SQL=ltrim('''STOCK IN HAND'',''STORE'',''PRODUCT''')
set #SQL='SELECT * FROM ITEM WHERE GROUPNAME IN(' + rtrim(#LS_SQL) + ')'
PRINT #SQL
execute sp_sqlexec #SQL
I am totally confused with this procedure.please correct my mistakes in quotes.
create procedure queryingsfor
#Tabname nvarchar(250),
#colname nvarchar(250),
#opname nvarchar(290),
#valuesname nvarchar(239)
as
begin
set NOCOUNT on;
declare #sql varchar(4000)
set #sql='select * from' +#Tabname+ 'where' +#colname+''''+#opname+''''+ ''''+#valuesname+''''
exec(#sql)
end
exec queryingsfor 'education','eduCurrentStudy','=','DME'
I'm only getting:
Error: Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'fromeducationwhereeduCurrentStudy'.
You might want to add some spaces in there
set #sql='select * from ' +#Tabname+ ' where '
+#colname+''''+#opname+''''+ ''''+#valuesname+''''
The correct statement would be something like
set #sql='select * from ' +#Tabname+ ' where '
+#colname + #opname+ ''''+#valuesname+''''
Or
even better
set #sql='select * from [' +#Tabname+ '] where
[' +#colname + ']' + #opname+ ''''+#valuesname+''''
To protect you from SQL injection you should do like this instead.
alter procedure queryingsfor
#Tabname nvarchar(250),
#colname nvarchar(250),
#opname nvarchar(4),
#valuesname nvarchar(239)
as
begin
set NOCOUNT on;
declare #sql nvarchar(4000)
set #sql = 'select * from '+quotename(#Tabname)+ ' where ' +quotename(#colname)+#opname+'#valuesname'
exec sp_executesql #sql, N'#valuesname nvarchar(239)', #valuesname
end
I have created a stored procedure that will drop a table if it exists in a database. When running the stored procedure with EXEC, I am getting the following error:
Msg 203, Level 16, State 2, Procedure
sp_DropIfExists, Line 13 The name 'IF
EXISTS(SELECT 1 FROM sys.objects WHERE
OBJECT_ID = OBJECT_ID(N'table_name')
AND type = (N'U')) DROP TABLE
[table_name]' is not a valid
identifier.
However if i copy and paste the T-SQL that is generated into management studio, it seems to be running fine. Can someone explain why this is not valid? The fix would be nice, but I am really after the Why primarily, The How would be nice to though! Thanks in advance.
ALTER PROCEDURE [dbo].[sp_DropIfExists](#tableName VARCHAR(255))
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL VARCHAR(MAX);
SET #SQL = 'IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N''' + #tableName + ''') AND type = (N''U'')) DROP TABLE [' + #tableName + ']'
PRINT #SQL;
EXEC #SQL;
END
you can use sp_execute
sp_executesql #SQL
for more information msdn document link
Not sure if this will solve your problems but you would be better placing you check is a function like so
CREATE FUNCTION [dbo].[TableExists]
(
#TableName VarChar(100)
)
RETURNS BIT
AS
BEGIN
DECLARE #TableExists BIT
IF EXISTS(SELECT name FROM sysobjects a
WHERE a.name = #TableName
AND a.xtype = 'U')
SET #TableExists = 1
ELSE
SET #TableExists = 0
RETURN #TableExists
END
Then you can use it as follows.
IF dbo.TableExists('[table_name]') = 1
DROP TABLE [table_name]
Try this and let me know if you still get the same error.
--ALTER (if procedure exists)
CREATE PROCEDURE sp_dropifexists (#tableName VARCHAR(255))
AS
BEGIN
DECLARE #SQL VARCHAR(MAX);
SET #SQL = 'IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N''' + #tableName + ''') AND type = (N''U'')) DROP TABLE [' + #tableName + ']'
--if write EXEC #SQL without parentheses sql says Error: is not a valid identifier
EXEC (#SQL);
END
--test procedure
exec sp_DropIfExists 'table'
EXEC #SQL should be EXEC (#SQL). (But #maycil's suggestion is correct too.)
Turns out, without the parentheses #SQL's value is interpreted as the name of a stored procedure to execute, not as a script. (I didn't know that before, but I made a small test to verify that it is indeed so.)