【发布时间】:2021-07-20 23:59:13
【问题描述】:
我正在尝试创建 DML 触发器以在 2 个表中执行某些删除和更新操作,
我有 3 张桌子:payments_yearly、payments_yearly_details、cheque_in
payments_yearly 表有所有付款,这些付款的详细信息(付款方式和值)保存在payments_yearly_details 中,付款方式可以是现金、签证、支票。检查详细信息将保存在cheque_in 表中。
我有一个查询,它从详细信息中获取付款信息 + 总和值,如下所示:
SELECT dbo.payments_yearly.ID, SUM(dbo.payments_yearly_details.value) AS value, dbo.payments_yearly.note,
dbo.payments_yearly.date, dbo.payments_yearly.app_user FROM dbo.payments_yearly INNER JOIN
dbo.payments_yearly_details ON dbo.payments_yearly.ID = dbo.payments_yearly_details.pay_id where payments_yearly.con_id=@con_id
GROUP BY dbo.payments_yearly.ID, dbo.payments_yearly.con_id, dbo.payments_yearly.note, dbo.payments_yearly.date, dbo.payments_yearly.app_user
因此,如果用户从payments_yearly 表中删除付款,我创建了一个触发器以从cheque_in 表中删除所有支票,并且我的触发器如下所示:
ALTER TRIGGER [dbo].[delete_cheque_after_delete_payment] on [dbo].[payments_yearly]
AFTER Delete
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare @payid as int
set @payid= (select ID from payments_yearly_details where pay_id=(SELECT deleted.ID FROM deleted) and method =N'شيك')
Delete from cheque_in where pay_id =@payid
END
但是当我从payments_yearly 删除任何付款时,支票也没有删除,所以我不知道这里的错误在哪里。
我试图将@pay_id 值更改为cheque_in 表中的静态值,例如25,但它与我创建的另一个触发器冲突,该触发器用于更新付款方式检查的payments_yearly_details 表值“因为这个值可能来自多张支票”当用户更改支票价值或删除与付款相关的支票时,触发如下:
ALTER TRIGGER [dbo].[Update_payments_yearly_detailson_cheque_UpdateDelete] on [dbo].[cheque_in]
after UPDATE, DELETE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF EXISTS (SELECT 1 FROM payments_yearly_details WHERE ID=(SELECT deleted.pay_id FROM deleted))
BEGIN
Declare @value as decimal(10,2)
set @value= (SELECT SUM(cheque_in.cheque_value) from cheque_in where cheque_in.pay_id = (SELECT deleted.pay_id FROM deleted))
Update payments_yearly_details set value=@value where ID=(SELECT deleted.pay_id FROM deleted)
END
END
此触发器运行良好,并在删除支票或更新支票值时更新付款值,但它与第一个触发器冲突,并出现以下错误消息:
System.Data.SqlClient.SqlException: 'Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. The statement has been terminated.'
我是触发器的新手,所以我的问题是:为什么我的第一个触发器不起作用?如果我为第一个触发器分配了一个静态值(在检查中,在这种情况下我的触发器工作),为什么我会在第二个触发器上收到错误消息。
谢谢。
【问题讨论】:
-
inserted和deleted是表,因此它们可以表示集合操作的结果。每个 statement 触发一次触发器,而不是 row。如果您绝对确定不会超过一排,那么请添加对行数的检查,并使用RaIsError或Throw明确告知以后来的人他们有试图执行不可接受的语句。 (if ( select Count(*) from inserted ) > 1 RaIsError( 'FooTable_Insert: No more than one row may be processed.', 25, 42 ) with log)
标签: sql-server tsql triggers