|
|
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Хотелось бы изменять тип (CREATE OR REPLACE TYPE XTLG_TYPE AS OBJECT ...) в схеме_1 при изменении структуры определенной таблицы в схеме_2. Есть такая возможность? 1. Создаем тип в схеме_1 create type XTLG_TYPE as object ( ID NUMBER, NUMB NUMBER(17,2) ); 2. Создаем таблицу RRR в схеме2 create table RRR ( ID NUMBER, NUMB NUMBER(17,2) ); 3. Создаем DDL-триггер в схеме_1 на изменение таблицы RRR в схеме_2 create or replace trigger ddl_trigger after alter on FACT.SCHEMA begin if ora_dict_obj_owner <> 'FACT' or ora_dict_obj_name <> 'RRR' then return; end if; EXECUTE IMMEDIATE 'CREATE OR REPLACE TYPE XTLG_TYPE AS OBJECT ( ID NUMBER, NUMB NUMBER(17,7) );'; end; 4. В схеме_2 пытаемся сохранить изменение структуры таблицы RRR. Получаем сообщение об ошибке. ORA-00604: error occurred at recursive SQL level 1 ORA-00902: invalid DDL operation in system triggers ORA-06512: at line 7 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.02.2017, 17:54 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Если не сработает триггер в автономной транзакции (а скорее всего, не сработает), можно из триггера запустить DBMS_JOB-задание на изменение типа ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.02.2017, 17:58 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Вячеслав Любомудров, спасибо, попробовал: job_text := 'begin execute immediate ''' || 'CREATE OR REPLACE TYPE XTLG_TYPE AS OBJECT ( ID NUMBER, NUMB NUMBER(17,7) )'';' || chr(10) || 'end;'; dbms_job.submit(job => job_no_out, what => job_text, next_date => sysdate, no_parse => TRUE); К сожалению, не помогло(. Задание висит. Смотрю select * from USER_JOBS поле FAILURES = 3 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.02.2017, 19:02 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
БородFAILURES = 3STFF job errors + ТОП №4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.02.2017, 19:11 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Elic, пока не понял( 1 пядь = 1/12 сажени = 1/4 аршина = 4 вершка = 7 дюймов = 17,78 см. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.02.2017, 19:28 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
БородВячеслав Любомудров, спасибо, попробовал: job_text := 'begin execute immediate ''' || 'CREATE OR REPLACE TYPE XTLG_TYPE AS OBJECT ( ID NUMBER, NUMB NUMBER(17,7) )'';' || chr(10) || 'end;'; dbms_job.submit(job => job_no_out, what => job_text, next_date => sysdate, no_parse => TRUE); К сожалению, не помогло(. Задание висит. Смотрю select * from USER_JOBS поле FAILURES = 3Ошибки ты можешь посмотреть в alert.log (и соответствующем trace-файле) или просто залогировав их в обработчике ошибок в какую-нибудь табличку. Но скорее всего, нет соответствующих прав. Например, CREATE TYPE предоставлена через роль, а не напрямую. Вот тебя и послали в ТОП4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2017, 01:59 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Почитал тут: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_8001.htm Из схемы_1 выполнил: GRANT all on FORS.XTLG_TYPE to FACT with grant option; GRANT EXECUTE ANY TYPE TO FACT with ADMIN OPTION; В trace-файле вижу: ORA-12012: error on auto execute of job 65 ORA-01031: insufficient privileges ORA-06512: at line 2 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.02.2017, 19:06 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
БородПочитал тут: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_8001.htm Читай ещё раз Prerequisites. До просветления. Бород1. Создаем тип в схеме_1 create type XTLG_TYPE as objectПопробуй после Код: plsql 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2017, 07:45 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Спасибо знатокам. Хотя полное просветление не наступило, но код как-то заработал. А именно: после изменения структуры таблицы схемы_2 (FACT.RRR) срабатывает триггер, изменяющий тип XTLG_TYPE в схеме_1. Только почему-то это изменение идет с запаздыванием на один шаг. Например, увеличиваю размер поля таблицы RRR в схеме FACT (схеме_2) с 9 до 10 - в типе XTLG_TYPE в схеме_1 он 9. Следущим шагом увеличиваю размер поля с 10 до 11 - в типе он 10... Заголовок тригерра такой: create or replace trigger ddl_trigger after alter on FACT.SCHEMA ... Пока не понял почему так несправедливо устроен мир Oracle:) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2017, 13:55 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
БородПока не понял почему так несправедливо устроен мир Oracle:) Без триггера: 1. Пользователь выдал ALTER TABLE 2. Oracle выполнил неявный COMMIT 3. Oracle изменил data dictionary 4. Oracle выполнил неявный COMMIT тем самым зафиксировав изменения. AFTER триггер выполняется как шаг 3.1, посему не видит изменения в data dictionary. Триггер запускает job который пока не выполняется. Шаг 4 выполняет COMMIT в прoцессе которого запускается job и не видит изменения в data dictionary. В результате имеем "с запаздыванием на один шаг". Измени время выполнения job на скажем SYSDATE + 10 / 3600 / 24 (+ 10 секунд). А вообще - ты изобретаешь велосипед с треугольными колесами, посему "Пока не понял почему так несправедливо устроен мир Oracle:)". В реляционных базах таблицы и их структура статичны. Поле NUMB траслируется (напрямую или косвенно) в какое-то бизнес определение предусматривающeе некоторый тип и размерность данных. Бизнес определение не скачет как биржевые сводки, и если меняется то редко. Так-что зачем эта динамика. Кроме того в серьезных проектах используется ERD и все структурные изменения делают там а затем генерируют DDL. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2017, 15:25 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
SYШаг 4 выполняет COMMIT в прoцессе которого запускается job и не видит изменения в data dictionary.Ты сегодня в ударе По тому триггеру, который он показал ему вообще не важен data dictionary ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2017, 15:30 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Вячеслав ЛюбомудровТы сегодня в ударе По тому триггеру, который он показал ему вообще не важен data dictionary Ну я дал товарищу "benefit of a doubt" и исходя из "Например, увеличиваю размер поля таблицы RRR в схеме FACT (схеме_2) с 9 до 10 - в типе XTLG_TYPE в схеме_1 он 9. Следущим шагом увеличиваю размер поля с 10 до 11 - в типе он 10" решил реальный триггер мняет тип согласно изменениям таблицы. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2017, 15:55 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
SYБез триггера: 1. Пользователь выдал ALTER TABLE 2. Oracle выполнил неявный COMMIT 3. Oracle изменил data dictionary 4. Oracle выполнил неявный COMMIT тем самым зафиксировав изменения. AFTER триггер выполняется как шаг 3.1, посему не видит изменения в data dictionary. Триггер запускает job который пока не выполняется. Шаг 4 выполняет COMMIT в прoцессе которого запускается job и не видит изменения в data dictionary. В результате имеем "с запаздыванием на один шаг". Измени время выполнения job на скажем SYSDATE + 10 / 3600 / 24 (+ 10 секунд). А вообще - ты изобретаешь велосипед с треугольными колесами, посему "Пока не понял почему так несправедливо устроен мир Oracle:)". В реляционных базах таблицы и их структура статичны. Поле NUMB траслируется (напрямую или косвенно) в какое-то бизнес определение предусматривающeе некоторый тип и размерность данных. Бизнес определение не скачет как биржевые сводки, и если меняется то редко. Так-что зачем эта динамика. Кроме того в серьезных проектах используется ERD и все структурные изменения делают там а затем генерируют DDL. SY. Спасибо. Время выполнения job увеличил. Не помогло. Дело в том, считывание структуры таблицы происходит ранее в этом же триггере. И проблема шага 3.1 возникает там: job_text := ' select LISTAGG(CASE' || ' WHEN t.DATA_TYPE = ''VARCHAR2'' THEN t.COLUMN_NAME||'' VARCHAR2(''||t.DATA_LENGTH||'')''||chr(10)' || ' WHEN t.DATA_TYPE = ''INTEGER'' THEN t.COLUMN_NAME||'' INTEGER''' || ' WHEN t.DATA_TYPE = ''NUMBER'' THEN t.COLUMN_NAME||'' NUMBER''||CASE WHEN t.DATA_PRECISION is not NULL THEN ''(''||t.DATA_PRECISION||CASE WHEN t.DATA_SCALE is not NULL THEN '',''||t.DATA_SCALE ELSE null END||'')'' ELSE null END||chr(10)' || ' WHEN t.DATA_TYPE = ''DATE'' THEN t.COLUMN_NAME||'' DATE''||chr(10)' || ' ELSE t.COLUMN_NAME' || ' END,' || ''',' || ''') WITHIN GROUP (ORDER BY t.SEGMENT_COLUMN_ID) agg' || ' from sys.all_tab_cols t' || ' where t.owner=''FACT''' || ' and t.table_name=''RRR''' || ' and t.COLUMN_ID > 0'; EXECUTE IMMEDIATE job_text INTO sql_text; Видимо, надо сделать задержку выолнения строки "EXECUTE IMMEDIATE job_text INTO sql_text". Непонятно как сделать это красиво. Зачем вся эта хрень? Статичные структуры таблиц иногда меняются. И хотелось бы процесс воздействия изменения на код автоматизировать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2017, 17:41 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
БородСпасибо. Время выполнения job увеличил. Не помогло. Дело в том, считывание структуры таблицы происходит ранее в этом же триггере. И проблема шага 3.1 возникает там: Видимо, надо сделать задержку выолнения строки "EXECUTE IMMEDIATE job_text INTO sql_text". Непонятно как сделать это красиво. Включить мозг: "AFTER триггер выполняется как шаг 3.1, посему не видит изменения в data dictionary". Посему считывание структуры таблицы должно быть не в триггере а в job. Передавай в job owner и table_name. БородЗачем вся эта хрень? Статичные структуры таблиц иногда меняются. И хотелось бы процесс воздействия изменения на код автоматизировать. Дорога в ад вымощена благими намерениями (хотелками). SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2017, 17:57 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
SYВключить мозг: "AFTER триггер выполняется как шаг 3.1, посему не видит изменения в data dictionary". Посему считывание структуры таблицы должно быть не в триггере а в job. Передавай в job owner и table_name. Мозг начал подавать признаки жизни :) Ок, передаю в job, выполняю select. Но дальше в коде второй job - пересоздание типа. Там нужен результат выполнения первого job. А на момент создания второго job результата первого еще нет, поэтому в строке для второго job видим хрень, верно? Есть возможность перед EXECUTE IMMEDIATE включить тормоз на 10 сек? Поможет ли это или напоремся на новые вилы? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2017, 18:05 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
SY, при всём уважении, втопку ERD ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2017, 18:11 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
точнее, не ERD, как таковое, а подход ERD >> DDL ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2017, 18:14 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Тормоз на минуту не помог. Мозг покрылся тиной и отключился. Пойдем в читалку;) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2017, 18:25 |
|
||
|
ALTER TYPE в DDL-тригере
|
|||
|---|---|---|---|
|
#18+
Зачем втоpой job? Job читает DBA_TAB_COLUMNS для owner + table_name, формирует текст для CREATE OR REPLACE TYPE и выполняет его через EXECUTE IMMEDIATE. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2017, 18:27 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39408052&tid=1886398]: |
0ms |
get settings: |
11ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
51ms |
get topic data: |
15ms |
get forum data: |
4ms |
get page messages: |
79ms |
get tp. blocked users: |
2ms |
| others: | 237ms |
| total: | 422ms |

| 0 / 0 |
