web-dev-qa-db-ja.com

Oracleの列にシーケンスがあるかどうかを確認する

Oracleの列がシーケンスから入力されているかどうかを把握しようとしています。 Oracleがシーケンスを処理する方法についての私の印象は、シーケンスと列が別個のエンティティであり、次のような次のシーケンス値を手動で挿入する必要があるということです。

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

またはそれをテーブルトリガーに入れます。列がシーケンスから読み込まれたかどうかを判断するのは簡単ではないことを意味します。あれは正しいですか?列がシーケンスから入力されているかどうかを把握する方法についてのアイデアはありますか?

28
stimms

あなたは正しいです;シーケンスはテーブルから分離されており、単一のシーケンスを使用して任意のテーブルにデータを入力できます。一部のテーブルの列の値は、手動で生成された値を除いて、ほとんどがシーケンス(またはシーケンスのセット)に由来する場合があります。

つまり、列とシーケンスの間に必須の接続はありません。したがって、スキーマからそのような関係を発見する方法はありません。

最終的に、分析は、テーブルにデータを挿入または更新するすべてのアプリケーションのソースコードになります。他には何も保証されません。テーブルに変更を加える唯一の方法であるストアドプロシージャがある場合、または値を設定するトリガーなどがある場合、検索の範囲を縮小できます。しかし、一般的な解決策は、「ソースの分析」の「非解決策」です。

21

シーケンスがトリガーで使用されている場合、それが移入するテーブルを見つけることができます。

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>

このクエリを変更して、シーケンスを使用するストアドプロシージャなどを検索できます。

12
APC

Oracleシーケンスとデータベースでの使用との間に直接のメタデータリンクはありません。 USER_SEQUENCESメタデータをクエリし、LAST_NUMBER列を列のデータと比較することで、列の値がシーケンスに関連しているかどうかをインテリジェントに推測できます。

2
dpbradley

ジョナサンが指摘したように:両方のオブジェクトを関連付ける直接の方法はありません。ただし、主キーとシーケンス/トリガーの「標準を維持する」場合は、主キーを見つけて制約をテーブルシーケンスに関連付けることで確認できます。

マルチDB製品を構築しているため、同様の何かが必要でした。AutoIncrement、IncrementSeed、およびIncrementStepがシーケンスでのみ見つかる.NetのDataTableオブジェクトにあるプロパティを使用して、いくつかのクラスを複製しようとしました。

したがって、先ほど述べたように、テーブルに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;

それはあなたにスキーマ/テーブルの列のリストを与えるでしょう:

  • テーブル名
  • 列がNULL可能である場合
  • 制約タイプ(PKのみ)
  • シードをインクリメントする(シーケンスから)
  • 増分ステップ(シーケンスから)
  • 列コメント
  • もちろん列名:)
  • データ・タイプ
  • もしあれば、デフォルト値
  • 列の長さ
  • インデックス(列ID)
  • 精度(数値用)
  • スケール(数値用)

コードは最適化できると確信していますが、それは私にとっては機能します。それを使用してテーブルの「メタデータをロード」し、そのメタデータをフロントエンドのエンティティとして表現します。

私はそれらを気にしないので、主キーのみをフィルタリングし、複合キー制約を取得しないことに注意してください。その場合は、コードを変更してそうする必要があります。1つの列を2回取得できるため(1つはPK制約用、もう1つは複合キー用)、重複をフィルタリングする必要があります。

1
Gustavo Rubio
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
Ali