#oracle #plsql #triggers
#Oracle #plsql #раздражители
Вопрос:
Я создал таблицу под названием LISTKOS
create table LISTKOS ( kostid number, name varchar2(50) not null, location varchar2(50), constraint pk_listkos primary key (kostid) );
Затем я продолжил создавать триггер для автоматического заполнения первичного ключа ( kostid
)
create or replace trigger LISTKOS before insert or update on LISTKOS for each row begin if inserting and :new.kostid is null then :new.kostid := dbms_random.string('x', 7); end if; end; /
Я выбрал «x», потому что хотел, чтобы оно было в буквенно-цифровой форме (и потому, что тип значений kostid
, как я описал при создании таблицы, таков number
).
Сообщение об ошибке продолжает появляться
ORA-06502: pl/sql numeric error
Ответ №1:
Вы объявили столбец как a number
, поэтому вы не можете хранить в нем буквенно-цифровые данные. Вы можете хранить только числовые данные. Если вы хотите хранить буквенно-цифровые данные, вам нужно объявить столбец как varchar2
. Если вы хотите заполнить первичный ключ случайным числом, вы должны использовать эту dbms_random.value
функцию.
Однако почти наверняка не имеет смысла генерировать значения первичного ключа случайным образом. Это относительно дорого для создания и (в зависимости от того, насколько загружена ваша система и какие диапазоны ключей вы разрешаете) может привести к конфликтам. Почти наверняка имело бы больше смысла использовать последовательность. Также не имеет смысла присваивать значение первичного ключа в on update
триггере.
create sequence kostid_seq start with 1 increment by 1; create or replace trigger LISTKOS before insert on LISTKOS for each row begin if :new.kostid is null then :new.kostid := kostid_seq.nextval; end if; end;
Комментарии:
1. Начиная с Oracle 12.1, это еще проще: мы можем использовать
identity
столбец с опциейgenerated by default on null
.2. Правда. Я предполагаю, что часть цели состоит в том, чтобы узнать о триггерах здесь.
3. в любом случае, я попытался использовать эту команду последовательности, но вместо этого получил следующее: Ошибки: СПИСОК ТРИГГЕРОВ Строка/Col: 4/4 PLS-00103: Обнаружен символ «КОНЕЦ» при ожидании одного из следующих:
4. @ruru — Вполне справедливо. Я пропустил точку с запятой. Обновил свой ответ
5. @ruru — Гораздо большая проблема с такими подходами (использование триггера с последовательностью или столбца идентификаторов) возникает, если мы делаем это в столбце, который является первичным ключом , и иногда мы разрешаем пользователю вводить идентификатор, в то время как в других случаях мы используем последовательность. Предположим, пользователь вводит допустимые значения идентификатора (1, 2, 3), а затем пытается ввести данные без идентификатора, полагаясь на значение по умолчанию. Значение последовательности может быть равно 1; тогда вставка завершится ошибкой, как нарушение ограничения PK. Такого рода определение таблицы требует больших проблем.
Ответ №2:
Триггер без используемой последовательности SQL
CREATE OR REPLACE TRIGGER LISTKOS BEFORE INSERT ON LISTKOS FOR EACH ROW WHEN (new.kostid is null) BEGIN SELECT nvl(max(kostid ),0) 1 INTO :NEW.kostid FROM LISTKOS; END;