我已经创建了一些类似的触发器,因此我常常发现常见的sntax错误 - 例如忘记END IF或THEN。我不能把这个编译成
CREATE OR REPLACE TRIGGER SOLD
BEFORE UPDATE OF STATUS ON STORE_COPY
FOR EACH ROW
DECLARE
RENT_OR_SALE NVARCHAR2(6);
UPDATED_DVD_ID NUMBER(10);
BEGIN
UPDATED_DVD_ID := SELECT DVD_ID FROM STORE_COPY WHERE :NEW.STATUS != :OLD.STATUS;
RENT_OR_SALE := SELECT (SELECT RENT_OR_SALE FROM DVD JOIN STORE_COPY ON STORE_COPY.DVD_ID = DVD.DVD_ID WHERE :NEW.STATUS != :OLD.STATUS) INTO RENT_OR_SALE FROM DUAL;
IF :NEW.STATUS != :OLD.STATUS
THEN
IF :OLD.STATUS = 'Y'
THEN
IF :NEW.STATUS = 'N'
THEN
IF RENT_OR_SALE = 'S'
THEN
INSERT INTO SOLD VALUES(NULL, CURRENT_TIMESTAMP, (SELECT PRICE FROM DVD JOIN STORE_COPY ON STORE_COPY.DVD_ID = DVD.DVD_ID WHERE :NEW.DVD_IS = UPDATED_DVD_ID), :NEW.DVD_ID);
END IF;
END IF;
END IF;
END IF;
END;
/
终端从“显示错误”中向我提供了此信息。命令:
Warning: Trigger created with compilation errors.
SQL> show errors;
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/23 PLS-00103: Encountered the symbol "SELECT" when expecting one of
the following:
( - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql stddev
sum variance execute forall merge time timestamp interval
date <a string literal with character set specification>
<a number> <a single-quoted SQL string> pipe
<an alternatively-quoted string literal with character set
specification>
<an alternat
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/5 PLS-00103: Encountered the symbol "RENT_OR_SALE"
答案 0 :(得分:2)
你不能使用&#34;选择&#34; IF检查条件内的子句。使用select INTO变量,然后在IF()中检查此变量。请参阅以下示例:if (select count(column) from table) > 0 then
答案 1 :(得分:1)
删除“;”从:
:NEW.STATUS != :OLD.STATUS;),
答案 2 :(得分:1)
您需要使用SELECT...INTO...
。 PL / SQL中没有variable := SELECT...
。一个起点是:
CREATE OR REPLACE TRIGGER SOLD
BEFORE UPDATE OF STATUS ON STORE_COPY
FOR EACH ROW
DECLARE
strRENT_OR_SALE NVARCHAR2(6);
nUPDATED_DVD_ID NUMBER(10);
BEGIN
SELECT DVD_ID
INTO nUPDATED_DVD_ID
FROM STORE_COPY
WHERE :NEW.STATUS != :OLD.STATUS;
SELECT RENT_OR_SALE
INTO strRENT_OR_SALE
FROM DVD
JOIN STORE_COPY
ON STORE_COPY.DVD_ID = DVD_ID
WHERE :NEW.STATUS != :OLD.STATUS;
IF :NEW.STATUS != :OLD.STATUS THEN
IF :OLD.STATUS = 'Y' THEN
IF :NEW.STATUS = 'N' THEN
IF RENT_OR_SALE = 'S' THEN
INSERT INTO SOLD VALUES
(NULL,
CURRENT_TIMESTAMP,
(SELECT PRICE
FROM DVD
JOIN STORE_COPY
ON STORE_COPY.DVD_ID = DVD.DVD_ID
WHERE :NEW.DVD_IS = UPDATED_DVD_ID),
:NEW.DVD_ID);
END IF;
END IF;
END IF;
END IF;
END;
但即便在这之后,你仍然会遇到错误。我怀疑那些SELECT是单例(也就是说,它们可能返回多行),所以他们会在运行时调整一下。即使你完成这件事,你仍然会得到一个ORA-04091错误(表正在变异;触发器看不到它)因为你在这个触发器中读取了SELECT语句触发器所在的表。
您尝试在那些SELECT FROM STORE_COPY...
语句中尝试读取的值是否与刚刚修改过的值相同?如果是这样,它们可用作:OLD和:NEW值,因此以下内容可能有效:
CREATE OR REPLACE TRIGGER SOLD
BEFORE UPDATE OF STATUS ON STORE_COPY
FOR EACH ROW
DECLARE
strRENT_OR_SALE NVARCHAR2(6);
nPrice NUMBER;
BEGIN
SELECT RENT_OR_SALE,
PRICE
INTO strRENT_OR_SALE,
nPrice
FROM DVD d
WHERE d.DVD_ID = :NEW.DVD_ID
IF :OLD.STATUS = 'Y' AND
:NEW.STATUS = 'N' AND
strRENT_OR_SALE = 'S'
THEN
INSERT INTO SOLD VALUES
(NULL,
CURRENT_TIMESTAMP,
nPrice);
END IF;
END TRIGGER_SOLD;
我可能已经猜到某些字段的位置(例如,我猜测PRICE是在DVD上。如果它实际上在STORE_COPY上,那么你可以使用:NEW.PRICE)。
分享并享受。