I have a stored procedure which is implemented in Dynamic SQL. I am trying to include an IN keyword and pass fixed values in the list between single quotes.
I want to write something like this:
where grp.Status in ('A,S')
but the above statement is already encapsulated in single quotes.
I tried using something like the one below:
where grp.Status in (' +QUOTENAME('A,S','''')+
but the query is only recognizing the first value in the list i.e. 'A'.
I also read about using a split function and putting the values in a temp table and using the temp table's column instead. But, I don't was to do that process for a tiny list.
Any suggestions and solutions are greatly appreciated.
You can just put the list into the SQL:
'where grp.Status in (''' + replace('A,S', ',', ''',''') + ''') . . .
If I got those single quotes right, this should produce the result as:
where grp.Status in ('A','S') . . .
If you do not want to use the split function you can do the following with your dynamic sql.
declare #xml xml
, #list Varchar(100) = 'A,B'
set #xml = N'<root><r>' + replace(#list, ',' ,'</r><r>') + '</r></root>'
Declare #Sql Nvarchar(MAX);
SET #Sql = N'Select * from TableName grp
WHERE grp.Status IN (
select r.value(''.'',''varchar(max)'') as item
from #xml.nodes(''//root/r'') as records(r)
)'
Exec sp_executesql #Sql
,N'#xml XML'
,#xml
Related
I'm trying to use the value from a variable being passed through from elsewhere in my where statement but i'm struggling on syntax.
I have a field that is being passed through where the value with in it is essentially a list
ie #Var1 where the value being passed through is AA','BB','CC (ie its missing the leading ' and trailing '
i want to use this value in my where statement as a list eg
where
field1 IN #Var1
ie - the actual result I want is
where
field1 IN ('AA','BB','CC')
I don't have any control over what is being passed through (ie AA','BB','CC will always be missing the leading and trailing ', so how do i use that info in the IN clause in the WHERE?
I seem to be coming up against issues with syntax around the use of the '
I hope that makes sense, its not the easiest thing to explain and its still relatively new to me
Here an example for my approach in the comments above:
CREATE PROCEDURE test_r(#x varchar(4000))
AS
BEGIN
DECLARE #t TABLE (keys NVARCHAR(10))
DECLARE #sql_xml XML = CAST('<root><X>'+REPLACE(#x, char(39)+','+char(39), '</X><X>') + '</X></root>' AS XML)
INSERT INTO #t(keys)
SELECT f.x.value('.', 'VARCHAR(10)') AS y
FROM #sql_xml.nodes('/root/X') f(x)
SELECT *
-- FROM [MyTable] m INNER JOIN...
FROM #t
END
GO
DECLARE #x AS nvarchar(4000) = 'AA' + char(39) + ',' + char(39) + 'BB' + char(39) + ',' + char(39) + 'CC'
EXEC test_r #x
Depending on what you have to do with the result of your query, you might want to create a function instead of a procedure.
I have a SELECT statement that can produce a list of values:
DECLARE #ValueList varchar(Max);
SELECT #ValueList = COALESCE(#ValueList + ',', '') + CAST(Val AS varchar(max))
FROM
(SELECT TOP (100) PERCENT tblSampleTable.SomeIDNumber AS Val
FROM tblSampleTable) AS ValuesThisYear
PRINT #ValList
This returns a list with values something like
val1,val2,val4,val9,
etc., ehich I can then feed into a stored procedure, or manage some other way.
Now I want to have the query that gets assessed for the list of values to be dynamic, maybe passed in or from another stored procedure, similar to this:
DECLARE #ValueList varchar(Max);
DECLARE #TSQL varchar(Max);
SET #TSQL = {stored proc to get base query}
SELECT #ValueList = COALESCE(#ValueList + ',', '') + CAST(Val AS varchar(max))
FROM
(#TSQL) AS ValuesThisYear
PRINT #ValList
I know that's the wrong syntax for including #TSQL, and that's what I'm trying to find out. I've viewed a number of threads and tried a number of methods, but am still not able to incorporate this dynamic part.
The tricky part seems to be the making of the list (the COALESCE and CAST statements), where I incorporate #ValList as part of the returned string.
Any help would be appreciated!
Dynamic SQL is usually about
Creating a variable that contains the exact SQL you want to run
Then using EXEC (#SQLvariable) to run that code
For example (not for production yet!) I've added a new variable #CustomSQL
DECLARE #ValueList varchar(Max);
DECLARE #TSQL varchar(Max);
DECLARE #CustomSQL varchar(Max);
SET #TSQL = {stored proc to get base query}
SET #CustomSQL =
'SELECT COALESCE(#ValueList + '','', '''') + CAST(Val AS varchar(max))
FROM (
' + #TSQL + '
) As ValuesThisYear;'
PRINT #CustomSQL
EXEC (#CustomSQL)
Notice that adding text/strings (e.g., the #TSQL variable) have to be entered as exact strings rather than their variable names. Also note apostrophes - you need to use '' every time you wish to refer to a '.
I also removed the variable name from the SELECT #ValueList = ... because the dynamic SQL cannot actually reference the variables - it has its own scope (?cannot remember the correct word) and doesn't have access to the variables. Solutions to this include
Using a temporary table e.g., #temp which can be referenced
Using the OUTPUT clause
Personally, I would approach it a different way - use the T-Sql provided to put data into a temporary table. Then use the temporary table in the other statement e.g.,
DECLARE #ValueList varchar(Max);
DECLARE #TSQL varchar(Max);
SET #TSQL = {stored proc to get base query}
DECLARE #CustomSQL varchar(Max)
CREATE TABLE #temp (Val varchar(1000))
SET #CustomSQL = 'INSERT INTO #temp (Val) ' + #TSQL
EXEC (#CustomSQL)
SELECT #ValueList = COALESCE(#ValueList + ',', '') + CAST(Val AS varchar(max))
FROM #temp As ValuesThisYear;
PRINT #ValList
I almost never get my dynamic SQL correct first try. Suggestions
Keep it as simple as possible
Before having a version that runs (e.g., EXEC (#CustomSQL)), comment the EXEC out and PRINT it instead.
Here are some examples from previous posts I've done recently
Query for R Machine Learning Services - Filtering Categories in Where Clause
Bottom of Dynamic columns depend on previous dynamic columns - TSQL
I am a beginner in Dynamic SQL and trying to write a dynamic sql code in which I need to include a table variable .When I try to include the table variable I am getting an error saying that I need to include the Static variable.
Below is just part of the code
DECLARE #NAMES TABLE (name varchar)
DECLARE #fields varchar(max);
.
.
.
Select #fields=FROM sys.columns
WHERE object_id=object_id('dbo.employees')
order by name
SET #SQL=''
SET #SQL='Select '+ #fields
SET #SQL=#SQL + ' from dbo.test()'
SET #SQL = #SQL + ' WHERE name IN'
SET #SQL= #SQL + '(Select name from '
SET #SQL=#SQL + #NAMES +')'
To start with, your SELECT to get the column names won't work at all. You need something like this:
DECLARE #fields nvarchar(max);
SET #fields = N'';
SELECT #fields += CASE WHEN LEN(#fields) = 0 THEN N'' ELSE N', ' END + name
FROM sys.columns
WHERE object_id=object_id('dbo.employees')
ORDER BY column_id
PRINT #fields;
I'm honestly not sure what the rest of your SQL is trying to do... it's trying to select the fields from the employee table from the return of a table-valued function called test()? Where the 'name' column from that test() result set is in ... what? You'll need to be a lot more clear before I can give you a complete answer. One major problem is that you've never actually filled your table variable with anything, so ... I have no idea what you're going for. Knowing the definition of the Test() function would also be helpful.
But at least the above will give you the #fields variable set correctly to the list of columns in the table dbo.employee.
When doing Dynamic SQL, it really helps to write out the end resulting SQL you want, and then identify what parts of that SQL should be filled in by variable data, and work backwards. It's then a lot easier to construct your SQL to build your dynamic SQL.
You need to include the tablevariable logic to dynamic sql
--You need to load #names inside dynamic sql
DECLARE #fields varchar(max);
.
.
.
Select #fields=FROM sys.columns
WHERE object_id=object_id('dbo.employees')
order by name
SET #SQL='DECLARE #NAMES TABLE (name varchar); '
SET #SQL +=' Select '+ #fields
SET #SQL=#SQL + ' from dbo.test()'
SET #SQL = #SQL + ' WHERE name IN'
SET #SQL= #SQL + '(Select name from '
SET #SQL=#SQL + ' #NAMES )'
Or you can load into temp table and access the temptable inside dynamic sql. This means you will be loading temptable like #names and then use that in dynamic sql...
I have the following sql query
Select * from Name
where surname in ('test1', 'test2')
which works
But I wanted to do the following
DECLARE #Surname as VARCHAR(100)
set #Surname = 'test1' + ',' + 'test2'
Select * from Name
where surname in #Surname
this is the actual query used
DECLARE #COESNo as VARCHAR(100)
set #COESNo = '121108883' + ',' + '121108890'
declare #sql varchar(max)
set #sql = 'select [LEI_ACCEPT] , [PREFERED_LEI] , [INSPECTION_COMPANY], [INSP_ACCEPT] from [CERTIFICATE_DETAILS] where [Certificate_no] in ('
set #sql = #sql + #COESNo + ')'
exec #sql
get the error
The name 'select [LEI_ACCEPT] , [PREFERED_LEI] , [INSPECTION_COMPANY], [INSP_ACCEPT] from [CERTIFICATE_DETAILS] where [Certificate_no] in (121108883,121108890)' is not a valid identifier.
doesn't seem to work
any ideas
There are two popular solutions.
First one is to build string with query and use sp_executesql to run it.
Second one is to write (or find) function (something like SplitText2Table()) which converts comma separated string to table and write query which use this function -- something like:
select *
from name
where surname in (select item from SplitText2Table(#surnames))
This is not a solution for the exact problem in the question. But maybe (?) you could instead use this workaround:
declare #SurName1 nvarchar(20)
declare #SurName2 nvarchar(20)
set #SurName1='test1'
set #SurName2='test2'
select * from [Name] where [surname] in (#SurName1, #SurName2)
you will need to create your statement and execute - like
declare #sql varchar(max)
set #sql = 'Select * from [Name] where surname in ('
set #sql = #sql + #surname + ')'
After creating the statement just say
exec #sql
You can also check the formed query is correct or not using print
print #sql
Please use print before execution of the command (this will help you in correcting the query is there is any error.).
EDIT:
As per the comment - Since Name is a keyword for SQL - we will need to use square bracket against it. I have modified the statement in my answer.
Edit 2: Based on further comments -
Firstly I would like to know the datatype of Certificate_no column in your database.
If it is a varchar field you will need to have single quotes around each value.
The name SELECT [LEI_ACCEPT] , [PREFERED_LEI] , [INSPECTION_COMPANY], [INSP_ACCEPT] FROM[CERTIFICATE_DETAILS] WHERE [Certificate_no] IN ('121108883','121108890')
You will need to create -
DECLARE #COESNo as VARCHAR(100)
set #COESNo = '''121108883''' + ',' + '''121108890'''
Since Certificate number is varchar the string build will need a single quote in formed query which will appear with three single quotes.
I have created Working DEMO for you on SQL FIDDLE - CLICK HERE
declare #A varchar(5000)
declare #B varchar(5000)
select #A=value from drp.Parameter where parameteridname='IV01'
--result of this query ('DIM003966','DIM000736','DIM025297',
-- 'DIM025302','DIM027583')
select [InventLocationId],[WMSLocationId] from ItemKit.InventDim
where inventdimid in (#A)
i am not getting any result out of second query but if i run them individually and use result of 1st query in second i am getting it. is there any way around to run them together
That is because it evaluates #a as is (as text, not a list of values).
You should create a sql statement on the fly and execute it:
declare #sqlStatement nvarchar(4000)
#sqlStatement = 'select [InventLocationId],[WMSLocationId] from ItemKit.InventDim where inventdimid in (' + #A + ')'
execute sp_executesql #sqlStatement
But as said by others, don't use unless really necessary.
You should use this code:
select [InventLocationId],[WMSLocationId] from ItemKit.InventDim
where inventdimid in (select value from drp.Parameter where parameteridname='IV01')
As you have a single string value (holding all the values) you could either:
Parse sql on the fly
Note: I do not recommend this, as it can allow sql injection
(see #Patrick Hofman's answer for good example of this)
Use like
declare #A varchar(5000)
declare #B varchar(5000)
select #A=value from drp.Parameter where parameteridname='IV01'
--result of this query ('DIM003966','DIM000736','DIM025297',
-- 'DIM025302','DIM027583')
SELECT #A /* Here you will see the problem, as it is not multiple values,
it is a single string with a comma & quote (') delimited list */
SELECT
[InventLocationId], [WMSLocationId]
FROM
ItemKit.InventDim
WHERE
/* parse up the inventdimid to include the quote (') around it */
#A like '%''' + #inventdimid + '''%'