如果子查询需要测试多个值

时间:2018-09-03 14:08:46

标签: sql sql-server sql-server-2012

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

我正在使用SQL Server2012。我将获得一串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

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

谢谢!

4 个答案:

答案 0 :(得分: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 :(得分:1)

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

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

将以上内容包装在EXISTS子句中:

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

答案 2 :(得分:1)

您可以尝试一下。

使用xml节点以,逗号溢出变量,然后获取结果集。

使用exists比较条件。

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

答案 3 :(得分:0)

上:

使用Sik.D答案来完成剩余的操作..一个新的ID输入@ id = 4956且该表中不存在...因此t1.CycleId为NULL。重复很多次:

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

这是最终代码:

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 -- there should be some ids without t1.CycleId -- assuming exists is true if there is one positive row for t1.CycleId=1
     IF NOT EXISTS  (SELECT 1
                 from table 1
                 where id in ( **-- same as before*  WHERE t1.CycleId IS NULL) )

        begin
             INSERT INTO table1
             values (id,1) -- not sure here with the Id...
         end

   ELSE


BEGIN
     IF NOT EXISTS  (SELECT 1
                     from table 1
                     where id in ( **-- same as before*  WHERE t1.CycleId IS NULL) )

            BEGIN 
                 INSERT INTO table1
                 values (id,1) -- not sure here with the Id...
            END 

                ELSE 

            BEGIN
                UPDATE table1 
                SET CycleId=1 
                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))

            END
END

如何简化?谢谢。