Числовая или значимая ошибка при использовании » dbms_random.string`

#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;