IN clause has parameter doesn't work in stored procedure - tsql

I have "Name IN (#NameList))" inside of the stored procedure as one of the conditions.
The parameter is declared as #NameList varchar(100) = ''
When I execute the procedure with string like EXEC myProc #NameList='''a'''
the procedure returns nothing, but when I replaced the parameter with hard coded value like 'a' it succeeded.
I put a PRINT statement inside the SP and it prints exactly 'a'
What's wrong here?
Thanks,

Please read my comments as well but one solution would be to split your comma separated string into a table and then join onto that:
declare #list varchar(max) = '13,14,15,13,14,15,13'
SELECT
LTRIM(RTRIM(a.b.value('.[1]','VARCHAR(255)'))) Parish
FROM
(
SELECT CAST('<XMLRoot><RowData>' + REPLACE(#list,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) x)t
CROSS APPLY x.nodes('/XMLRoot/RowData')a(b)

Related

How to get a list of quoted strings from the output of a SELECT query that has that list of quoted strings in it, but is of type string?

The following code is not a full setup that you can run to check. It shall just make it a bit clearer what the question is about.
With an example function like this (the variadic example is taken from PostgreSQL inserting list of objects into a stored procedure or PostgreSQL - Passing Array to Stored Function):
CREATE OR REPLACE function get_v(variadic _v text[]) returns table (v varchar(50)) as
$F$
declare
begin
return query
select t.v
from test t
where t.v = any(_v)
end;
$F$
language plpgsql
;
If you copy the one-value output of a select string_agg... query, 'x','y','z', by hand and put it as the argument of the function, the function works:
SELECT v FROM get_v_from_v(
'x','y','z'
);
The 'x','y','z' gets read into the function as variadic _v text[] so that the function can check its values with where t.v = any(_v).
If you instead put the (select string_agg...) query that is behind that 'x','y','z' output in the same place, the function does not work:
select v from get_v_from_v(
(select string_agg(quote_literal(x.v), ',') from (select v from get_v_from_name('something')) as x)
);
That means: the "one-value output field" 'x','y','z' that comes from the (select string_agg...) query is not the same as the text[] list type: 'x','y','z'.
With get_v_from_name('something') as another function that returns a table of one column and the "v" values in the rows, and after running the string_agg() on its output, you get the 'x','y','z' output. I learnt this working function string_agg() at How to make a list of quoted strings from the string values of a column in postgresql?. The full list of such string functions is in the postgreSQL guide at 9.4. String Functions and Operators.
I guess that the format of the select query output is just a string, not a list, so that the input is not seen as a list of quoted strings, but rather like a string as a whole: ''x','y','z''. The get_v_from_v argument does not need just one string of all values, but a list of quoted strings, since the argument for the function is of type text[] - which is a list.
It seems as if this question does not depend on the query that is behind the output. It seems rather just a general thing that the output in a tuple of a table and taken as the argument of a function is not the same as the same output hand-copied as the same argument.
Therefore, the question. What needs to be done to make the output of a select query the same as the hand-copy of its output, so that the output is just the list 'x','y','z', as if it was just copied and pasted?
PS: I guess that this way of making lists of quoted strings from the one-column table output only to pass it to the function is not best practice. For example, in TSQL/SQL Server, you should pass "table valued parameters", so that you pass values as a table that you select from within the function to get the values, see How do I pass a list as a parameter in a stored procedure?. Not sure how this is done in postgreSQL, but it might be what is needed here.
CREATE OR REPLACE function get_v(_v text[]) returns table (v varchar(50)) as
$F$
declare
begin
return query
select t.v
from test t
where t.v = any((select * from unnest(_v)))
end;
$F$
language plpgsql
;
With get_v_from_name('something') as another function that returns a table of one column and the "v" values in the rows (this was said in the question), the following works:
select v from get_v_from_v(
(select array_agg(x.v) from (select v from get_v_from_name('something')) as x)
);
Side remark:
array_agg(quote_literal(x.v), ',') instead of array_agg(x.v) fails, the function does not allow a second argument.

SSIS How to Use Parameters with IN Clause

emailVariable = john#example.com, sally#testing.com
SQL Query:
select *
from [table_1]
where email in (?);
Parameter set to use emailVariable.
This returns nothing, both emails are valid.
Am I doing something wrong?
I am using an OLE DB Source Editor.
You can also use string_split:
declare #stringToSplit varchar(255) = 'john#example.com, sally#testing.com'
select *
from [table_1]
where email in (
select ltrim(rtrim(value)) from string_split(?,',')
)
String_Split will return a table of values based on your input string and the delimiter. In your case you also need ltrim and rtrim because of extra spaces.
This is a classic mistake. Although the following works:
where email in ('john#example.com','sally#testing.com')
you cannot use one variable to put a multitude of values. The comma(s) is not part of the value string, it is considered code. What you can do is use dynamic sql:
declare #emailVariable nvarchar(max)=N'''john#example.com'',''sally#testing.com''' -- notice the escaped quotes
declare #sql nvarchar(max)
set #sql=N'select * from [Table_1] where email in (' + #emailVariable + ')'
exec(#sql)

How do convert below code from T-SQL into DB2 LUW?

How do I convert this code from T-SQL into DB2 LUW, it seems so easy with T-SQL but in DB2 can't find any solution. See code below:
DECLARE #sqlCommand varchar(1000)
DECLARE #columnList varchar(75)
DECLARE #city varchar(75)
SET #columnList = 'AddressID, AddressLine1, City'
SET #city = '''London'''
SET #sqlCommand = 'SELECT ' + #columnList + ' FROM Person.Address WHERE City = ' + #city
EXEC (#sqlCommand)
The problem is that you can’t ‘select to nowhere’ in a compound statement in DB2. Db2 CLP can return you the result set of a single sql statement, but it doesn’t try to do the same for select statements in a compound statement. If you want to print the result set from a select statement in a compound statement, you can, for example, declare a cursor, fetch it in a loop, and use dbms_output.put_line calls to print the values of variables.
Not Pretty but you can find an example of the bottom of this page:
Stored Procedures and Dynamic SQL Returning a Result set
Essentially you most:
1) create a dynamic SQL string
2) prepare the string into a statement
3) Link the statement to a cursor you're going to declare as WITH RETURN
Opening the cursor will be the last line in your procedure.

Scalar-valued function does not return NULL but a 'NULL' string

I need to import data from Excel into a ms sql database and I thought using the OPENROWSET would be a good idea... well, it is not bad but has some side effects.
The data I'm receiving is not allways 100% correct. By correct I mean cells that should be NULL (and in Excel empty) sometimes contain the string "NULL" or some other junk like whitespaces. I tried to fix it with this script:
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[NullIfEmpty](#input nvarchar)
RETURNS nvarchar(max)
AS
BEGIN
if (#input = '' or #input = 'NULL')
begin
return NULL
end
return #input
END
But strange things happen. This gives me a string with the text "NULL" instead of a real NULL so the grid cell after querying the database isn't yellow but contains normal text even though the target column allows NULL.
A simple test with:
select dbo.nullifempty('NULL')
or
select dbo.nullifempty(null)
also yields a string.
Do you know why this is happening and how I can fix it?
To get null for empty strings or strings that are the word NULL, you could just use coalesce and nullif:
COALESCE(NULLIF(#input, 'NULL'), NULLIF(#Input, ''), #input)
Please note that the problem in your original code is because you didn't specify the length of the #input parameter - so SQL Server created it as varchar(1).
You should always specify length for char/varchar/nchar and nvarchar.
From nchar and nvarchar page remarks:
When n is not specified in a data definition or variable declaration statement, the default length is 1. When n is not specified with the CAST function, the default length is 30.
(n referring to the n in nchar(n) or nvarchar(n))
repleace lines with 'ALTER"
ALTER FUNCTION [dbo].[NullIfEmpty](#input nvarchar(max))
and with line with 'if'
if (LTRIM(RTRIM(#input)) = '' or #input IS NULL)
you should reassign value for declared variable using set
''''
BEGIN
if (#input = '' or #input = 'NULL')
begin
set #input = NULL
end
select #input
END
test

comma separated value in sql statement from a variable

I am getting comma separated value like this in a variable (let say variable name #listobj)
'abc' , 'xyz'
but when I am using below statement it is not giving me the correct result
SELECT * FROM someTable
Where column1 IN (#listobj)
but abc is present in the table.
Where I am doing it wrong?
create a function that split the string to
CREATE FUNCTION dbo.Split(#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (items varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
then make call to the function SELECT * FROM someTable
Where column1 IN (dbo.Split(#listobj))
enter link description here
SQLFiddle demo
select * from someTable
where ','+LTRIM(RTRIM(#listobj))+',' LIKE '%,'+LTRIM(RTRIM(column1))+',%'
A classic question and the answer is no, you cannot use a parameter in this way. There are several workarounds though
One of which is to parse the value inside the stored procedure and dynamically generate sql inside the procedure to be execute later. However, this is not a good practice.
Refer to this question
How to pass a comma separated list to a stored procedure?
and also some good discussion on it here
http://social.msdn.microsoft.com/Forums/en-US/sqlintegrationservices/thread/1ccdd39e-8d58-45b2-9c21-5c4dbd857f95/