9

I have a nvarchar(MAX) in my stored procedure which contains the list of int values, I did it like this as it is not possible to pass int list to my stored procedure, but, now I am getting problem as my datatype is int and I want to compare the list of string. Is there a way around by which I can do the same?

---myquerry----where status in (@statuslist)

but the statuslist contains now string values not int, so how to convert them into INT?

UPDate:

USE [Database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER PROCEDURE [dbo].[SP]
(
@FromDate datetime = 0,
@ToDate datetime = 0,
@ID int=0,
@List nvarchar(MAX) //This is the List which has string ids//
)

AS SET FMTONLY OFF; DECLARE @sql nvarchar(MAX), @paramlist nvarchar(MAX)

SET @sql    = 'SELECT ------ and Code in(@xList)
  and -------------'
SELECT @paramlist = '@xFromDate datetime,@xToDate datetime,@xId int,@xList nvarchar(MAX)'

EXEC sp_executesql @sql, @paramlist, 
@xFromDate = @FromDate ,@xToDate=@ToDate,@xId=@ID,@xList=@List
PRINT @sql

So when I implement that function that splits then I am not able to specify the charcter or delimiter as it is not accepting it as (@List,',').

or (','+@List+',').

Incredible
  • 3,495
  • 8
  • 49
  • 77
  • Well you could write a table-valued function to split the string of int values or you could possibly use table-value parameters if you are using SQL Server 2008+ (not really worked with them so not certain if they are 100% suitable for this purpose) – Neil Hibbert May 21 '13 at 06:55
  • @ Neil : please elaborate a bit more, can you provide me a link for the same? – Incredible May 21 '13 at 07:04
  • This post shows what I mean: http://stackoverflow.com/questions/16040226/should-table-valued-parameters-be-used-here – Neil Hibbert May 21 '13 at 07:08

6 Answers6

15

It is possible to send an int list to your stored procedure using XML parameters. This way you don't have to tackle this problem anymore and it is a better and more clean solution.

have a look at this question: Passing an array of parameters to a stored procedure

or check this code project: http://www.codeproject.com/Articles/20847/Passing-Arrays-in-SQL-Parameters-using-XML-Data-Ty

However if you insist on doing it your way you could use this function:

CREATE FUNCTION [dbo].[fnStringList2Table]
(
    @List varchar(MAX)
)
RETURNS 
@ParsedList table
(
    item int
)
AS
BEGIN
    DECLARE @item varchar(800), @Pos int

    SET @List = LTRIM(RTRIM(@List))+ ','
    SET @Pos = CHARINDEX(',', @List, 1)

    WHILE @Pos > 0
    BEGIN
        SET @item = LTRIM(RTRIM(LEFT(@List, @Pos - 1)))
        IF @item <> ''
        BEGIN
            INSERT INTO @ParsedList (item) 
            VALUES (CAST(@item AS int))
        END
        SET @List = RIGHT(@List, LEN(@List) - @Pos)
        SET @Pos = CHARINDEX(',', @List, 1)
    END

    RETURN
END

Call it like this:

SELECT      *
FROM        Table
WHERE status IN (SELECT * from fnStringList2Table(@statuslist))
Nick N.
  • 12,902
  • 7
  • 57
  • 75
  • 1
    I like the XML solution because it's very flexible for passing more complicated data into a proc, and I like that you can treat the XML data as a table. – Rory Hunter May 21 '13 at 07:45
  • This is not working as I am using dynamic sql and in that ',' is creating an error – Incredible May 21 '13 at 08:10
  • Why do you still have to use dynamic SQL? Please try to prevent using dynamic SQL since you have this function now. If you have to use it persè try to mention it in your question. I think this answers your question and if it does not work, you should definitely edit the question itself. Btw, it is not inline, you should run the function once in your database – Nick N. May 21 '13 at 08:42
9

You can work with string list too. I always do.

declare @statuslist nvarchar(max)
set @statuslist = '1, 2, 3, 4'

declare @sql nvarchar(max)
set @sql = 'select * from table where Status in (' + @statuslist + ')'
Execute(@sql)
2

You can do this by using sql function which will return you an integer array.. It would be great if you pass @Delimiter separated string to your stored procedure which could be processed properly afterwards.

Write one function to split the data as following

CREATE FUNCTION [dbo].[SplitValues] (@StringArray NVARCHAR(MAX), @Delimiter NVARCHAR(10)) 
RETURNS @ResultedValues table 
(
ResultValue INT
) 
AS 
BEGIN       
  DECLARE @Tokens TABLE(Token nvarchar)         
  DECLARE   @String nvarchar

  WHILE (CHARINDEX(@Delimiter,@StringArray)>0)
   BEGIN 
    INSERT INTO @Tokens (Token) VALUES (LTRIM(RTRIM(SUBSTRING(@StringArray,1,CHARINDEX(@Delimiter,@StringArray)-1))))
    SET @String = SUBSTRING(@StringArray,
    CHARINDEX(@Delimiter,@StringArray)+LEN(@Delimiter),LEN(@StringArray))
   END 
INSERT INTO @ResultedValues (ResultValue ) VALUES ( CAST(LTRIM(RTRIM(@String)) AS INT))
RETURN
END

And then use it like following, i am using (,) as @Delimiter here

SELECT ResultValue [YourSchema].[SplitValues](@statuslist,',')
Remy
  • 12,555
  • 14
  • 64
  • 104
K D
  • 5,889
  • 1
  • 23
  • 35
  • This I have used but it is not helping me as I am not able to use ',' as it shows error in my dynamic sql – Incredible May 21 '13 at 08:26
  • How would you use this with a table colum as the parameter? E.g. something like this: SELECT SplitValues([visible_document_type_id], ',') FROM [document_access_rules] – Remy Mar 29 '20 at 18:21
1

Actually, you can send the list of int values to your procedure by creating a User Defined Table Type. However, this implies more work in order to populate the table parameter.

In your case, you can use the sp_executesql stored procedure to achieve what you want like this:

declare @statement nvarchar(4000) = '----your query---- where status in (' 
+ @statusList +')'
sp_executesql @statement
RePierre
  • 9,358
  • 2
  • 20
  • 37
  • I want to go with the above one, creating user defined table, can you advise me in that how to do that? – Incredible May 21 '13 at 07:11
  • @ItiTyagi, please take a look here http://technet.microsoft.com/en-us/library/ms175007(v=sql.100).aspx and here http://technet.microsoft.com/en-us/library/bb510489(v=sql.100).aspx . The second link has an example on how to use custom type with a stored procedure. – RePierre May 21 '13 at 07:35
  • I have also updated my code, I hope you may help me in the same. – Incredible May 21 '13 at 09:35
0

here is an example of how to do it and the Link for more informations

ALTER FUNCTION iter_intlist_to_tbl (@list nvarchar(MAX))
   RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
                       number  int NOT NULL) AS


BEGIN

    DECLARE @startpos int,
            @endpos   int,
            @textpos  int,
            @chunklen smallint,
            @str      nvarchar(4000),
            @tmpstr   nvarchar(4000),
            @leftover nvarchar(4000)


   SET @textpos = 1
   SET @leftover = ''


    WHILE @textpos <= datalength(@list) / 2
    BEGIN


        SET @chunklen = 4000 - datalength(@leftover) / 2 


        SET @tmpstr = ltrim(@leftover + substring(@list, @textpos, @chunklen))

        SET @textpos = @textpos + @chunklen

        SET @startpos = 0

        SET @endpos = charindex(' ' COLLATE Slovenian_BIN2, @tmpstr)

        WHILE @endpos > 0
        BEGIN

            SET @str = substring(@tmpstr, @startpos + 1, @endpos - @startpos - 1) 

            IF @str <> ''
                INSERT @tbl (number) VALUES(convert(int, @str))

            SET @startpos = @endpos

            SET @endpos = charindex(' ' COLLATE Slovenian_BIN2, @tmpstr, @startpos + 1)
        END

        SET @leftover = right(@tmpstr, datalength(@tmpstr) / 2 - @startpos)
    END

    IF ltrim(rtrim(@leftover)) <> ''
        INSERT @tbl (number) VALUES(convert(int, @leftover))

    RETURN
END


-- ############################ Example ############################
--CREATE    PROCEDURE get_product_names_iter @ids varchar(50) AS
--SELECT    P.ProductName, P.ProductID
--FROM      Northwind..Products P
--JOIN      iter_intlist_to_tbl(@ids) i ON P.ProductID = i.number
--go
--EXEC get_product_names_iter '9 12 27 37'
-- ############################ WICHTIG ############################
WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
0

This works for me on an Informix DataBase:

DROP FUNCTION rrhh:fnc_StringList_To_Table;
CREATE FUNCTION rrhh:fnc_StringList_To_Table (pStringList varchar(250))
    RETURNING INT as NUMERO;

    /* A esta Funcion le podes pasar una cadena CSV con una lista de numeros
     *      Ejem:  EXECUTE FUNCTION fnc_StringList_To_Table('1,2,3,4');
     * y te devolvera una Tabla con dichos numeros separados uno x fila
     * Autor:  Jhollman Chacon @Cutcsa - 2019 */

    DEFINE _STRING VARCHAR(255);
    DEFINE _LEN INT;
    DEFINE _POS INT;
    DEFINE _START INT;
    DEFINE _CHAR VARCHAR(1);
    DEFINE _VAL INT;

    LET _STRING = REPLACE(pStringList, ' ', '');
    LET _START = 0;
    LET _POS = 0;
    LET _LEN = LENGTH(_STRING);

    FOR _POS = _START TO _LEN
        LET _CHAR = SUBSTRING(pStringList FROM _POS FOR 1);

        IF _CHAR <> ',' THEN 
            LET _VAL = _CHAR::INT;
        ELSE 
            LET _VAL = NULL;
        END IF;

        IF _VAL IS NOT NULL THEN 
            RETURN _VAL WITH RESUME;
        END IF;

    END FOR;

END FUNCTION;

EXECUTE FUNCTION fnc_StringList_To_Table('1,2,3,4');
SELECT * FROM TABLE (fnc_StringList_To_Table('1,2,3,4'));
Jhollman
  • 2,093
  • 24
  • 19