【发布时间】:2014-04-21 12:34:12
【问题描述】:
我很少使用触发器,但在更新语句上执行触发器时我似乎遇到了问题。例如,我有一个名为 Project 的表,我们允许软删除。我所说的软删除是在这个表中我们有一个名为Deleted的位字段,如果为真则表示记录已被删除,如果为假则表示它是有效记录。
现在这个表有很多关系(引用这个项目的表)。例如,一个项目可以有多个与之关联的程序。所以我有一个ProgramProject 表,其中一个程序可以有多个项目(1 对多关系,其中 1 是程序,许多是项目)。所以当我删除一个项目时(根据我上面提到的),触发器应该删除与之关联的所有项目......
但是,在某些情况下,当触发器执行时,它似乎会返回错误:
System.Data.SqlClient.SqlException was caught
HResult=-2146232060
Message=Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
我是否错误地执行了这些触发器?下面是一个触发器的例子:
ALTER TRIGGER [dbo].[trDeleteProject] ON [dbo].[Project]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
--check if the Deleted field was updated
IF(UPDATE(Deleted))
BEGIN
DECLARE @WasDeleted bit
DECLARE @ProjectID int
--get the project that was just deleted
SET @ProjectID = (SELECT ProjectID FROM Inserted)
--get whether they want the record deleted (1) or not (0)
SET @WasDeleted = (SELECT Deleted FROM Inserted)
--did they want to delete it? (1)
if (@WasDeleted=1)
BEGIN
--yes they delete the record so we remove instances...
--1.)Remove programs when a project is deleted
UPDATE ProgramProject SET Deleted=1 WHERE ProjectID = @ProjectID
--2.)Remove project contact roles when you delete a project
UPDATE ProjectContactRole SET Deleted=1 WHERE ProjectID = @ProjectID
--3.)Remove sub projects when you delete a project
--UPDATE SubProject SET Deleted=1 WHERE ProjectID = @ProjectID
--4.)Remove any transport system when you delete a project
UPDATE ProjectTransportSystem SET Deleted=1 WHERE ProjectID = @ProjectID
--5.)Remove any project mechanical architecture when you delete a project
UPDATE ProjectMechanicalArchitecture SET Deleted=1 WHERE ProjectID = @ProjectID
--6.)Remove any install personnel when you delete a project
UPDATE ProjectInstallPersonnel SET Deleted=1 WHERE ProjectID = @ProjectID
END
END
END
我是否因为它是触发器而错误地执行此操作?我应该加入某个临时表而不是单个更新语句吗?
更新
我尝试使用 M Ali 的示例,但遇到了同样的问题,子查询返回超过 1 行...
这是我使用的代码:
ALTER TRIGGER [dbo].[trDeleteProject] ON [dbo].[Project]
FOR UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT * INTO #temp
FROM Inserted i
WHERE i.deleted = 1
--1.)Remove programs when a project is deleted
UPDATE P
SET p.Deleted = 1
FROM #temp t INNER JOIN ProgramProject p ON P.ProjectID = t.ProjectID
--2.)Remove project contact roles when you delete a project
UPDATE Pr
SET pr.Deleted = 1
FROM #temp t INNER JOIN ProjectContactRole pr ON Pr.ProjectID = t.ProjectID
--3.)Remove sub projects when you delete a project
UPDATE SP
SET SP.Deleted = 1
FROM #temp t INNER JOIN SubProject sp ON SP.ProjectID = t.ProjectID
--4.)Remove any transport system when you delete a project
UPDATE PTS
SET PTS.Deleted = 1
FROM #temp t INNER JOIN ProjectTransportSystem PTS ON PTS.ProjectID = t.ProjectID
--5.)Remove any project mechanical architecture when you delete a project
UPDATE PMA
SET PMA.Deleted = 1
FROM #temp t INNER JOIN ProjectMechanicalArchitecture PMA ON PMA.ProjectID = t.ProjectID
--6.)Remove any install personnel when you delete a project
UPDATE PIP
SET PIP.Deleted = 1
FROM #temp t INNER JOIN ProjectInstallPersonnel PIP ON PIP.ProjectID = t.ProjectID
--7.)Remove any install shifts when you delete a project
UPDATE PIS
SET PIS.Deleted = 1
FROM #temp t INNER JOIN ProjectInstallShift PIS ON PIS.ProjectID = t.ProjectID
--8.)Remove any install windows when you delete a project
UPDATE PIW
SET PIW.Deleted = 1
FROM #temp t INNER JOIN ProjectInstallWindow PIW ON PIW.ProjectID = t.ProjectID
--9.)Remove any project pallet type when you delete a project
UPDATE PPT
SET PPT.Deleted = 1
FROM #temp t INNER JOIN ProjectPalletType PPT ON PPT.ProjectID = t.ProjectID
--10.)Remove issues related to a project
UPDATE I
SET I.Deleted = 1
FROM #temp t INNER JOIN Issue I ON I.ProjectID = t.ProjectID
--11.)Remove measurement architecture for a project
UPDATE PMAS
SET PMAS.Deleted = 1
FROM #temp t INNER JOIN ProjectMeasurementArchitectureSystem PMAS ON PMAS.ProjectID = t.ProjectID
--12.)Remove controls architecture for a project
UPDATE PCAS
SET PCAS.Deleted = 1
FROM #temp t INNER JOIN ProjectControlsArchitectureSystem PCAS ON PCAS.ProjectID = t.ProjectID
END
【问题讨论】:
-
我提出的方法中没有子查询,这段代码不能产生这个错误。请显示您正在执行的查询以触发此触发器。
-
为了调试,我会在触发器的顶部和底部放置一个打印语句。如果您收到错误但没有打印,则错误在触发器之前。如果你得到两个打印然后错误是触发之后的问题。如果您获得第一次打印,然后出现错误,则问题出在触发器中。我同意@M.Ali。除非您保留一些原始代码,否则我看不出您如何使用他提出的代码来获得该错误。
-
我相信因为这个触发器内部的更新正在调用其他触发器,所以我也必须查看其他触发器。
标签: sql sql-server triggers