how to pass variables this in dynamic query in sql - sql

i using the dynamic query to pass the variables
select a.TableName, COUNT(a.columnvalue) as '+'count'+' from Settings a
where a.ColumnValue in ('+ #columnvalue +') and a.Value in (' + #value +')
the #columnvalues = 'a','b','c'
#value ='comm(,)','con(:)'
how to pass this in dynamic query
any idea???

I would use the sp_executesql command.
Some more documentation is here: http://msdn.microsoft.com/en-us/library/ms188001.aspx
Basically, you define a sql query, and parameter list, and then pass those in along with your actual parameters into that method.
So, something like this (real basic)
CREATE PROCEDURE dbo.yourProc
#customerId INT
AS
DECLARE #sql NVARCHAR(1000)
SET #sql = 'SELECT * FROM Customers WHERE CustomerId = #customerId'
DECLARE #params NVARCHAR(1000)
SET #params = '#customerId INT'
EXEC dbo.sp_executesql #sql, #params, #customerId

Related

Can I create a stored procedure to select a table from a database with the database name as a variable? [duplicate]

I'm looking to pass my database name as a parameter to the stored procedure, and I'm looking to use it in the where condition to set the database of the stored procedure. But I get an error:
Incorrect syntax near '.'
Sample Code
Create proc [dbo].[stored_procedure_one]
#variable1 int,
#dbname varchar(10)
as
begin
select *
from #dbname..table_name
End
Can someone suggest me how to solve this?
You will need to use dynamic sql for this something like this.....
Create proc [dbo].[stored_procedure_one]
#variable1 int,
#dbname SYSNAME --<-- use appropriate data type for object names
as
begin
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N' select * from ' + QUOTENAME(#dbname) + N'..table_name'
Exec sp_executesql #Sql
End
Also use QUOTENAME() function to protect yourself against possible sql-injection attack.
Just to offer an alternative, it's fun to note that EXEC can take a string as the thing to execute, so for example:
DECLARE #sp nvarchar(255) = N'sys.sp_who2';
EXEC #sp;
It can also take parameters, e.g.
DECLARE #sp nvarchar(255) = N'sys.sp_who2';
EXEC #sp 'active';
So we can dynamically build the context where we run a command by using:
DECLARE #dbname sysname = N'tempdb';
DECLARE #context nvarchar(1000) = QUOTENAME(#dbname)
+ N'.sys.sp_executesql';
DECLARE #sql nvarchar(max) = N'SELECT DB_NAME();';
EXEC #context #sql;
And you can pass parameters, too:
DECLARE #dbname sysname = N'tempdb';
DECLARE #context nvarchar(1000) = QUOTENAME(#dbname)
+ N'.sys.sp_executesql';
DECLARE #sql nvarchar(max) = N'SELECT DB_NAME(), #x;';
EXEC #context #sql, N'#x int', 5;
This approach really simplifies things like concatenating the database name all over the place, avoiding db-specific functions like object_name, and ensures that your entire command runs in that other database. You can also do it across linked servers, e.g.:
DECLARE #server sysname = N'linked_server';
DECLARE #dbname sysname = N'tempdb';
DECLARE #context nvarchar(1000) = QUOTENAME(#server)
+ N'.' + QUOTENAME(#dbname)
+ N'.sys.sp_executesql';
...

SQL add a variable to a query

How do I create variables that are specified once and then used in queries later in a script? These variables may be used multiple times in a query, and in multiple queries in a script. I use #x as such a variable in the examples below.
What I want to do is something like:
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ' + #x + ' as [TestCase]
From mytable'
Exec (#Query)
-- returns "Invalid column name 'test'"
Which returns the error mentioned above. I would like it to achieve the equivalent of:
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ''test'' as [TestCase]
From mytable'
Exec (#Query)
-- Returns e.g.
-- Name TestCase
-- Alice Test
-- Bob Test
I also note that the following doesn't work and returns the same error as the first:
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ' + 'test' + ' as [TestCase]
From mytable'
Exec (#Query)
-- returns "Invalid column name 'test'"
Based on the error and since I'm not trying to use the #x as a column name, but just as a variable, I assume I'm using an invalid implementation of a variable.
Since you're not trying to use a variable as a column name, you do not need to use dynamic SQL at all. (Which is a Good Thing(TM) since dynamic SQL should only be used with a great deal of caution due to it being a great attack surface.)
A simple:
declare #x nvarchar(40)
set #x = 'test'
select [Name], #x as TestCase
from mytable
will do.
That being said, if you have a use case for dynamic SQL (again the particular query in question here does not but perhaps an ad-hoc query is being passed in to the procedure), the thing to do would be to pass your variable as a parameter to the query via sp_executesql. This is akin to creating a stored procedure with parameters:
declare #x nvarchar(40)
declare #query nvarchar(1000)
set #x = 'test'
set #query = 'select [Name], #x as TestCase from mytable'
exec sp_executesql #query, N'#x nvarchar(1000)', #x
You were missing quotes. Thats it. Try below code.
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ''' + #x + ''' as [TestCase]
From mytable'
Exec (#Query)
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name],'++''''+#x+''''+ ' as [TestCase]
From mytable'
print #query
Output:
Select [Name],'test' as [TestCase]
From mytable

Call sp_executesql with varchar parameter

I faced problem when I called sp_executesql and I passed varchar parameter.
I got this error:
Procedure expects parameter '#statement' of type
'ntext/nchar/nvarchar'.
Psychic debugger says you either are passing to SP_ExecuteSQL a variable of type varchar (make it nvarchar), or you've got a string you haven't used the unicode prefix on:
E.g.
Exec sp_executesql 'select * from something'
To fix it use:
Exec sp_executesql N'select * from something'
Notice the N prefix on the string.
This means the #statement parameter of sp_executesql expects nvarchar.
This does not mean that your parameter has to be nvarchar.
Of course, if you don't have parameters, why are you using sp_executesql?
CREATE TABLE #foo (bar varchar(100) NOT NULL);
DECLARE #filter varchar(100) = 'bob';
EXEC sys.sp_executesql
N'SELECT * FROM #foo WHERE bar = #p1', --NVARCHAR because of N prefix
N'#p1 varchar(100)', --NVARCHAR because of N prefix
#filter --VARCHAR
DROP TABLE #foo
Try this :
e.g. This will give the error because #SQL needs to be NVARCHAR
Below give error:
DECLARE #SQL VARCHAR(100)
SET #SQL = 'SELECT TOP 1 * FROM sys.tables'
EXECUTE sp_executesql #SQL
So: Use NVARCHAR(100)
DECLARE #SQL NVARCHAR(100)
SET #SQL = 'SELECT TOP 1 * FROM sys.tables'
EXECUTE sp_executesql #SQL

How to pass an output variable in dynamic sql query

I was reviewing a stored procedure where I found piece of code below. Looking at the code, my perception is that we are creating a variable named #QuestionInclude and passing its value in dynamic sql statement. But how this code is working?
This is something strage and new to me.
declare #QuestionInclude varchar(10)
select #sqln = 'select #QuestionInclude = 1 from ##Stg_Prelim'
exec sp_executesql #sqln,N'#QuestionInclude varchar(10) output',#QuestionInclude output
may be this will help you
http://msdn.microsoft.com/en-us/library/ms188001.aspx
procedure sp_executesql have parameters #stmt, which is actual statement to run, #params - declaration of parameters, and then all parameters declared in #params
It's also better to pass parameters by names
declare #QuestionInclude varchar(10), #stmt nvarchar(max), #params nvarchar(max)
select #stmt = 'select #QuestionInclude = 1 from ##Stg_Prelim'
select #params = '#QuestionInclude varchar(10) output'
exec sp_executesql
#stmt = #stmt,
#params = #params,
#QuestionInclude = #QuestionInclude output

Selecting from a table where the name is passed as a variable

I am trying to write a simple stored proc which takes three arguments 'database name one', 'database name two' and 'table name'. The sql will then perform a row count for the defined table in each database and store it.
Working on it piecemeal I have hit the first problem in that you can't do
select * from #tablename
I know you can use dynamic sql with the exec command but this is not ideal as I can't return values.
The following example looks like it should work but doesn't.
declare #tablename as nvarchar(500)
declare #sqlstring as nvarchar(500)
declare #parmdefinition as nvarchar(500)
declare #numrows as bigint
set #tablename = N'dummy_customer'
set #parmdefinition = N'#tablenameIN nvarchar(500), #numrowsOUT as bigint OUTPUT'
select #sqlstring = 'select #numrowsOUT = count(*) from #tablenameIN'
select #sqlstring
exec sp_executesql #sqlstring, #parmdefinition, #tablenameIN = #tablename, #numrowsOUT = #numrows OUTPUT
select #numrows
The error message given is
Msg 1087, Level 16, State 1, Line 1
Must declare the table variable "#tablenameIN".
Currently using SQL Server 2008 SP2.
Edit:
We're doing this because we are doing a migration and the customer wants a report which shows the row count for each table in the source and destination database. As there are many tables being able to use sp_MSForEachTable to call the stored proc seems ideal.
Edit:
The final solution for future reference is
declare #tablename as nvarchar(500)
declare #sqlstring as nvarchar(500)
declare #parmdefinition as nvarchar(500)
declare #numrows as bigint
set #tablename = N'dummy_customers'
set #parmdefinition = N'#tablename nvarchar(500), #numrowsOUT as bigint OUTPUT'
select #sqlstring = 'select #numrowsOUT = count(*) from ' + quotename(#tablename)
exec sp_executesql #sqlstring, #parmdefinition, #tablename = #tablename, #numrowsOUT = #numrows OUTPUT
select #numrows
You'd have to use dynamic sql, and concatenate the table name into the SQL string to then execute via sp_executsql:
select #sqlstring = 'select #numrowsOUT = count(*) from ' + QUOTENAME(#tablename)
EXECUTE sp_executesql ....