UDF не дают тот же результат - PullRequest
       9

UDF не дают тот же результат

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

когда я выполняю UDF из триггера, результат не совпадает

UDF всегда возвращает true при выполнении в триггере

, но вне триггера результат равен true илиfalse

ALTER FUNCTION [dbo].[MandatExist]
(
   @Numero      int,
   @IdBranche   int,
   @Exercice    int 
)
RETURNS   bit
AS
BEGIN
    DECLARE @Result   bit
    DECLARE @Nbr      int 
    DECLARE @Categ    int

    SELECT @Categ = CategorieNumero
    FROM Branche
    WHERE IdBranche = @IdBranche

    SELECT @Nbr=COUNT(*)
    FROM  Mandat AS M INNER JOIN Branche AS B ON M.IdBranche=B.IdBranche
    WHERE (Numero = @Numero) AND (B.CategorieNumero = @Categ) AND (Exercice = @Exercice)

    IF @Nbr = 0
      SET @Result = 0
    ELSE 
      SET @Result = 1

    RETURN @Result

END

вызов триггера MandatExist, чтобы получить, существует ли номер или нет

ALTER TRIGGER [dbo].[ValidInsertUpdate_Mandat]
   ON  [dbo].[Mandat]
   FOR INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    DECLARE  @Cloturer       AS bit
    DECLARE  @Exercice       AS int
    DECLARE  @IdBranche      AS int
    DECLARE  @Numero         AS int
    DECLARE  @Message        AS nvarchar(100)

    SELECT @Cloturer=Cloturer, @Exercice=Exercice, @Numero=Numero, @IdBranche=IdBranche
    FROM INSERTED


    IF (dbo.MandatExist(@Numero, @IdBranche, @Exercice)=1)
    BEGIN
      SET @Message = 'Numero de mandat existant.'
      RAISERROR(@Message, 16, 1)
      ROLLBACK TRAN
    END 

Ответы [ 2 ]

0 голосов
/ 01 октября 2018

я использовал решение Ивана

IF EXISTS(
              SELECT 1
              FROM INSERTED I INNER JOIN Branche b ON b.IdBranche = i.IdBranche
                            INNER JOIN Branche b_dup ON b_dup.IdBranche = b.IdBranche
                            INNER JOIN Mandat m_dup on (m_dup.Exercice = i.Exercice) AND (m_dup.Numero = i.Numero) AND (b_dup.IdBranche=i.IdBranche) 
                            WHERE i.IdMandat != m_dup.IdMandat
             )
    BEGIN
      RAISERROR('error', 16, 1)
      ROLLBACK TRAN
    END 
0 голосов
/ 30 сентября 2018

INSERTED является таблицей, поэтому может содержать более одной строки, что означает, что этот код

SELECT @Cloturer=Cloturer, @Exercice=Exercice, @Numero=Numero, @IdBranche=IdBranche
FROM INSERTED

по существу неверен.

UDF не лучший выбор для наборана основе программирования и может привести к снижению производительности.В частности, этот UDF не имеет абсолютно никакого смысла и не имеет смысла инкапсулировать этот код в отдельный модуль.Это тривиальный код EXISTS.

Вся функция может и должна быть заменена на оператор EXISTS, весь код триггера может выглядеть следующим образом:

IF EXISTS(
  SELECT 1
  FROM INSERTED
  INNER JOIN ...
  WHERE ...
)
BEGIN
  RAISERROR(...)
END

I'mЯ не уверен, в чем смысл ваших таблиц и столбцов, но я предполагаю, что вы пытаетесь проверить уникальность.Итак, при условии, что вам не нужна еще одна Mandat запись для того же CategorieNumero, окончательный EXISTS может выглядеть следующим образом:

IF EXISTS(
   SELECT 1
   FROM INSERTED i
   INNER JOIN Branch b on b.IdBranche = i.IdBranch
   -- other branches with the same CategorieNumero; why isn't CategorieNumero unique?
   INNER JOIN Branch b_dup on b_dup.CategorieNumero = b.CategorieNumero  
   -- existing Mandat rows for the same CategorieNumero with any IdBranch
   INNER JOIN Mandat m_dup on m_dup = b_dup.IdBranch 
   -- ensure you're not comparing inserted/updated Mandat row to itself
   WHERE i.ID != m_dup.ID 
)
...

Но ваше намерение мне неясно, и я думаю, что после разъяснениябольшинство ваших потребностей будут легко удовлетворены уникальными ограничениями .

Если вам не нужно более одной строки для каждого набора (Exercice, Numero, IdBranch) - просто добавьте уникальное ограничение в таблицу Mandat и удалите и триггер, и функцию!

Нетриггеры чрезмерного использования.И UDFs.

...