Триггер, созданный с ошибками компиляции


Я написал этот триггер, чтобы дисконтировать топ-клиента в базе данных на 10% при совершении новой покупки:

CREATE or REPLACE TRIGGER CLIENT_DISCOUNT
  BEFORE INSERT
  ON PURCHASE
  FOR EACH ROW
DECLARE
  CLIENTNO  NUMBER(5);
BEGIN
  SELECT (SELECT CLIENT.CLIENTNO, CLIENT.CNAME, TOTALS.TOTAL FROM CLIENT, 
    (SELECT CLIENTNO, SUM(AMOUNT) AS TOTAL FROM PURCHASE GROUP BY CLIENTNO) TOTALS WHERE CLIENT.CLIENTNO = TOTALS.CLIENTNO  AND ROWNUM <= 1 ORDER BY TOTALS.TOTAL DESC).CLIENTNO INTO CLIENTNO;
  IF :NEW.CLIENTNO = CLIENTNO THEN
    :NEW.AMOUNT = (:NEW.AMOUNT * 0.1);
  END IF;
END;

Однако, когда я выполняю это утверждение, я получаю следующее сообщение:

Warning: Trigger created with compilation errors.
Может кто-нибудь, пожалуйста, сказать мне, что я делаю не так?

Спасибо, Алекс.

Обновление-ошибки:

Errors for TRIGGER CLIENT_DISCOUNT:

LINE/COL
--------------------------------------------------------------------------------
ERROR
--------------------------------------------------------------------------------
4/3
PL/SQL: SQL Statement ignored

5/141
PL/SQL: ORA-00907: missing right parenthesis

7/17
PLS-00103: Encountered the symbol "=" when expecting one of the following:


LINE/COL
--------------------------------------------------------------------------------
ERROR
--------------------------------------------------------------------------------
   := . ( @ % ; indicator

8/3
PLS-00103: Encountered the symbol "END"

Решение:

CREATE or REPLACE TRIGGER CLIENT_DISCOUNT
    BEFORE INSERT
    ON PURCHASE
    FOR EACH ROW
DECLARE
    vCLIENTNO  NUMBER(5);
BEGIN
    SELECT TOPCLIENT.CLIENTNO INTO vCLIENTNO FROM (SELECT CLIENT.CLIENTNO, CLIENT.CNAME, TOTALS.TOTAL FROM CLIENT, (SELECT CLIENTNO, SUM(AMOUNT) AS TOTAL FROM PURCHASE GROUP BY CLIENTNO) TOTALS WHERE CLIENT.CLIENTNO = TOTALS.CLIENTNO  AND ROWNUM <= 1 ORDER BY TOTALS.TOTAL DESC) TOPCLIENT;
    IF :NEW.CLIENTNO = vCLIENTNO THEN
        :NEW.AMOUNT := (:NEW.AMOUNT * 0.9);
    END IF;
END;
/
3 3

3 ответа:

У меня нет ваших таблиц, поэтому я не могу гарантировать, что нашел все ваши ошибки. Однако я могу сказать следующее:

  1. я не верю, что вы можете сделать SELECT (....).CLIENTNO. Попробуйте SELECT x.CLIENTNO FROM (....) x вместо этого.
  2. ваш самый внешний SELECT не имеет предложения FROM. Попробуйте добавить FROM DUAL, так как этот внешний SELECT не выбирает ни из одной таблицы.
  3. оператор присваивания PL/SQL-это :=, а не =. Чтобы назначить :NEW.AMOUNT, нужно написать :NEW.AMOUNT := (:NEW.AMOUNT * 0.1);.
  4. умножение суммы на 0,1 дает клиенту скидку 90%, а не 10%.

Попробуйте

CREATE or REPLACE TRIGGER CLIENT_DISCOUNT
  BEFORE INSERT
  ON PURCHASE
  FOR EACH ROW
DECLARE
  vCLIENTNO  NUMBER(5);
BEGIN
  SELECT Z.CLIENTNO INTO vCLIENTNO FROM (SELECT CLIENT.CLIENTNO, CLIENT.CNAME, TOTALS.TOTAL FROM CLIENT, 
    (SELECT CLIENTNO, SUM(AMOUNT) AS TOTAL FROM PURCHASE GROUP BY CLIENTNO) TOTALS WHERE CLIENT.CLIENTNO = TOTALS.CLIENTNO  AND ROWNUM <= 1 ORDER BY TOTALS.TOTAL DESC) Z;
  IF :NEW.CLIENTNO = vCLIENTNO THEN
    :NEW.AMOUNT := (:NEW.AMOUNT * 1.091);
  END IF;
END;

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

Если вы можете изменить модель данных, возможно, вам нужно определить главного клиента в другой таблице, а не пытаться выбрать таблицу сумма сумм покупки, когда вы также вставляете в эту таблицу.