【问题标题】:Converting String List into Int List in SQL在 SQL 中将字符串列表转换为 Int 列表
【发布时间】:2013-05-21 06:49:45
【问题描述】:

我的存储过程中有一个 nvarchar(MAX),其中包含 int 值列表,我这样做是因为 无法将 int 列表传递给我的存储过程, 但是,现在我遇到了问题,因为我的数据类型是 int,我想比较字符串列表。 有没有办法让我做同样的事情?

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

但statuslist现在包含字符串值而不是int,那么如何将它们转换为INT?

更新日期:

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//
)

作为 设置 FMTONLY 关闭; 声明 @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

因此,当我实现该拆分功能时,我无法指定字符或分隔符,因为它不接受它为 (@List,',')。

(','+@List+',')。

【问题讨论】:

  • 好吧,您可以编写一个表值函数来拆分 int 值的字符串,或者如果您使用的是 SQL Server 2008+,则可以使用表值参数(不是真正使用它们,所以不确定如果它们 100% 适合此目的)
  • @Neil:请详细说明一下,你能给我一个链接吗?
  • 这篇文章说明了我的意思:stackoverflow.com/questions/16040226/…

标签: sql string list stored-procedures casting


【解决方案1】:

可以使用 XML 参数将 int 列表 发送到您的存储过程。这样您就不必再处理这个问题了,这是一个更好、更干净的解决方案。

看看这个问题: Passing an array of parameters to a stored procedure

或检查此代码项目: http://www.codeproject.com/Articles/20847/Passing-Arrays-in-SQL-Parameters-using-XML-Data-Ty

但是,如果您坚持按自己的方式进行操作,则可以使用此功能:

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

这样称呼它:

SELECT      *
FROM        Table
WHERE status IN (SELECT * from fnStringList2Table(@statuslist))

【讨论】:

  • 我喜欢 XML 解决方案,因为它非常灵活,可以将更复杂的数据传递到 proc 中,而且我喜欢您可以将 XML 数据视为表格。
  • 这不起作用,因为我使用的是动态 sql,并且在那个“,”中会产生错误
  • 为什么还要使用动态SQL?请尽量避免使用动态 SQL,因为您现在有此功能。如果您必须使用它,请尝试在您的问题中提及它。我认为这回答了您的问题,如果它不起作用,您绝对应该编辑问题本身。顺便说一句,它不是内联的,你应该在你的数据库中运行一次函数
【解决方案2】:

您也可以使用字符串列表。我总是这样。

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)

【讨论】:

  • 不,它给我一个错误,必须将其声明为标量类型等
  • 将您的 sql 变量声明为 nvarchar 并以逗号分隔格式传递字符串参数。它可能会起作用。
  • 仍然无法正常工作,因为我有一个动态 sql,当我在 sql 'select--------' 中使用 ',' 时出现错误
  • 我想你错过了一些括号。
  • 在这样的代码中你必须小心SQL注入攻击
【解决方案3】:

您可以使用 sql 函数来执行此操作,该函数将返回一个整数数组。 如果您将@Delimiter 分隔的字符串传递给您的存储过程,这将是很好的事后可以正确处理。

编写一个函数来拆分数据,如下所示

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

然后像下面这样使用它,我在这里使用 (,) 作为@Delimiter

SELECT ResultValue [YourSchema].[SplitValues](@statuslist,',')

【讨论】:

  • 这个我用过,但它对我没有帮助,因为我无法使用“,”,因为它在我的动态 sql 中显示错误
  • 你将如何将它与表列作为参数一起使用?例如。像这样:SELECT SplitValues([visible_document_type_id], ',') FROM [document_access_rules]
【解决方案4】:

实际上,您可以通过创建User Defined Table Typeint 值列表发送到您的过程。但是,这意味着为了填充表参数需要做更多的工作。

在您的情况下,您可以使用sp_executesql 存储过程来实现您想要的:

declare @statement nvarchar(4000) = '----your query---- where status in (' 
+ @statusList +')'
sp_executesql @statement

【讨论】:

【解决方案5】:

这里是一个如何做的例子和Link了解更多信息

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 ############################

【讨论】:

    【解决方案6】:

    这适用于 Informix 数据库:

    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'));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      • 2015-02-23
      • 2018-08-04
      • 2014-05-23
      • 2018-04-08
      相关资源
      最近更新 更多