powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / генерация id посредством триггера
22 сообщений из 22, страница 1 из 1
генерация id посредством триггера
    #39859713
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго дня. я человек новый в Оракле) мне 3 дня. есть такой вопрос. есть табличка с ключевым полем:
CREATE TABLE abs
(
num_ID NUMBER,
OWNER VARCHAR2(30),
NAME VARCHAR2(30),
TYPE VARCHAR2(19),
);
ALTER TABLE abs ADD (
CONSTRAINT PK_num_id
PRIMARY KEY
(num_id));

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

Данный триггер откомпилировался без ошибок

create or replace TRIGGER auto_id
BEFORE INSERT ON abs
FOR EACH ROW
DECLARE
BEGIN
if :new.num_id is null then
insert into abs (num_id, owner, name, type) values ((select max(num_id)from abs)+1, :new.owner, :new.name, :new.type);
end if;
END auto_id;

insert into abs (owner, name, type) values (100, 100, 100); - в инсерте явно не указан num_id, при попытке добавить запись ругается на то что ноль нельзя записать в ключевое поле, ругается правильно... как раз задача тригера исправить это, но увы не получается. подскажите пожалуйста, где ошибаюсь?
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859719
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nathgul
Код: plsql
1.
2.
3.
BEFORE INSERT ON abs
...
    insert into abs

Перевожу: перед вставкой вставить ещё одну другую хрень.
RTFM Correlation Names and Pseudorecords (FAQ)
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859722
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ну я примерно так и думал) как правильно сделать?
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859723
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
тригер after тоже использовать не могу, потому что запись не создается если поле с PK не может быть нулевым.
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859724
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nathgul,

:new.num_id:= ...

насчет select max(num_id)from abs
1) если вставлять за раз несколько строк будет мутация (ошибка выполнения)
ORA-04091: table ABS is mutating, trigger/function may not see it
2) при паралельной вставке возможен
ORA-00001: unique constraint (PK_NUM_ID) violated

обычно используют последовательность (в не древних версиях автономерацию);

для лабы может и прокатит
ТАК ДЕЛАТЬ НЕЛЬЗЯ!!!

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
SQL> create or replace TRIGGER auto_id
  2  BEFORE INSERT ON abs
  3  FOR EACH ROW
  4  WHEN (new.num_id is null)
  5  DECLARE
  6  BEGIN
  7    select nvl(max(num_id),0)+1 into :new.num_id from abs;
  8  END auto_id;
  9  /

Trigger created.

SQL> select * from abs;

    NUM_ID OWNER                          NAME                           TYPE
---------- ------------------------------ ------------------------------ -------------------
         2 Nathgul
         1 Stax



.....
stax
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859727
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nathgulкак правильно сделать?Вдумчиво прочитать в приведённой документации:
"A BEFORE trigger can change …"
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859728
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nathgulкак правильно сделать?

использовать последовательность

....
stax
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859729
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax ТАК ДЕЛАТЬ НЕЛЬЗЯ!!! Ты непоследователен. С одной стороны пережёвываешь, а с другой стороны так переживаешь.
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859746
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE TABLE MYAccess
(
  OBJECT_ID    NUMBER,
  OWNER        VARCHAR2(30),
  OBJECT_NAME  VARCHAR2(150),
  OBJECT_TYPE  VARCHAR2(30),
  CREATED      DATE
);

ALTER TABLE MYAccess ADD (
  CONSTRAINT PK_OBJECTS
 PRIMARY KEY
 (OBJECT_ID));


Итог:
Table MYACCESS created.
Table MYACCESS altered.
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859751
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
insert into MYaccess select object_id, owner, object_name, object_type, created from all_objects order by object_id asc;

CREATE OR REPLACE TRIGGER auto_id
BEFORE INSERT ON MYACCESS
FOR EACH ROW
WHEN (new.OBJECT_id is null)
DECLARE
BEGIN
   select nvl(max(OBJECT_id),0)+1 into :new.OBJECT_id from MYACCESS;
END auto_id;



59 973 rows inserted.
Trigger AUTO_ID compiled
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859755
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
select max(OBJECT_ID) from MYACCESS;
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
select * from MYACCESS where OWNER='200';



MAX(OBJECT_ID)
--------------
73993
1 row inserted.
OBJECT_ID OWNER OBJECT_NAME OBJECT_TYPE CREATED

-------------- ------------------------------ ---------------------------
73994 200 200


Вроде работает, всем спс.
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859758
Надфиль
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Staxдля лабы может и прокатит

нормальному преподу так не прокатит.
это иногда прокатит в однопользовательской среде :-)
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859765
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
StaxNathgulкак правильно сделать?

использовать последовательность

....
stax
...
WHEN (new.OBJECT_id is null)
DECLARE
BEGIN
select nvl(max(OBJECT_id),0)+1 into :new.OBJECT_id from MYACCESS;
...
странно почему работает так как надо, синтаксис говорит вроде как иначе nvl пашет.

Синтаксис Oracle/PLSQL функции NVL: NVL( string1, replace_with )
string1 - строка, которая проверяется на Null значение.
replace_with - возвращаемое значение, если string1 является Null.

можешь подсказать как правильно читать select nvl(max(OBJECT_id),0)+1 into :new.OBJECT_id from MYACCESS;???
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859766
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NathgulВроде работает, всем спс.
ВРОДЕ

1) добавте за раз несколько строк (insert from select)
2) добавте в двух сесcіях (паралельно/без commit)

.....
stax
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859774
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
StaxNathgulВроде работает, всем спс.
ВРОДЕ

1) добавте за раз несколько строк (insert from select)
2) добавте в двух сесcіях (паралельно/без commit)

.....
stax
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
create or replace TRIGGER auto_id
BEFORE INSERT ON MYACCESS
FOR EACH ROW
WHEN (new.OBJECT_id is null)
DECLARE
BEGIN
   select max(OBJECT_id)+1 into :new.OBJECT_id from MYACCESS;
END auto_id;


Код: plsql
1.
2.
3.
4.
5.
6.
[color=red]insert into MYaccess (object_id, owner, object_name, object_type) values (1, 200, 200, 200);[/color]
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);



убрал nvl из тригера, отчистил таблицу, внес новые записи... не срабатывало пока не внес первую строку с указанием OBJECT_ID вручную.

OBJECT_ID OWNER OBJECT_NAME
-----------------------------------------------------
1 200 200 200
2 200 200 200
3 200 200 200
4 200 200 200
5 200 200 200
6 200 200 200

6 rows selected.
я так понимаю ключевым было
FOR EACH ROW
WHEN (new.OBJECT_id is null)
DECLARE
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859789
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NathgulДоброго дня. я человек новый в Оракле) мне 3 дня. Какую версию Oracle Database использует новый человек?
Код: plsql
1.
SELECT * FROM V$VERSION;

?
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859794
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nathgul
я так понимаю ключевым было
FOR EACH ROW
WHEN (new.OBJECT_id is null)
DECLARE

не так
WHEN условие срабатывания триггера (срабатываем если не задан id)
имхо луче кодировать WHEN чем в теле IF


nvl нужен токо для первой строкі (клгда табличка пустая)
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SQL> ed
Wrote file afiedt.buf

  1* select max(id)+1 from (select 1 id from dual where 1=2) t
SQL> /

 MAX(ID)+1
----------


SQL> ed
Wrote file afiedt.buf

  1* select nvl(max(id),0)+1 from (select 1 id from dual where 1=2) t
SQL> /

NVL(MAX(ID),0)+1
----------------
               1



зы
Повторно
триггер не годится для практического пользования
1) добавте за раз несколько строк (insert from select)
2) добавте в двух сесcіях (паралельно/без commit)

.....
stax
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859818
Nathgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot Stax]Nathgul

зы
Повторно
триггер не годится для практического пользования
1) добавте за раз несколько строк (insert from select)
2) добавте в двух сесcіях (паралельно/без commit)

.....
stax

Код: plsql
1.
2.
3.
4.
5.
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);


добавлял двумя пакетами без комита. Итог 10 добавленных строк.. в таблице с OBJECT_ID полнейший порядок.
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39859824
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nathgulдобавлял двумя пакетами без комита.

insert into MYaccess (owner, object_name, object_type)
(select 200, 200, 200 from dual union all select 201, 201, 201 from dual)

ps
2) добавте в двух сесcіях/компютерах/окнах (паралельно/одновременно/без commit)

.....
stax
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39860015
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

ТС три дня от роду, он еще головку держать не научился, а ты ему про сессии какие то
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39860025
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nathgulдобавлял двумя пакетами без комита. Итог 10 добавленных строк.. в таблице с OBJECT_ID полнейший порядок.

Твой тригер может рабoтать только при INSERT VALUES и то в однопользовательском варианте.

Пример INSERT SELECT:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SQL> insert into MYaccess (owner, object_name, object_type) select 200, 200, 200 from dual;
insert into MYaccess (owner, object_name, object_type) select 200, 200, 200 from dual
            *
ERROR at line 1:
ORA-04091: table SCOTT.MYACCESS is mutating, trigger/function may not see it
ORA-06512: at "SCOTT.AUTO_ID", line 3
ORA-04088: error during execution of trigger 'SCOTT.AUTO_ID'


SQL> 



Пример с 2мя пользователями:

Сессия 1 выдает и не коммитит:

Код: plsql
1.
2.
3.
4.
5.
SQL> insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);

1 row created.

SQL> 



Сессия 2 выдает и висит:

Код: plsql
1.
2.
3.
SQL> insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);

 



Сессия 1 выдает коммит:

Код: plsql
1.
2.
3.
4.
5.
SQL> commit;

Commit complete.

SQL> 



Сессия 2 тут-же вылeтает с:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
SQL> insert into MYaccess (owner, object_name, object_type) values (200, 200, 200);
insert into MYaccess (owner, object_name, object_type) values (200, 200, 200)
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.PK_OBJECTS) violated


SQL> 



Почему? Сессия не видит незакоммиченные изменения другх сессий. Посему

Код: plsql
1.
select nvl(max(OBJECT_id),0)+1 into :new.OBJECT_id from MYACCESS;



сессии 2 выберет то-же значение что и сессия 1.

SY.
...
Рейтинг: 0 / 0
генерация id посредством триггера
    #39860106
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYПочему?В коня ли корм?..
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / генерация id посредством триггера
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]