2009-11-13 21 views
22

我試圖找出Oracle中的列是否從序列中填充。我對甲骨文如何處理測序的印象是,序列和列是獨立的實體,一個需要手動插入像一個序列值:查找Oracle中的列是否有序列

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

或把它變成一個表觸發。這意味着判斷列是否從序列中填充並不重要。那是對的嗎?關於如何確定列是否從序列中填充的任何想法?

+1

好問題!一個。 – caddis 2009-11-13 17:41:17

回答

17

你是對的;該序列與表分開,並且可以使用單個序列來填充任何表,並且某些表中列中的值可能主要來自序列(或序列集),但手動生成的值除外。

換句話說,列和序列之間沒有強制性連接 - 因此無法從模式中發現這種關係。

最終,分析將是在表中插入或更新數據的所有應用程序的源代碼。沒有其他保證。如果有一個存儲過程是對錶進行修改的唯一方法,或者存在設置值的觸發器或其他類似的東西,則可以減小搜索範圍。但一般的解決方案是'分析源'的'非解決方案'。

+3

Bah,這會讓這有點困難。 – stimms 2009-11-13 15:57:21

+1

如果那些出現在你之前的人是友善的,那麼序列的名稱將在其中包含表名。 我們製作了一個表格,以幫助開發人員將表格序列的名稱和表格的名稱包括在內。這在搜索序列時非常有用。 – 2009-11-13 17:07:53

2

Oracle序列與數據庫中的任何用途之間沒有直接的元數據鏈接。如果列的值通過查詢USER_SEQUENCES元數據並將LAST_NUMBER列與列的數據進行比較,您可以進行智能猜測。

10

如果序列被觸發時,就可以發現它填充哪些表:

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> 

您可以改變這個查詢查找存儲過程等,使利用序列。

+0

好主意,IMO是你擁有的最好的選擇。如果該序列不是用於觸發器中,而是例如在一個包中,這和一點都沒有關係一樣好。 – 2009-11-13 16:07:40

1

正如喬納森指出:沒有直接的方法來關聯這兩個對象。但是,如果您爲主鍵和序列/觸發器「保留一個標準」,您可以通過查找主鍵找到並將約束關聯到表序列。

我需要類似的東西,因爲我們正在構建一個多分貝產品,我嘗試複製一些類的屬性找到一個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的)
  • 增量種子(從序列)
  • 增量步驟(從序列)
  • 列註釋
  • 列名,當然:)
  • 數據類型
  • 缺省值,如果有的話
  • 列的長度
  • 索引(列ID)
  • 精度(對於數字)
  • 量表(用於數字)

我敢肯定,代碼可以優化,但它爲我工作,我用它來「加載元數據」的表,然後表示的元數據作爲對我的前端實體。

請注意,我只過濾主鍵並且不檢索複合鍵約束,因爲我不關心這些約束。如果你這樣做,你必須修改代碼才能這樣做,並確保過濾重複項,因爲你可以獲得一列兩次(一個用於PK約束,另一個用於複合鍵)。

+0

這些連接受到許多方面的限制。我運行了一個版本,併爲一個所有者獲得了數百個重複的行。請注意,主約束附加到表,但觸發器也在表上,而不是主鍵;並且一個表可以有多個由觸發器填充的列。如果它對你有效,那麼很好,但是YMMV。 – cliffordheath 2016-04-27 04:39:02

0
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' 
+0

歡迎來到SO。你能否更詳細地解釋SQL所做的事情?謝謝。 – 2015-07-31 22:06:19

+0

它將列出所有序列以及它們在我們常用來增加序列值的表和列上的用法。 – Ali 2015-08-06 14:24:33