I'm having to build my query dynamically, firstly, it gets the maxlogid from the log, and appends this to the temporary table name. Then it does a COALESCE to return the distinct values into a string.
However, the output of the string, I want to have in a parameter, so I can use it again later on within a dynamic sql query.
Here is my code;
DECLARE #maxLogId VARCHAR(10)
SELECT #maxLogId = (SELECT Max(id) FROM dbo.tLog)
DECLARE #PolicyTempTable VARCHAR(100)
SET #PolicyTempTable = '##tPols' + #maxLogId
DECLARE #emailParm NVARCHAR(1000)
SET #emailParm = N'DECLARE #email VARCHAR(MAX)
SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm
The results are returned as follows;
"abc#a.co.uk",""abc#b.co.uk"
I want to be able to write the sp_executesql into a seperate parameter, so I can use for a dynamic query like below;
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + '' EXEC sp_executesql #emailParm + '' + ')'')'
However, I can't use the sp_executesql within my dynamic query.
You can use parameters with sp_executesql
DECLARE #emailParm NVARCHAR(1000)
DECLARE #emailOut NVARCHAR(MAX)
SET #emailParm = N'SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm, N'#email VARCHAR(1000) OUTPUT', #email = #emailOut OUTPUT
Then you can build your second dynamic sql
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + #emailOut + ')'')'
Related
I am trying to insert data into a SQL Server table using a variable. I tried
DECLARE #table NVARCHAR(50) = 'ToolList',
#val NVARCHAR(50) = 'test'
EXEC ('INSERT INTO ' + #table + 'SELECT ' + #val)
and
EXEC ('INSERT INTO ' + #table + '([col1]) VALUES(' + #val +')'
but still get an error that says
Incorrect syntax near 'test'.
you missed a space before SELECT and the #val should enclosed in single quote
DECLARE #table nvarchar(50) = 'ToolList',
#val nvarchar(50) = 'test'
EXEC ( 'INSERT INTO ' + #table + ' SELECT ''' + #val + '''')
when you use Dynamic SQL, it is easier to form the query in a variable so that you can print out , inspect the value before execution
select #sql = 'INSERT INTO ' + #table + ' SELECT ''' + #val + ''''
print #sql
exec (#sql)
You'd better use sp_executesql that allows for statements to be parameterized, to avoid the risk of SQL injection.
DECLARE #Query NVARCHAR(1000),
#table NVARCHAR(50) = 'ToolList'
SET #Query = 'INSERT INTO ' + #table + ' SELECT #val'
EXEC sp_executesql #Query, N'#val nvarchar(50)', #val = 'test'
sp-executesql-transact-sql
You can also use CHAR(39) instead of adding single quotes every time for better readability. And also, you have not added a space after the variable which contains the table name.
Query
declare #table nvarchar(50) = 'ToolList',
#val nvarchar(50) = 'test2';
declare #sql as varchar(max) = 'insert into ' + #table
+ ' select ' + char(39) + #val + char(39);
exec(#sql);
You need 4 singlequotes before the #val field as it is a string and all strings needs to be encapsulated in single quotes.
You can print the dynamic string using PRINT command check what the final string you are going to execute.
DECLARE #table VARCHAR(50) = 'ToolList'
DECLARE #val VARCHAR(50) = 'test'
DECLARE #DSQL AS VARCHAR(MAX) = ''
SET #DSQL = #DSQL + ' INSERT INTO [' + #table + ']' + '
SELECT ' + '''' + #val + ''''
--PRINT #DSQL
EXEC(#DSQL)
DECLARE #ompid NVARCHAR(max)
DECLARE #Names VARCHAR(max)
SELECT #Names = COALESCE(#Names + ') as ' + Variable_Name + ' ,AVG(', 'AVG(') + Variable_Name
FROM charttest
WHERE ompid = 125
DECLARE #lastcol NVARCHAR(100) = (
SELECT TOP 1 (Variable_Name)
FROM charttest
WHERE ompid = 125
ORDER BY Variable_Name ASC
)
DECLARE #Names2 NVARCHAR(500) = #Names + ') as ' + #lastcol + ''
DECLARE #sql NVARCHAR(500)
SET #sql = 'SELECT ' + #Names2 + ' FROM ompvaribles'
EXEC (#sql)
This is my sql query i had show second table avg but not getting second table records.
I'm not sure what is actually not working with your query (I'm assuming you get an error), but in order to execute the dynamic query you've build you need to use:
exec sp_executesql #sql
Please see the SQL code below:
declare #Classification as varchar(5)
set #Classification =''
declare #ClassificationSQL as nvarchar(4000)
set #ClassificationSQL=''
declare #cnt int
declare #counts int
DECLARE NicheDeletionOffenderCursor CURSOR FOR
select classification from dbnicheoffenderclassificationlookup
Open NicheDeletionOffenderCursor
FETCH NEXT FROM NicheDeletionOffenderCursor INTO #Classification
WHILE ##FETCH_STATUS = 0
BEGIN
If #ClassificationSQL=''
set #ClassificationSQL='classification like ' + char(39) + '%' + #Classification + '%' + char(39)
else
set #ClassificationSQL=#ClassificationSQL + ' OR classification like ' + char(39) + '%' + #Classification + '%' + char(39)
FETCH NEXT FROM NicheDeletionOffenderCursor INTO #Classification
END
CLOSE NicheDeletionOffenderCursor
DEALLOCATE NicheDeletionOffenderCursor
SET #ClassificationSQL = 'select count(*) as cnt from person where id=903 and (' + #ClassificationSQL + ')'
EXECUTE sp_executesql #ClassificationSQL, N'#cnt int OUTPUT', #cnt=#Counts OUTPUT
How do I assign the count output from #ClassificationSQL to a variable to use in the next part of the TSQL?
There are several things to mention here:
No need to declare the variable used inside of the dynamic sql (i.e. #cnt) outside of it (i.e. at the top)
No need for a cursor as a simple SELECT #var = #var + column construct will concatenate
With no cursor, there is no need to declare the variable used with it (i.e. #Classification)
Single-quotes can be escaped by using two of them (i.e. ''). However, it could simply be preference to use CHAR(39) instead as some people find it to be more readable.
Setting a variable in dynamic SQL is just like regular SQL (i.e. SELECT #var = expression FROM...)
End result:
DECLARE #ClassificationSQL NVARCHAR(4000)
DECLARE #Counts INT
SET #ClassificationSQL = COALESCE(#ClassificationSQL + N' OR ', '')
+ N'classification LIKE ''%'
+ classification
+ N'%'''
FROM dbnicheoffenderclassificationlookup
SET #ClassificationSQL =
N'SELECT #TempCount = COUNT(*) FROM person WHERE id = 903 AND ('
+ #ClassificationSQL
+ N')'
EXECUTE sp_executesql
#ClassificationSQL,
N'#TempCount INT OUTPUT',
#TempCount = #Counts OUTPUT
SELECT #Counts
See a below sample about how you can get the output of a dynamic query (tested in SQL Server 2008 R2). Actual post from where the idea is taken How to get sp_executesql result into a variable?
DECLARE #retval int;
DECLARE #SQL nvarchar(500);
DECLARE #Param nvarchar(500);
DECLARE #table nvarchar(50)
SELECT #table = N'newperson'
SELECT #SQL = N'SELECT #retvalOUT = MAX(salary) FROM ' + #table;
SET #Param = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #SQL, #Param, #retvalOUT=#retval OUTPUT;
SELECT #retval;
You can make changes to your procedure accordingly.
Could someone explain why the following gives me "Must declare the scalar variable #facilities." but works fine if I were to use VARCHAR instead of my created type? How can I fix this?
TIA
--CREATE TYPE integer_list AS TABLE (n int NOT NULL PRIMARY KEY)
--DROP PROCEDURE spTestTVP
CREATE PROCEDURE spTestTVP (
#facilities integer_list READONLY
--#facilities varchar(100)
)
AS
DECLARE #sql nvarchar(4000)
SET #sql = 'SELECT * FROM TestTable'
SET #sql = #sql + ' WHERE 1=1 '
IF #facilities IS NOT NULL
SET #sql = #sql + ' AND (FacilityNo IN (' + #facilities + ') OR FacilityNo IS NULL)'
EXEC sp_executesql #sql
DECLARE #items VARCHAR(MAX)
SELECT#items = COALESCE(#items+',' ,'') + n
FROM #facilities
DECLARE #sql nvarchar(4000)
SET #sql = 'SELECT * FROM TestTable'
SET #sql = #sql + ' WHERE 1=1 '
IF #facilities IS NOT NULL
SET #sql = #sql + ' AND (FacilityNo IN (' + #items + ') OR FacilityNo IS NULL)'
EXEC sp_executesql #sql
or not dynamic as follows:
SELECT t.* FROM TestTable as t
left outer join
#facilities as f
on
f.n = t.FacilityNo
where
t.FacilityNo is null
or
f.n is not null
When you are concatenating things in a dynamicSQl statment all pieces that build the statement must be either varchar or nvarchar. That is a limit of SQL.
On the other hand you don't need dynamic sql since you have created a table.
SELECT * FROM TestTable t
LEFT join #facilities f on f.n = t.facilityNO
I want to write query in which name table will dynamicaly compute. I have code like this below. What should I put in 'magic code' region?
DECLARE #myTableName nvarchar(100) = 'sch'
+ CAST(#nowYear as VARCHAR(5))
+ 'Q'
+ CAST(#nowQuarter as VARCHAR(3))
+ '.[tVisits]'
-- magic code --
myTable = DoSomething(#aktTableName)
-- magic code --
SELECT * FROM myTable
I use MS SQL Server 2012
You need use the dynamic SQL -
DECLARE
#nowYear INT = 2013
, #nowQuarter INT = 1
DECLARE #myTableName NVARCHAR(100) = '[sch'
+ CAST(#nowYear AS VARCHAR(5))
+ 'Q'
+ CAST(#nowQuarter AS VARCHAR(3))
+ '].[tVisits]'
DECLARE #SQL NVARCHAR(MAX) = N'SELECT * FROM ' + #myTableName
EXEC sys.sp_executesql #SQL
Instead of SELECT * FROM myTable
You need to do something like
DECLARE #sql nvarchar(4000)
SELECT #sql = ' SELECT * FROM ' + #myTable -- #myTable is a string containing qualified table name
EXEC sp_executesql #sql
Note that sp_executesql allows for a parameterized query - check its documentation