一尘不染

SQL:使用IN子句将字符串投射到IDS

sql

DECLARE @STR_IDS VARCHAR(15)
SET @STR_IDS='7,15,18'
UPDATE TBL_USERS WHERE ID IN  @STR_IDS

我知道更新语句将不起作用,因为ID是INT类型,并且我正在那里替换varachar值。我如何更改查询,以便它实际上像这样执行?

 UPDATE TBL_USERS WHERE ID IN (7,15,18)

谢谢你


阅读 166

收藏
2021-05-05

共1个答案

一尘不染

Op没有提到数据库,因此我将仅使用SQL Server,因为问题中的示例SQL看起来像TSQL。在SQL
Server中有很多分割字符串的方法。本文介绍了几乎每种方法的优点和缺点:

Erland Sommarskog撰写的“当表值参数无法剪切时,SQL Server
2005及更高版本中的数组和列表”

您需要创建一个拆分功能。这是分割函数的使用方式:

SELECT
    *
    FROM YourTable                               y
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value

我更喜欢使用数字表方法在TSQL中拆分字符串,但是在SQL Server中拆分字符串的方法有很多,请参见前面的链接,其中解释了每种方法的优点和缺点。

为了使Numbers Table方法起作用,您需要进行一次时间表设置,这将创建一个Numbers包含1至10,000行的表:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

设置号码表后,请创建以下拆分功能:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
    ,@List     varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN 
(

    ----------------
    --SINGLE QUERY-- --this will not return empty rows
    ----------------
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''

);
GO

现在,您可以轻松地将CSV字符串拆分为一个表,然后在表上进行联接或根据需要使用它,甚至可以在动态sql中使用它。这是从您的问题中使用它的方法:

UPDATE t
    SET Col1=...
    FROM dbo.FN_ListToTable(',','7,15,18') dt
        INNER JOIN TBL_USERS                t ON  CAST(dt.value AS INT)=t.id
2021-05-05