查找Oracle中的列是否具有序列

时间:2009-11-13 15:44:38

标签: oracle metadata

我试图弄清楚Oracle中的列是否从序列中填充。我对Oracle如何处理排序的印象是序列和列是单独的实体,需要手动插入下一个序列值,如:

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

或将其放入表触发器中。这意味着判断列是否从序列中填充是非常重要的。那是对的吗?关于如何确定列是否从序列填充的任何想法?

5 个答案:

答案 0 :(得分:20)

你是对的;序列与表分开,单个序列可用于填充任何表,并且某些表中列中的值可能主要来自序列(或序列集),但手动生成的值除外。 / p>

换句话说,列和序列之间没有强制连接 - 因此无法从架构中发现这种关系。

最终,分析将是在表中插入或更新数据的所有应用程序的源代码。没有其他保证。如果存储过程是对表进行修改的唯一方法,或者存在设置值或其他此类事物的触发器,则可以缩小搜索范围。但一般的解决方案是“分析来源”的“非解决方案”。

答案 1 :(得分:11)

如果在触发器中使用序列,则可以找到它填充的表:

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 :(得分:2)

Oracle序列与数据库中的任何使用之间没有直接的元数据链接。如果列的值与序列相关,您可以通过查询USER_SEQUENCES元数据并将LAST_NUMBER列与列的数据进行比较来进行智能猜测。

答案 3 :(得分:1)

正如乔纳森所指出的那样:没有直接的方法可以将两个物体联系起来。但是,如果您为主键和序列/触发器“保持标准”,则可以通过查找主键找出,然后将约束与表序列相关联。

我需要类似的东西,因为我们正在构建一个多db产品,并且我试图复制一些具有在.Net的DataTable对象中找到的属性的类,它们具有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约束,另一个用于复合键)。

答案 4 :(得分: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'