SQL Trigger,子查询返回多个值。

时间:2013-06-04 12:13:28

标签: sql-server triggers

我的触发器出现问题,它适用于单行更新,但对于多次更新,它会给出子查询返回多个值的错误。如何处理这个。

    GO

    ALTER TRIGGER [dbo].[OnpaymentUpdate]
       ON  [dbo].[paymentData]
     AFTER UPDATE 
    AS 
    BEGIN  
        SET NOCOUNT ON;  
        DECLARE @customerID NCHAR(50),  @lastpaymentDate DATETIME, @stat nchar(50), @month int;
        SET @customerID= (SELECT customerID FROM inserted)  
SET @stat= (SELECT stat FROM inserted) --table inserted contains inserted rows (or new updated rows)
        set @lastpaymentDate =  (SELECT MAX(paymentDate) FROM paymentReceipt where customerID=@customerID)  
    SET @month= (SELECT DATEDIFF(MONTH,  @lastpaymentDate,GETDATE()))
     DECLARE @balance BIGINT
        SET @balance = 
                (
                    SELECT (totalprice-(paidAmount+concession)) 
                    FROM paymentData
                    WHERE customerID = @customerID
                )
                 Declare @paid int
                 SET @paid = 
                (
                    SELECT paidAmount 
                    FROM paymentData
                    WHERE customerID = @customerID
                )


        UPDATE PaymentData
            SET balanceAmount = @balance ,
              lastpaymentDate=@lastpaymentDate
        WHERE customerID = @customerID


    if (@month >=2  and @stat!='Cancel' and @stat!='Refund' And @stat!='Refunded' and @stat!='Transfered' and @stat!='Transfer')
    Begin

    IF  (@month <2 and @stat='Defaulter')
     SET @stat='Regular'
     IF (@balance<=0 and @paid >0)
     SET @stat='Payment Completed'
     else
     SET @stat='Defaulter'
     End
    else
    Begin

    if @stat='Refund'
     Set @stat='Refunded'
     if @stat='Cancled'
     Set @stat='Cancel'
     if @stat='Transfer'
     Set @stat='Transfered'
    End

     UPDATE PaymentData
            SET stat =@stat

        WHERE customerID = @customerID

    END

2 个答案:

答案 0 :(得分:0)

他们是否可以在此过程中添加多个CustomerID?这条线很麻烦:

   SET @customerID= (SELECT customerID FROM inserted)  
   SET @stat= (SELECT stat FROM inserted) --table inserted contains inserted 

如果保证customerID和stat对所有行保持一致,您可以使用MAX修复它,例如:

   SET @customerID= (SELECT MAX(customerID) FROM inserted)  
   SET @stat= (SELECT MAX(stat) FROM inserted) --table inserted contains inserted 

但是,如果不保证这些项目对于插入的所有行都是一致的,那么您将遇到麻烦。如果是这种情况,你需要一个光标来光标值。

也改为:

    SET @balance = 
            (
                SELECT SUM( (totalprice-(paidAmount+concession)) ) 
                FROM paymentData
                WHERE customerID = @customerID

            )
             Declare @paid int
             SET @paid = 
            (
                SELECT SUM(paidAmount) 
                FROM paymentData
                WHERE customerID = @customerID
            )

答案 1 :(得分:0)

我根本没有触发器。我重建你的表,然后创建一个模仿你当前表定义的视图。当然,我不知道你现在的桌子,所以我现在只能写出我最好的猜测。正如我所说的那样,我不明白你的状态逻辑在@month显然同时是>=2<2的底部,所以我让那部分不完整:

create table dbo._PaymentData (
    CustomerID nchar(50) not null,
    _Status nchar(50) not null,
    TotalPrice bigint not null,
    PaidAmount bigint not null,
    Concession bigint not null,
    Balance as TotalPrice - (PaidAmount + Concession)
)
go
create view dbo.PaymentData
with schemabinding
as
    with RecentReceipts as (
        select CustomerID,MAX(PaymentDate) as LastPayment from dbo.PaymentReceipt group by CustomerID
    ), MonthsDelinquent as (
        select CustomerID,LastPayment,DATEDIFF(month,LastPayment,CURRENT_TIMESTAMP) as Months from RecentReceipts
    )
    select
        pd.CustomerID,
        TotalPrice,
        PaidAmount,
        Concession,
        Balance,
        LastPayment,
        CASE
            WHEN _Status in ('Cancel','Refund','Refunded','Transfered','Transfer')
            THEN _Status
            WHEN md.Months > 2 and Balance<= 0 and PaidAmount > 0
            THEN 'Payment Complete'
            --More conditions here to work out the actual status
        END as Status
    from
        dbo._PaymentData pd
            left join
        MonthsDelinquent md
            on
                pd.CustomerID = md.CustomerID
go

现在,我们不需要触发器 - 表和/或视图总是正确的(尽管在视图上需要触发器 允许更新Status / _Status - 目前尚不清楚是否必要或者_Status是否真的需要存在)