Если подзапрос должен проверить несколько значений - PullRequest
0 голосов
/ 03 сентября 2018

Как разделить строку, чтобы получить доступ к элементу x? - в решениях использовались CTE и WHILE. Я сказал, что мой запрос не использует WHILE, потому что это не очень хорошая производительность, она замедляет скорость .. То же самое касается CURSOR

Я использую SQL Server 2012. Я получу строку идентификаторов (@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

Это не работает. Мне сказали, что следует избегать использования WHILE или CURSOR.

Мне нужно запустить несколько значений, присутствующих в @Ids (это может быть 100 значений или просто 5 значений, разделенных запятой,). Если хотя бы один из этих идентификаторов имеет CycleId = 1, он должен полностью остановить операцию. Может быть, это может быть ...

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

1-й случай:

@IDs = 121, 434, 543, 345

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

в этом случае операция должна быть остановлена ​​на @Id 121 (она не должна читать / проверять любые другие идентификаторы и должна выдавать ошибку, как я показывал ранее)

2-й случай

@IDs = 121, 434, 543, 345

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

В этом случае операция должна выполнять транзакцию.

Спасибо!

Ответы [ 4 ]

0 голосов
/ 06 сентября 2018

до:

ИСПОЛЬЗУЯ ответ Sik.D для завершения оставшихся .. новый идентификатор вводится в @ id = 4956 и не существует в таблице ... следовательно, t1.CycleId IS 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

Как упростить? спасибо.

0 голосов
/ 03 сентября 2018

Предполагая, что ваша строковая переменная @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
0 голосов
/ 03 сентября 2018

Вы можете попробовать это.

используя узел 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

0 голосов
/ 03 сентября 2018

Ваша первая проблема заключается в том, что вы пытаетесь сопоставить целое число в списке значений VARCHAR с разделителями-запятыми. Существует хакерское решение для этого , но вы должны указать переменную таблицы вместо CSV :

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

Оберните вышеупомянутое в предложении EXISTS:

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