#sql #oracle #triggers #ora-00904 #ora-00933
#sql #Oracle #триггеры #ora-00904 #ora-00933
Вопрос:
У меня есть две таблицы, TableA и TableB. Я хочу установить триггер. Как только вставка происходит в TableA, это может вызвать некоторые события в TableB.
Две таблицы выглядят следующим образом, например,
- Столбцы таблицы: (product_id, product_name, производство)
- Столбцы TableB: (покупатель, product_id)
Что я хочу сделать, так это: после вставки новой строки в таблицу A, если ее product_name равно null, затем запустите обновления в TableB. Обновите ‘ product_id TableB’ до этого нового вставленного product_id, если строки в TableB имеют то же производство, что и новое вставленное производство.
CREATE TRIGGER t1
AFTER INSERT ON tableA
FOR EACH ROW WHEN (NEW.product_name is NULL)
BEGIN
UPDATE tableB
SET tableB.product_id = :NEW.product_id
WHERE tableB.product_id IN (SELECT tableA.product_id
FROM tableA
WHERE tableA.manufacture = :NEW.manufacture);
END;
Он всегда жалуется на несколько ошибок в SQL developer:
Error(2,2): PL/SQL: SQL Statement ignored
Error(2,120): PL/SQL: ORA-00933: SQL command not properly ended
Error(2,36): PL/SQL: ORA-00904: "NEW"."product_id": invalid identifier
Error: PLS-00801: internal error [ph2csql_strdef_to_diana:bind]
Обновить:
CREATE TABLE "tableA"
(
"PRODUCT_ID" NUMBER PRIMARY KEY,
"PRODUCT_NAME" VARCHAR2(50 BYTE) DEFAULT NULL,
"MANUFACTURE" VARCHAR2(50 BYTE) DEFAULT NULL
)
CREATE TABLE "tableB"
(
"BUYER_ID" NUMBER PRIMARY KEY,
"PRODUCT_ID" NUMBER DEFAULT NULL
)
Комментарии:
1. Ознакомьтесь с этим сообщением , в котором приведен пример, аналогичный тому, что вы пытаетесь сделать.
2. проблема в том, что я думаю, что синтаксис правильный. Я не понимаю, почему oracle жалуется.
3. Можете ли вы также опубликовать инструкции create table ..? Это поможет воспроизвести вашу точную проблему..
4. Я опубликовал их. Спасибо
5. Вероятно, было бы лучше использовать хранимую процедуру для выполнения вставки в A и условного обновления в B. Такого рода работу трудно отследить до триггера, если у вас возникнут проблемы позже. У вас также могут возникнуть трудности с выбором из A внутри триггера — я не думаю, что известно, будет ли запрос к A включать вставляемую в данный момент строку, поэтому Oracle не позволит вам избежать двусмысленности. (Но может зависеть от версии — не уверен!)
Ответ №1:
Вы получаете все эти ошибки одновременно или разные ошибки при попытке выполнить разные действия? ORA-00904 (и, возможно, связанный с ним ORA-00933) появится, если вы опустили :
перед NEW.product_id
, а PLS-00801 может появиться из-за наличия пробела между ними
(т. Е. : NEW.product_id
. Не уверен, как вы могли бы получить оба одновременно.
В том виде, в каком она опубликована сейчас, она выглядит нормально — вы все еще получаете сообщение Errors: check compiler log
после TRIGGER T1 compiled
— или вы просматриваете старые ошибки в окне журнала компилятора разработчика SQL? Если вы не уверены, щелкните правой кнопкой мыши в окне журнала компилятора и выберите «Очистить» перед повторным запуском, чтобы увидеть, какие ошибки (если таковые имеются) действительно генерируются текущим кодом.
Ответ №2:
Вы создали таблицы со смешанными именами «TableA» и «TableB». Обычно это плохая практика в Oracle и приводит к проблемам при обращении к таблицам в коде, потому что на них нужно ссылаться в правильном регистре, заключенном в двойные кавычки:
CREATE TRIGGER t1
AFTER INSERT ON "tableA"
FOR EACH ROW WHEN (NEW.product_name is NULL)
BEGIN
UPDATE "tableB"
SET "tableB".product_id = :NEW.product_id
WHERE "tableB".product_id IN (SELECT "tableA".product_id
FROM "tableA"
WHERE "tableA".manufacture = :NEW.manufacture);
END;
Комментарии:
1. Поскольку триггер не будет компилироваться с другими подобными ошибками, я предположил, что имена таблиц были изменены непоследовательно для публикации, и все настоящие имена должны быть заглавными. В любом случае, конечно, стоит указать.
2. Да, вероятно, это не опубликованная проблема, но именно это произошло, когда я попытался воссоздать проблему, используя опубликованный код. И эти инструкции CREATE TABLE выглядят как копирование и вставка из SQL Developer, хотя, возможно, настоящие имена таблиц впоследствии были введены в смешанном регистре.
Ответ №3:
В SQL * Plus вам необходимо завершать CREATE TRIGGER
инструкцию с помощью /
в одной строке.
В зависимости от вашего инструмента SQL вам может потребоваться использовать другой способ установки альтернативного разделителя.
Ответ №4:
Измените предложение where в вашем вложенном операторе select с WHERE «TableA».manufacture = :NEW.manufacture на WHERE «TableA».manufacture = NEW.manufacture