This question already has answers here:
Passing a varchar full of comma delimited values to a SQL Server IN function
(27 answers)
Closed 7 years ago.
I would like to retrieve certain users from a full list of a temp table #temptable.
The query looks like this:
DECLARE #List varchar(max)
SELECT #List = coalesce(#List + ',','') + '''' + StaffCode + ''''
FROM tblStaffs
SELECT UserName
FROM #temptable
WHERE #temptable.StaffCode IN (#List)
I can tell #List is in a right format:
'AAA','ABB','BBB','CCC','DDD','MMM'
And if I change it to
WHERE #temptable.StaffCode IN ('AAA','ABB','BBB','CCC','DDD','MMM')
It certainly works, then why not IN (#List)?
Create some split string function and convert the comma separated values to rows then you can use the converted rows IN clause
DECLARE #List VARCHAR(max)
SELECT #List = COALESCE(#List + ',', '') +StaffCode
FROM tblStaffs
SELECT UserName
FROM #temptable
WHERE #temptable.StaffCode IN (SELECT split_values
FROM dbo.Splitstring_function(#list))
Check here for various Split String function
If you dont want to create functions then you can also directly use the code instead of creating a new function(M.Ali's answer).
Another way of doing it is using dynamic query.
Declare #List varchar(max), #sql nvarchar(max)
Select #List = coalesce(#List + ',','') + '''' + StaffCode + ''''
From tblStaffs
set #sql = '
Select UserName
From #temptable
Where #temptable.StaffCode IN ('+ #List + ')'
--print #sql
exec (#sql)
To debug the dynamic query always print the dynamic sql before executing.
Because the Variable has a string which IN operator reads as 'AAA'',''ABB'',''BBB' and it treats it as a single value.
In your query you should really use the query itself in the IN operator something like....
Select UserName
From #temptable
Where #temptable.StaffCode IN (SELECT StaffCode From tblStaffs)
Anyway if there is a need to use variable and then read values inside the IN operator from that variable you can do something like this....
DECLARE #List VARCHAR(1000);
Select #List = coalesce(#List + ',','') + StaffCode
From tblStaffs
SELECT *
From #temptable
Where #temptable.StaffCode IN (
SELECT t.c.value('.', 'VARCHAR(1000)')
FROM (
SELECT x = CAST('<t>' +
REPLACE(#List , ',', '</t><t>') + '</t>' AS XML)
) a
CROSS APPLY x.nodes('/t') t(c))
I would recommend that you not use a comma-delimited string at all. Consider a semi-join instead:
select [Temp].[UserName]
from
#temptable [Temp]
where
exists (select 1 from [tblStaffs] where [tblStaffs].[StaffCode] = [Temp].[StaffCode]);
Related
I have a query that inside in quotes:
DECLARE #PivotQuery AS NVARCHAR(MAX),
#PivotColumns AS NVARCHAR(MAX),
#PivotNull AS NVARCHAR(MAX)
SELECT #PivotColumns= ISNULL(#PivotColumns + ',','') + QUOTENAME(DepId)
FROM (SELECT DISTINCT sp.DepId FROM SKDEP sp) AS Stock
SELECT #PivotNull
= ISNULL(#PivotNull + ',','')
+ 'ISNULL(' + QUOTENAME(DepId) + ', 0) AS '
+ QUOTENAME(DepId)
FROM (SELECT DISTINCT sp.DepId FROM SKDEP sp) AS Stock
SET #PivotQuery =
N'SELECT P.P, P.D, '+#PivotNull+'
FROM
(
select
s.prdid as P,
p.prddsc as D,
case when mstes=''S'' then sum(-MstCntDisp) else sum(MstCntDisp) end as Stock,
s.DepId
from SKMOV S
join PRODUC P on s.PrdId=p.PrdId
where s.mstsal>0 AND s.MstTpo=''S'' and s.PrdId=**''*TF033''**
group by s.prdid, p.PrdDsc, s.MstES, s.depid
) AS t
PIVOT(sum(Stock)
FOR DEPID IN (' + #PivotColumns + ')) AS P'
EXEC sp_executesql #PivotQuery
In the where clause I need specific my parameters with the question mark, so:
and s.PrdId=?
But I don't know how to specify the parameter when having the query in quotes, because it doesn't take it.
Finally i resolved my problem that this way:
In the where clause, im pass value of one string,
where s.mstsal>0 AND s.MstTpo=''S'' and s.PrdId=''PRODUCT_ID''
And after when report open (in tab Script/beforeOpen), im replace the string value with the parameter.
this.queryText=this.queryText.replace("PRODUCT_ID",params["ID"].value);
And works!
I am developing a custom application using CodeIgniter and MSSQL Server. Here i am using stored procedures.
Now i am wondering to implement codeigniter query type functionality where i can create a universal stored procedure in SQL Server and at the time of using i can pass tablename, array of fields and values.
It can work for both insert and update.
Something like we do in CodeIgniter to execute the query,
$data = array('fieldname1' => 'value1',
'fieldname2' => 'value2');
$this->db->insert($tablename,$data);
Just like this if we can pass the table name and array of the data to stored procedure and stored procedure automatically execute it.
If this can be done, it can save lots n lots of man hours. If anyone have already done i will be very much happy to see the solution.
You need to make string very specific in this case.
Figure out your table name, Column name, Column values for insert. For update 2 more parameters are required Id column name and its value.
GO
---- exec InsertUpdate 'tablename', 'col1, col2, col3', 'val1, val2, val3', 'idcol', 'idval'
GO
Create proc InsertUpdate
( #TableName nvarchar(500),
#ColName nvarchar(max),
#ColValues nvarchar(max),
#IDColName nvarchar(100) = '', --- for update only otherwise null
#IdColValue nvarchar(Max) = '' --- for update only otherwise null
)
As
Begin
declare #Query nvarchar(max)
if (#IdColValue = '')
Begin
set #Query = ' Insert into ' + #TableName + ' (' + #ColName + ') values (' + #ColValues + ')'
End
Else
Begin
;with CtColumn as (
select ROW_NUMBER() over (order by (select 1000)) as Slno, * from Split(#ColName,',') )
, CtValue as (
select ROW_NUMBER() over (order by (select 1000)) as Slno, * from Split(#ColValues, ','))
, CTFinal as (
select CCOl.Slno, CCOl.Items as ColName, CVal.Items as ColValue from CtColumn as CCOl inner join CtValue as CVal on CCOl.Slno=CVal.Slno )
select #Query = 'update ' + #TableName + ' set ' +
stuff ( (select ',' + ColName + '=' + ColValue from CTFinal for xml path ('')) ,1,1,'') +
' where ' + #IDColName + '=' + #IdColValue
End
exec sp_executesql #Query
End
Go
I need to generate a dynamic sql in below specified format where my table is a parameter i.e, Number of columns is not static
For example, below may be the table schema
ID Name
1 asd
2 xyz
I need a query which generates the select statement as below
select 'ID :' + ID + ',Name :'+Name from table
The output from generated above sql will be like this
ID : 1, Name:asd
ID : 2, Name:xyz
If the table has more number of columns, select statement that needs to be changes varies as below
select 'ID :' + ID + ',Name :'+Name + ',Col3 :' + Col3 ...from table
Could someone help me regarding this
Thanks,
Sree
Here is one option which uses a little XML and string manipulation
I should add, NULL values will be excluded.
Example
Declare #YourTable Table ([ID] varchar(50),[Name] varchar(50))
Insert Into #YourTable Values
(1,'asd')
,(2,'xyz')
Select stuff(
replace(
replace(
replace(
replace(
(Select * from #YourTable for XML RAW)
,'<row ',',')
,'="',':')
,'" ',',')
,'"/>','')
,1,1,'')
Returns
(No column name)
ID:1,Name:asd,ID:2,Name:xyz
Use the information schema views. They contain all the information you need to generate your dynamic sql. The rest is just simple SQL and patience.
I am able to achieve this using below sql
DECLARE #TableName VARCHAR(MAX) = 'tableName'
DECLARE #SQL VARCHAR(MAX) = 'SELECT ''{''+'''
SELECT #SQL = #SQL + '
"'+COLUMN_NAME+'":"''' + '+coalesce(CAST('+COLUMN_NAME+' AS VARCHAR(MAX)),'''')+''",' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #TableName
SET #SQL = LEFT(#SQL,LEN(#SQL)-1) + '
}'' FROM ' + #TableName
PRINT #SQL
Thanks,
Sree
Note: this is NOT asking
how to select a string where the column name is known.
how to select a string in ALL tables (all google results relate to this one)
This is asking search in only ONE table.
SQL returns error info conversion failed when converting the nvarchar value S3N2V5.
I want to locate the column name where S3N2V5 exists.
No manual methods please. There are 1000000 columns.
Input S3N2V5
Output columnname1ofthistable
Assuming I understand the question, here is one way to get a list of all columns from a single table that contain the search value, using CASE:
Create and populate sample table (Please save us this step in your future questions)
CREATE TABLE T
(
COL1 char(3),
COL2 char(3),
COL3 char(3),
COL4 int
)
INSERT INTO T VALUES
('abc', 'def', 'nop', 1),
('klm', 'nop', 'qrs', 2),
('tuv', 'wzy', 'zab', 3)
Build your dynamic sql:
DECLARE #Search nvarchar(5) = 'nop'
DECLARE #SQL nvarchar(max) = 'SELECT CASE #Search'
SELECT #SQL = #SQL +' WHEN '+ COLUMN_NAME + ' THEN '''+ COLUMN_NAME +''''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'T'
AND LOWER(DATA_TYPE) LIKE '%char%' -- only search char, varchar, nchar and nvarchar columns
SELECT #SQL = 'SELECT ColumnName FROM (' +
#SQL + ' END As ColumnName FROM T) x WHERE ColumnName IS NOT NULL'
Execute: (Note that using sp_executeSQL is SQL Injection safe, since we do not concatenate the search parameter into the query, but using it as a parameter)
EXEC sp_executeSQL #SQL, N'#Search nvarchar(5)', #Search
Results:
ColumnName
COL3
COL2
DECLARE #MyValue NVarChar(4000) = 'searchstring';
SELECT S.name SchemaName, T.name TableName
INTO #T
FROM sys.schemas S INNER JOIN
sys.tables T ON S.schema_id = T.schema_id;
WHILE (EXISTS (SELECT * FROM #T)) BEGIN
DECLARE #SQL NVarChar(4000) = 'SELECT * FROM $$TableName WHERE (0 = 1) ';
DECLARE #TableName NVarChar(1000) = (
SELECT TOP 1 SchemaName + '.' + TableName FROM #T
);
SELECT #SQL = REPLACE(#SQL, '$$TableName', #TableName);
DECLARE #Cols NVarChar(4000) = '';
SELECT
#Cols = COALESCE(#Cols + 'OR CONVERT(NVarChar(4000), ', '') + C.name + ') = CONVERT(NVarChar(4000), ''$$MyValue'') '
FROM sys.columns C
WHERE C.object_id = OBJECT_ID(#TableName);
SELECT #Cols = REPLACE(#Cols, '$$MyValue', #MyValue);
SELECT #SQL = #SQL + #Cols;
select substring(#SQL,charindex('.',#SQL)+1,charindex('(',#SQL)-charindex('.',#SQL)-8) as 'TableName'
EXECUTE(#SQL);
DELETE FROM #T
WHERE SchemaName + '.' + TableName = #TableName;
END;
DROP TABLE #T;
This will give you table Name and the entire row from the table which contains the searchstring.
Apart from anwswers mentioned in post : Older Post
1) (using column name) SELECT table_name,table_schema FROM INFORMATION_SCHEMA.COLUMNS WHERE column_name='sort_method';
I hope better you can take dump ( in.sql format ) and you can easily search the content using IDEs like N++.
I run several queries that use a list of character values in the where clause, e.g.,
select *
from table1
where col1 in ('a','b','c')
The character list changes frequently, so I want to store the string in a variable and reference the variable in all of the queries instead of maintaining several copies of the string. I've tried the following but the query returns zero rows.
declare #str varchar(50)
select #str = '''a''' + ',' + '''b'''+ ',' + '''c'''
select *
from table1
where col1 in (#str)
#str has the value 'a','b','c' but for some reason, SQL Server doesn't recognize it. How do I build a string and store it in a variable that works with the in keyword?
The IN construct in SQL as a set lookup, not a string lookup. Your single string value of "'a','b','c'" is exactly what it's looking for when you say where col1 in (#str)... as Fredou mentioned in comments.
Instead you want to pass in a set of values by using a table variable (or a temp table):
declare #tabIn table ( val varchar(10) )
insert #tabIn
(val) values
('a'), ('b'), ('c')
select *
from table1
where
col1 in (select val from #tabIn)
or, alternatively, just do a straight join:
declare #tabIn table ( val varchar(10) )
insert #tabIn
(val) values
('a'), ('b'), ('c')
select *
from table1 t1
join #tabIn t2 on
t1.col1 = t2.val
It is possible to create a string with embedded quotes. As Fredou and ChrisS mentioned, #str is considered a single string. If the #str value is concatenated with the rest of your select statement and then executed, you will achieve the your desired results. SQL Fiddle example.
declare #str varchar(50)
declare #sql varchar(MAX)
select #str = '''a''' + ',' + '''b'''+ ',' + '''c'''
Select #sql = 'SELECT * FROM table1 WHERE col1 IN (' + #str + ')'
Exec(#sql)
Results using #str = '''a''' + ',' + '''b'''+ ',' + '''c'''
Results using #str = '''a''' + ',' + '''b'''