我在触发器中遇到错误的逻辑。我在基表上更新后插入到Audit表中的记录数量是错误的。以下是重新创建此问题的代码段。
create table #T1 (id int NOT NULL, CODE varchar(3) NOT NULL, pkID INT NOT NULL)
insert into #T1 (id, CODE, pkID)
values(1, 'vak', 1989),(2,'Vl2',1988), (2,'Vl2',1988)--, (null, 'Gotik')
go
create table #T2 (id int NOT NULL, CODE varchar(3) NOT NULL, pkID INT NOT NULL)
insert into #T2 (id, CODE, pkID)
values(101, 'vas', 1979),(105,'va3',1973), (4,'va5',1888), (4,'va5',1888)--, (null, 'Popik')
go
create table [MyDB].dbo.Test_Dec22nd2017 (id int NOT null CONSTRAINT PK_TEST PRIMARY KEY, Ln varchar(10) null)
insert into [MyDB].dbo.Test_Dec22nd2017 (id, ln)
values (1, 'vasya1'),(2,'vasya3'), (4,'vasya2'),(5,'Super'), (6,'LYAYA'), (105,'TERSDF'), (101,'DFSDS')
go
DROP TRIGGER DBO.TR_TEST_DEC22nd2017
GO
CREATE TRIGGER DBO.TR_TEST_DEC22nd2017
ON [dbo].[Test_Dec22nd2017] AFTER INSERT, DELETE, UPDATE
NOT FOR REPLICATION
AS
BEGIN
IF NOT EXISTS ( SELECT TOP 1 1 FROM
inserted ins
FULL OUTER JOIN deleted del ON ins.ID = del.ID
INNER JOIN
[MyDB].dbo.Test_Dec22nd2017 a ON a.id = ISNULL(ins.ID, del.ID)
INNER JOIN #T1 t ON t.id = a.id
LEFT JOIN #T2 t2 ON t2.id = a.id
--WHERE t.id IS NULL AND t2.id IS NULL
)
BEGIN
WITH CTE2 AS (
SELECT
ISNULL(ins.ID, del.ID) AS ID,
CASE
WHEN ins.ID IS NOT NULL AND del.ID IS NOT NULL THEN 'UPDATE'
WHEN ins.ID IS NOT NULL THEN 'INSERT'
ELSE 'UPDATE' END
AS AuditType
FROM inserted ins
FULL OUTER JOIN deleted del
ON ins.ID = del.ID
)
,AUDIT_CTE2 AS (
SELECT DISTINCT
CTE2.ID,
'OVC' AS Code,
CTE2.AuditType
FROM CTE2
-- WHERE ID IS NOT NULL
)
INSERT [MyDB].[dbo].[AuditTable] (Code, ID, AuditType)/*, ParentCode, ParentID)*/
SELECT
Code,
ID,
AuditType
FROM AUDIT_CTE2
END
IF EXISTS ( SELECT TOP 1 1 FROM
inserted ins -- ISNULL(T.pkID, t2.pkID)
FULL OUTER JOIN deleted del ON ins.ID = del.ID
INNER JOIN
[MyDB].dbo.Test_Dec22nd2017 a ON a.id = ISNULL(ins.ID, del.ID)
LEFT JOIN #T1 t ON t.id = a.id
LEFT JOIN #T2 t2 ON t2.id = a.id
WHERE t.id IS NOT NULL OR t2.id IS NOT NULL
)
BEGIN
WITH CTE AS (
SELECT
ISNULL(ins.ID, del.ID) AS ID,
CASE
WHEN ins.ID IS NOT NULL AND del.ID IS NOT NULL THEN 'UPDATE'
WHEN ins.ID IS NOT NULL THEN 'INSERT'
ELSE 'UPDATE' END
AS AuditType
FROM inserted ins
FULL OUTER JOIN deleted del
ON ins.ID = del.ID
)
,AUDIT_CTE AS (
SELECT DISTINCT
CTE.ID,
'TST' AS Code,
CTE.AuditType,
ISNULL(T.CODE,T2.CODE) AS ParentCode,
ISNULL(T.pkID, T2.pkID) AS ParentID
FROM CTE
INNER JOIN MyDB.dbo.Test_Dec22nd2017 a ON CTE.ID = a.id
LEFT OUTER JOIN #T1 T ON T.id = a.id
LEFT OUTER JOIN #T2 T2 ON T2.id = a.id
WHERE T.pkID IS NOT NULL OR T2.pkID IS NOT NULL
)
INSERT [MyDB].[dbo].[AuditTable] (Code, ID, AuditType, ParentCode, ParentID)
SELECT
Code,
ID,
AuditType,
ParentCode,
ParentID
FROM AUDIT_CTE
END
END
这是导致将两个错误记录插入Audit talbe
的原因GO
UPDATE [MyDB].dbo.Test_Dec22nd2017
SET Ln = 'DDD' WHERE ID
IN (101,105,11)
SELECT TOP 30 * FROM [MyDB].[dbo].[AuditTable] ORDER BY 1 DESC
从上面的图片中可以看出,它在搜索审核表中插入了5行。但是应该只插入3.一个用于ID 6,父代码= Null,ParentID = NULL,两个记录用于ID 101和105,ParentID为1973和1979以及相应的父代码。
这两个陈述完美无缺。
insert into [MyDB].dbo.Test_Dec22nd2017 (id, ln)
values (44,'vasya1'), (45,'vasya2')
SELECT TOP 30 * FROM [MyDB].[dbo].[AuditTable] ORDER BY 1 DESC
GO
UPDATE [MyDB].dbo.Test_Dec22nd2017
SET Ln = 'DDD' WHERE ID
IN (5,10,6)
SELECT TOP 30 * FROM [MyDB].[dbo].[AuditTable] ORDER BY 1 DESC
答案 0 :(得分:0)
您可以将触发器中的第一个IF NOT EXISTS
更改为:
IF EXISTS (SELECT TOP 1 1 FROM
inserted ins
FULL OUTER JOIN deleted del ON ins.ID = del.ID
INNER JOIN
[tempdb].dbo.Test_Dec22nd2017 a ON a.id = ISNULL(ins.ID, del.ID)
LEFT JOIN #T1 t ON t.id = a.id
LEFT JOIN #T2 t2 ON t2.id = a.id
WHERE t.id IS NULL AND t2.id IS NULL
)
忽略#T1或#T2
中存在的任何ID