Oracleの列がシーケンスから入力されているかどうかを把握しようとしています。 Oracleがシーケンスを処理する方法についての私の印象は、シーケンスと列が別個のエンティティであり、次のような次のシーケンス値を手動で挿入する必要があるということです。
insert into tbl1 values(someseq.nextval, 'test')
またはそれをテーブルトリガーに入れます。列がシーケンスから読み込まれたかどうかを判断するのは簡単ではないことを意味します。あれは正しいですか?列がシーケンスから入力されているかどうかを把握する方法についてのアイデアはありますか?
あなたは正しいです;シーケンスはテーブルから分離されており、単一のシーケンスを使用して任意のテーブルにデータを入力できます。一部のテーブルの列の値は、手動で生成された値を除いて、ほとんどがシーケンス(またはシーケンスのセット)に由来する場合があります。
つまり、列とシーケンスの間に必須の接続はありません。したがって、スキーマからそのような関係を発見する方法はありません。
最終的に、分析は、テーブルにデータを挿入または更新するすべてのアプリケーションのソースコードになります。他には何も保証されません。テーブルに変更を加える唯一の方法であるストアドプロシージャがある場合、または値を設定するトリガーなどがある場合、検索の範囲を縮小できます。しかし、一般的な解決策は、「ソースの分析」の「非解決策」です。
シーケンスがトリガーで使用されている場合、それが移入するテーブルを見つけることができます。
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>
このクエリを変更して、シーケンスを使用するストアドプロシージャなどを検索できます。
Oracleシーケンスとデータベースでの使用との間に直接のメタデータリンクはありません。 USER_SEQUENCESメタデータをクエリし、LAST_NUMBER列を列のデータと比較することで、列の値がシーケンスに関連しているかどうかをインテリジェントに推測できます。
ジョナサンが指摘したように:両方のオブジェクトを関連付ける直接の方法はありません。ただし、主キーとシーケンス/トリガーの「標準を維持する」場合は、主キーを見つけて制約をテーブルシーケンスに関連付けることで確認できます。
マルチ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;
それはあなたにスキーマ/テーブルの列のリストを与えるでしょう:
コードは最適化できると確信していますが、それは私にとっては機能します。それを使用してテーブルの「メタデータをロード」し、そのメタデータをフロントエンドのエンティティとして表現します。
私はそれらを気にしないので、主キーのみをフィルタリングし、複合キー制約を取得しないことに注意してください。その場合は、コードを変更してそうする必要があります。1つの列を2回取得できるため(1つはPK制約用、もう1つは複合キー用)、重複をフィルタリングする必要があります。
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'