当我从触发器中执行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
答案 0 :(得分:0)
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
我不确定您的表和列的含义是什么,但我认为您正在尝试检查某些唯一性。因此,假设您不希望同一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
表添加唯一约束,并删除触发器和函数!
不要过度使用触发器。还有UDF。
答案 1 :(得分:0)
我用过伊凡的解决方案
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