2013-06-04 3 views
0

내 방아쇠에 문제가 생겼다. 단일 행 업데이트에서 작동하지만 여러 업데이트의 경우 하위 쿼리가 하나 이상의 값을 반환한다는 오류가 발생합니다. 이것을 어떻게 처리 할 것인가.SQL 트리거, 둘 이상의 값을 반환하는 하위 쿼리입니다.

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 [email protected]) 
    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 , 
       [email protected] 
     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 [email protected] 

     WHERE customerID = @customerID 

    END 
+0

당신의 질문에 단서가 있는데, '삽입 된 표에는 삽입 된 행 (또는 새로운 업데이트 된 행)이 들어 있습니다.'라고 쓰여져 * rows *라고 쓰여지고 * 단 하나의 * 값을 선택하려고 시도하는 것입니다. 그것을 스칼라 변수에 할당하십시오. –

+0

이것은 아마도 집합 기반 연산으로 다시 쓰거나 계산 된 열 및/또는 인덱싱 된 뷰로 대체 할 수 있습니다. 그러나 먼저 테이블 구조에 대한 아이디어가 필요합니다. 예를 들어, 특정'customerID'에 대한 PaymentData의 한 행? –

+0

마침내 (지금은) IF (@month> = 2 및 ... begin ... if (@month <2 and ...) - 두 번째' if 문이 항상 만족 될 때 –

답변

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 

과 't 필요 트리거 - 테이블 및/또는 뷰입니다 항상 트리거 Status/_Status 업데이트 할 수 있도록 뷰에 필요한 수 있지만 (최대 올바른 - 그것은 즉 필요하거나 _Status 있는지 여부 현재 분명하지 않다 실제로 존재해야 함)

+0

내가 이것을 시도해 주셔서 감사합니다. – user2339573

0

두 개 이상의 고객 ID가 프로세스에 추가 될 수 있습니까? 해당 항목이없는 경우,

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

그러나 : 고객 ID 및 합계는 모든 행의 일관성을 보장하는 경우

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

, 당신처럼 MAX로 문제를 해결할 수 있습니다 :이 줄은 문제입니다 삽입 된 모든 행에 대해 일관성이 보장되므로 문제가 발생할 것입니다. 이 경우 값을 통해 커서를 이동하려면 커서가 있어야합니다.

또한이로 변경

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 
      ) 
+0

고객 ID가 일정하지 않음 (예 : 모든 고객의 경우 paymentdata 테이블에는 하나의 레코드 만 있지만 paymentreceipt 테이블에는 많은 레코드가 있음 – user2339573

+0

) 문제가 지불 데이터와 함께하지 않으므로 거기에 SUM을 할 필요가 없습니다. 삽입 된 SQL 서버는 다른 고객을 위해 여러 레코드를 삽입 할 수 있습니다. 그러나이를 방지하는 다른 비즈니스 로직이 있습니까? 그렇다면 , 그럼 당신은 안전하게 MAX를 사용할 수 있지만 정말 안전 커서를 선호 할 수도 있습니다. 주제 밖으로, 이런 종류의 논리는 트리거 밖에서 더 잘 수행됩니다, 왜냐하면 트리거가 더 불투명하고 이것은 정말로 당신의 도메인 논리이기 때문입니다 .JMO –

관련 문제