IF子查询需要测试多个值

问题描述 投票:0回答:4

How do I split a string so I can access item x? - 解决方案使用了CTEWHILE。我告诉我的请求是没有使用WHILE,因为这不是很好的表现,它会延迟速度..同样适用于CURSOR

我正在使用SQL Server 2012.我将获得一串需要针对值进行测试的ID(@IDs)(在本例中为1)。

IF (SELECT CycleId
    FROM TABLE1
    WHERE ID in (@IDs) ) = '1'
BEGIN
     -- ABORT TRANSACTION AND FINISH THE QUERY
END
ELSE
BEGIN
     -- START TRANSACTION FOR THE Id....
END

这不起作用。有人告诉我应该避免使用WHILECURSOR

我需要运行@Ids中存在的几个值(它可以是100个值或只有5个以逗号分隔的值)。如果这些ID中的至少一个具有CycleId = 1,则它应该完全停止操作。也许它可能......

BEGIN          
      RAISERROR ('It is not possible to complete the transaction.',20,1)
      BREAK
END

表弟:

@IDs = 121, 434, 543, 345

Id    CycleId
---------------
121      1
434      2
543      1
345      1

在这种情况下,操作应该在@Id 121处停止(它不应该读取/测试任何其他ID并且它应该像我之前显示的那样抛出错误)

第二个案例

@IDs = 121, 434, 543, 345

Id    CycleId
--------------
121      3
434      2
543      5
345      6

在这种情况下,操作应该执行事务。

谢谢!

sql sql-server sql-server-2012
4个回答
2
投票

假设您的字符串变量@ids看起来像这样:' 2, 4 , 5 , 7,8,9,10, 21,22',您可以尝试以下方法:

-- pre-condition @ids by removing blanks and adding a comma at either end:
select @ids=','+replace(@ids,' ','')+',';

IF (SELECT 1 FROM TABLE1 WHERE patindex(concat('%,',CycleId,',%',@ids)>0 )
BEGIN
 -- ABORT TRANSACTION AND FINISH THE QUERY
END
ELSE
BEGIN
 -- START TRANSACTION FOR THE Id....
END

1
投票

您的第一个问题是您尝试匹配逗号分隔值的VARCHAR列表中的整数。有一个hacky解决方案,但你应该指定一个表变量而不是CSV:

SELECT 1
FROM table1
WHERE CONCAT(',', @IDs, ',') LIKE CONCAT('%,', ID , ',%')
AND CycleId = 1

在EXISTS子句中包含以上内容:

IF EXISTS (SELECT ...)
BEGIN
  RAISERROR ...
END

1
投票

你可以试试这个。

使用qazxsw poi代码通过qazxsw poi逗号分割你的变量,然后得到结果集。

使用xml来比较条件。

,

exists


0
投票

达:

使用Sik.D回答来完成剩下的..一个新的Id进入@ id = 4956并且在表中不存在...因此t1.CycleId是NULL。这重复了很多:

declare @IDs varchar(100) = '121,434,543,345' 

create table TABLE1(
    Id int,
    CycleId int
);


insert into TABLE1 values (121,1);
insert into TABLE1 values (434,2);
insert into TABLE1 values (543,1);
insert into TABLE1 values (345,1);

IF exists( 
    SELECT 1
        FROM TABLE1 t1
        WHERE ID  in (
            SELECT Split.a.value('.', 'NVARCHAR(MAX)')
            FROM
            (
                SELECT CAST('<X>'+REPLACE(@IDs, ',', '</X><X>')+'</X>' AS XML) AS String
            ) AS A
            CROSS APPLY String.nodes('/X') AS Split(a)
            WHERE  t1.CycleId = 1
    )
)

BEGIN
     -- ABORT TRANSACTION AND FINISH THE QUERY
END
ELSE
BEGIN
    -- START TRANSACTION FOR THE Id....
END

"

这是最终的代码:

sqlfiddle

如何简化?谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.