Как поднять ошибку, если условие не соответствует

У меня есть пользовательская таблица, в которой я хочу создать условие, если количество запасов >= source.Qty, а затем вычесть еще raiserror('Qty not enough', 16, 1)

Это мой код

MERGE Stock AS TARGET 
USING @InvoiceLines AS SOURCE 
      ON (TARGET.ProductID = SOURCE.ProductID AND TARGET.Qty >= SOURCE.Qty)

WHEN MATCHED THEN
    UPDATE 
        SET Qty = TARGET.Qty - SOURCE.Qty;

Пожалуйста, предоставьте минимально воспроизводимый пример с данными образца и желаемыми результатами.

Dale K 23.06.2024 11:40

@DaleK вычитает, даже если акции 0 будут равны -1. Я хочу поднять ошибку, если условие не соответствует.

waleed 23.06.2024 11:40

Пожалуйста, отредактируйте свой вопрос, чтобы уточнить это.

Dale K 23.06.2024 11:42

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

Dale K 23.06.2024 11:44

Обратите внимание: не используйте raiserror, используйте throw

Dale K 23.06.2024 11:44

@DaleK может редактировать мой код и показывать правильный синтаксис.

waleed 23.06.2024 11:46

@DaleK Я не знаю правильного синтаксиса для выдачи исключения, если Qty меньше, можете ли вы внести изменения в мой код

waleed 23.06.2024 11:55

Обратитесь к документации Используйте THROW, чтобы вызвать исключение

Squirrel 23.06.2024 12:00

@Squirrel, проблема с моим (синтаксисом слияния), когда он не совпадает, он позволяет только вставку, обновление, удаление, я не могу сделать исключение throw

waleed 23.06.2024 12:03

@Squirrel, я пробовал много раз, можешь ли ты отредактировать синтаксис моего кода в соответствии с моими потребностями?

waleed 23.06.2024 12:09
MERGE ...... IF EXISTS (SELECT * FROM Stock WHERE Qty < 0) THROW ......
Squirrel 23.06.2024 12:22

Почему Merge, когда достаточно простого Update?

Zohar Peled 23.06.2024 12:36
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
12
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я решил, проверив @@Rowcount, если 0 означает, что строка не затронута, часть моего кода

       BEGIN 

       MERGE Stock AS TARGET 
       USING @InvoiceLines AS SOURCE 
       ON (TARGET.ProductID = SOURCE.ProductID AND TARGET.Qty >= SOURCE.Qty )
       WHEN MATCHED THEN
         UPDATE SET Qty =TARGET.Qty - SOURCE.Qty;
         IF @@ROWCOUNT=0
         RAISERROR('Qty not Enough', 16, 2) 
          
       END 


BEGIN CATCH
    declare @error int, @message varchar(4000), @xstate int;
    select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE()
    ,@xstate = XACT_STATE()
    IF @xstate = -1
        rollback;
    IF @xstate = 1 and @trancont = 0
        rollback
    IF @xstate = 1 and @trancont > 0
        rollback transaction mytran
    --IF @@TRANCOUNT > 0
    --BEGIN
        RAISERROR(@message, 16, 1)  
    --  ROLLBACK
    --END
END CATCH

Используйте THROW, а не RAISERROR, да и зачем бросать только для того, чтобы поймать, можно условно откатиться без ловли

Charlieface 23.06.2024 15:26

Кроме того, если нужно изменить более одной строки, это вообще не будет работать.

Charlieface 23.06.2024 15:34
Ответ принят как подходящий

Похоже, вам просто нужен IF EXISTS. Просто проверить @@ROWCOUNT недостаточно, если требуется изменить более одной строки.

Также обратите внимание:

  • Используйте явную транзакцию и подсказку UPDLOCK или SERIALIZABLE, чтобы обеспечить правильную блокировку.
  • Используйте SET XACT_ABORT ON, чтобы гарантировать правильные откаты.
  • Используйте THROW, а не RAISERROR, так как это лучше учитывает откаты.
  • ON в MERGE должно быть только условием соединения, все остальные условия должны находиться в CTE или в предложении WHEN MATCHED THEN.
  • Сказав это, похоже, вы можете просто использовать простое соединение UPDATE.
SET XACT_ABORT, NOCOUNT ON;

BEGIN TRAN;

IF EXISTS (SELECT 1
    FROM Stock AS s WITH (UPDLOCK)
    JOIN @InvoiceLines AS il
      ON s.ProductID = il.ProductID
    WHERE s.Qty < il.Qty
)
    THROW 50001, N'Qty not Enough', 1;

UPDATE s
SET Qty -= il.Qty
FROM Stock AS s
JOIN @InvoiceLines AS il ON il.ProductID = s.ProductID;

COMMIT;

@да, я проверил свой старый ответ, когда в одном из продуктов осталось количество, все еще возвращается 1 ROWCOUNT, я сделал ваш ответ, и он работает отлично, большое спасибо

waleed 23.06.2024 19:52

Другие вопросы по теме