比这复杂得多,但这是基本的
Person
表(id,name,emailaddress)Salesperson
table(id,personID)CustomerServiceRep
table(id,personID)Jeff是personID = 1的销售人员(id = 4)和customerservicerep(id = 5)。
简单
Trigger on SalesPerson Table
AFTER DELETE
AS
DECLARE @personID int = (SELECT personID FROM deleted);
IF @personID IS NOT NULL
BEGIN TRY
DELETE FROM Person
WHERE Person.id = @personID;
END TRY
BEGIN CATCH
END CATCH
DELETE FROM SalesPerson WHERE id=4;
原因
Msg 3616,Level 16,State 1 触发器执行期间出错。批处理已中止,用户事务(如果有)已回滚。
我确信如果某种约束存在personID
,则有一种更简单的方法可以不删除Private Sub Tab3_Plan_Enter(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Tab3_Plan.Enter
dgPlan.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
CircuitItems = LoadCatalogItems(dgPlan, cbVDSvcLocation, iKind.PlanSku)
' More event code
Private Function LoadCatalogItems(ByRef DGV As DataGridView, _
ByVal cbControl As System.Windows.Forms.ComboBox, _
ByRef ItemKind As Integer) As Integer
Dim DescDGName As String
Dim OrigInternalDesc As String
Dim DisplayDesc As String
DGV.Rows.Clear() ' <-- This is where the exception is thrown
' More function code
。或者赶上约束。如果有更多的表/列可能使用相同的表/约束(外键),那么浏览每个可能存在的表似乎非常重复并且可能更难。
答案 0 :(得分:0)
这里需要一个而不是删除触发器而不是后触发器。
CREATE Trigger tr_Delete_person
on Person
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
-- Delete any child records
Delete FROM SalesPerson
WHERE EXISTS (SELECT 1 FROM deleted
WHERE personID = SalesPerson.personID)
Delete FROM CustomerServiceRep
WHERE EXISTS (SELECT 1 FROM deleted
WHERE personID = CustomerServiceRep .personID)
-- Finally delete from the person table
DELETE FROM Person
WHERE EXISTS (SELECT 1 FROM deleted
WHERE personID = Person .personID)
END
答案 1 :(得分:0)
你的触发器中也有一个根本的缺陷,因为你似乎期望触发器将被激活每行一次 - 这是 NOT 在SQL Server中的情况。相反,触发器会在每个语句时触发,而伪表Deleted
可能包含多行。
鉴于该表可能包含多行 - 您希望在这里选择哪一行?
DECLARE @personID int = (SELECT personID FROM deleted);
未定义 - 您将从Deleted
中的一行,任意行中获取值,而忽略所有其他行 - 通常不强>你想要什么!
您需要使用Deleted
WILL 包含多行的知识重写整个触发器!您需要使用基于集合的操作 - 不要只期望Deleted
中的一行!