Найти, если столбец в Oracle имеет последовательность - PullRequest
27 голосов
/ 13 ноября 2009

Я пытаюсь выяснить, заполнен ли столбец в Oracle из последовательности. У меня сложилось впечатление, что Oracle управляет секвенированием, что последовательность и столбец являются отдельными объектами, и нужно вручную вставить следующее значение последовательности, например:

insert into tbl1 values(someseq.nextval, 'test')

или поместите его в триггер таблицы. Это означает, что нетривиально определить, заполняется ли столбец из последовательности. Это верно? Любые идеи о том, как я мог бы выяснить, заполняется ли столбец из последовательности?

Ответы [ 5 ]

21 голосов
/ 13 ноября 2009

Вы правы; последовательность отделена от таблицы, и для заполнения любой таблицы может использоваться одна последовательность, а значения в столбце в некоторой таблице могут в основном поступать из последовательности (или набора последовательностей), за исключением значений, созданных вручную.

Другими словами, нет обязательной связи между столбцом и последовательностью - и, следовательно, нет способа обнаружить такую ​​связь из схемы.

В конечном счете, анализ будет исходным кодом всех приложений, которые вставляют или обновляют данные в таблице. Больше ничего не гарантировано. Вы можете уменьшить область поиска, если есть хранимая процедура, которая является единственным способом внести изменения в таблицу, или если есть триггер, который устанавливает значение, или другие подобные вещи. Но общее решение - это «не решение» «анализа источника».

12 голосов
/ 13 ноября 2009

Если последовательность используется в триггере, можно найти, какие таблицы она заполняет:

SQL> select t.table_name, d.referenced_name as sequence_name
  2  from   user_triggers t
  3         join user_dependencies d
  4         on d.name = t.trigger_name
  5  where  d.referenced_type = 'SEQUENCE'
  6  and    d.type = 'TRIGGER'
  7  /

TABLE_NAME                     SEQUENCE_NAME
------------------------------ ------------------------------
EMP                            EMPNO_SEQ

SQL>

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

2 голосов
/ 13 ноября 2009

Нет прямых связей метаданных между последовательностями Oracle и любым использованием в базе данных. Вы можете сделать разумное предположение, если значения столбца связаны с последовательностью, запросив метаданные USER_SEQUENCES и сравнив столбец LAST_NUMBER с данными для столбца.

1 голос
/ 01 августа 2015
select t.table_name,
   d.referenced_name  as sequence_name,
   d.REFERENCED_OWNER as "OWNER",
   c.COLUMN_NAME
  from user_trigger_cols t, user_dependencies d, user_tab_cols c
 where d.name = t.trigger_name
   and t.TABLE_NAME = c.TABLE_NAME
   and t.COLUMN_NAME = c.COLUMN_NAME
   and d.referenced_type = 'SEQUENCE'
   and d.type = 'TRIGGER'
1 голос
/ 12 сентября 2013

Как указал Джонатан: не существует прямого способа связать оба объекта. Однако, если вы «соблюдаете стандарт» для первичных ключей и последовательностей / триггеров, вы можете узнать об этом, найдя первичный ключ, а затем связать ограничение с последовательностью таблиц.

Мне нужно что-то подобное, так как мы создаем продукт с несколькими базами данных, и я попытался воспроизвести некоторые классы со свойствами, найденными в объекте DataTable из .Net, который имеет AutoIncrement, IncrementSeed и IncrementStep, который можно найти только последовательности.

Итак, как я уже сказал, если вы используете для своих таблиц PK и у вас всегда есть последовательность, связанная с триггером для вставок в таблицу, это может пригодиться:

select tc.table_name,
  case tc.nullable 
    when 'Y' then 1
    else 0
  end as is_nullable,
  case ac.constraint_type 
    when 'P' then 1
    else 0
  end as is_identity,
  ac.constraint_type,
  seq.increment_by as auto_increment_seed,
  seq.min_value as auto_increment_step,
  com.comments as caption,
  tc.column_name,
  tc.data_type,
  tc.data_default as default_value,
  tc.data_length as max_length,
  tc.column_id,
  tc.data_precision as precision,
  tc.data_scale as scale
from SYS.all_tab_columns tc
left outer join SYS.all_col_comments com
  on (tc.column_name = com.column_name and tc.table_name = com.table_name)
LEFT OUTER JOIN  SYS.ALL_CONS_COLUMNS CC 
  on (tc.table_name = cc.table_name and tc.column_name = cc.column_name and tc.owner = cc.owner)
LEFT OUTER JOIN SYS.ALL_CONSTRAINTS AC
  ON (ac.constraint_name = cc.constraint_name and ac.owner = cc.owner)
LEFT outer join user_triggers trg
  on (ac.table_name = trg.table_name and ac.owner = trg.table_owner)
LEFT outer join user_dependencies dep
  on (trg.trigger_name = dep.name and dep.referenced_type='SEQUENCE' and dep.type='TRIGGER')
LEFT outer join user_sequences seq
  on (seq.sequence_name = dep.referenced_name)  
where tc.table_name = 'TABLE_NAME'
and tc.owner = 'SCHEMA_NAME'
AND AC.CONSTRAINT_TYPE = 'P'
union all
select tc.table_name,
  case tc.nullable 
    when 'Y' then 1
    else 0
  end as is_nullable,
  case ac.constraint_type 
    when 'P' then 1
    else 0
  end as is_identity,
  ac.constraint_type,
  seq.increment_by as auto_increment_seed,
  seq.min_value as auto_increment_step,
  com.comments as caption,
  tc.column_name,
  tc.data_type,
  tc.data_default as default_value,
  tc.data_length as max_length,
  tc.column_id,
  tc.data_precision as precision,
  tc.data_scale as scale
from SYS.all_tab_columns tc
left outer join SYS.all_col_comments com
  on (tc.column_name = com.column_name and tc.table_name = com.table_name)
LEFT OUTER JOIN  SYS.ALL_CONS_COLUMNS CC 
  on (tc.table_name = cc.table_name and tc.column_name = cc.column_name and tc.owner = cc.owner)
LEFT OUTER JOIN SYS.ALL_CONSTRAINTS AC
  ON (ac.constraint_name = cc.constraint_name and ac.owner = cc.owner)
LEFT outer join user_triggers trg
  on (ac.table_name = trg.table_name and ac.owner = trg.table_owner)
LEFT outer join user_dependencies dep
  on (trg.trigger_name = dep.name and dep.referenced_type='SEQUENCE' and dep.type='TRIGGER')
LEFT outer join user_sequences seq
  on (seq.sequence_name = dep.referenced_name)  
where tc.table_name = 'TABLE_NAME'
and tc.owner = 'SCHEMA_NAME'
AND AC.CONSTRAINT_TYPE is null;

Это даст вам список столбцов для схемы / таблицы с:

  • Название таблицы
  • Если столбец обнуляемый
  • Тип ограничения (только для ПК)
  • Прирост семян (из последовательности)
  • Шаг приращения (из последовательности)
  • Комментарии к колонке
  • Название столбца, конечно:)
  • Тип данных
  • Значение по умолчанию, если есть
  • Длина столбца
  • Индекс (идентификатор столбца)
  • Точность (для чисел)
  • Шкала (для чисел)

Я почти уверен, что код можно оптимизировать, но он работает для меня, я использую его для «загрузки метаданных» для таблиц, а затем представляю эти метаданные в виде сущностей на моем интерфейсе.

Обратите внимание, что я фильтрую только первичные ключи и не получаю ограничения составного ключа, так как меня это не волнует. Если вы это сделаете, вам придется изменить код, чтобы сделать это, и убедиться, что вы фильтруете дубликаты, поскольку вы можете получить один столбец дважды (один для ограничения PK, другой для составного ключа).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...