Oracle - ORA-01422: точная выборка возвращает больше запрошенного количества строк - PullRequest
1 голос
/ 09 декабря 2011

Я все еще работаю над этой базой данных для небольшого розничного магазина (сценарий, к счастью!) И в настоящее время пытаюсь решить эту проблему с помощью триггера.

Соответствующими объектами являются Клиент, Оплата и Заказ,Платеж является связующим звеном между двумя другими, поэтому один Клиент может совершать много платежей, а в одном заказе может быть много платежей (необычно, но все же возможно), и это нормально.

Триггер:

CREATE OR REPLACE TRIGGER Check_Payment_Status  
BEFORE UPDATE OF Order_Status ON Customer_Order 

for each row
  DECLARE paymentStatus payment.payment_status%type;
  BEGIN

    select payment.payment_status into paymentStatus
    from payment
    where order_no = :new.order_no;

    IF (paymentStatus ='Failed' OR paymentStatus IS NULL ) then  
      RAISE_APPLICATION_ERROR(-20103, 'The full payment has not been made so the order cannot be     processed further until then.');
      update customer_order set order_status='Delayed' where order_no= :new.order_no;
    END IF;

    IF (paymentStatus ='Successful' ) then  
      update payment set payment_date=SYSDATE where order_no= :new.order_no;
    END IF;


  END; 
. 
run

На данный момент работает нормально.Обычно, прежде чем заказ клиента может быть помечен как «Отправлено», статус платежа должен быть «Успешный».Если он имеет значение null или «Failed», триггер будет выглядеть как «о, нет, не!»(но в более формальных словах), который работает как задумано.Однако если применить бизнес-правило «заказ может иметь много платежей», триггер должен проверить все соответствующие платежи, где я получаю эту ошибку, поскольку оператор SELECT INTO намеревается вернуть только одну строку.

Я немного читал о курсорах, но думаю, что здесь я зашёл слишком далеко - кто-нибудь может предложить какие-то решения, пожалуйста?

Ответы [ 3 ]

9 голосов
/ 09 декабря 2011

В общем, у вас есть много логики уровня приложения, связанной с триггером, который доставит вам много неприятностей в будущем, потому что вы не будете знать, когда и почему значения были обновлены вваши связанные таблицы.

У Дейва Косты есть хорошее предложение для обработки платежей, и я бы создал один или несколько связанных пакетов PL / SQL с четко написанными функциями и процедурами для обработки логики уровня приложения, которую вы 'мы пытаемся выполнить этот триггер.

Триггеры следует использовать очень редко - обычно, когда вы устанавливаете первичный ключ из последовательности или проверяете доступ к таблице.

9 голосов
/ 09 декабря 2011

Хорошо, если заказ может иметь несколько платежей, как вы решаете, будет ли он полностью оплачен? Предположительно, каждый платеж имеет определенную сумму, а заказ имеет общую сумму, подлежащую оплате, поэтому вам необходимо проверить, что полная сумма была выплачена. Мне кажется, вы можете сделать это, получив сумму всех успешных платежей, а затем сравнив ее с общей суммой задолженности. Основной запрос будет:

  SELECT SUM(payment_amount)
    INTO total_payment_amount
    FROM payment
    WHERE order_no = :new.order_no
      AND payment_status = 'Successful';
4 голосов
/ 24 октября 2012

Я знаю, что это старый вопрос, но сегодня он возник в производственной базе данных клиентов. Иногда бывает полезно упорядочить по первичному ключу, возможно, по порядковому номеру, в порядке убывания и использовать «rownum = 1». Естественно, вы должны выяснить, почему у вас есть более одной записи, которая соответствует критериям, и исправить ошибку в вашем приложении, которая позволяет это.

...