确定 Oracle 列由序列和触发器填充(标识列,如 SQLServer)
本文关键字:标识 SQLServer 触发器 Oracle 确定 填充 | 更新日期: 2023-09-27 18:31:46
我必须确定,如果一列被自动填满。
大多数情况下,这是在 PrimaryKey 列中完成的。这必须使用Oracle数据库以及SQLServer来完成。
我问题的背景是(只是为了您更好地理解),我正在阅读一个 XML 文件,其中规范说,元素标签与表的列名匹配。该表将由用户给出,他选择我必须解析的 xml 文件。之后,我正在寻找 xml 文件中的所有元素,如果它们与表中的列名称匹配。
目前尚不清楚 xml 文件是否会为我提供主键信息。可能是,但也不可能。如果列的名称将在 xml 内,一切都会很好。但如果没有,我必须查一下
- 我在 xml 文件中给出了一个 PK 列,还有
- 如果该 PK 列自动填充值
如果没有给出这一点,我必须提出一个例外。因此,我必须确定该架构信息。
使用SQLServer,这是没有问题的。IsAutoIncrement 将为真,如果它是一个标识列。
我像这样阅读表架构数据(只是一个简短的例子)
System.Data.Common.DbDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo);
dtTable = reader.GetSchemaTable();
现在我得到了我想要的所有信息。不幸的是,对于 Oracle,IsAutoIncrement 属性设置为 false。
我知道,如果 DBMS 没有像 SQLServer 那样在列中声明列,GetSchemaTable() 应该如何确定该列是否由序列设置。这对我来说很清楚。
有没有人有想法,如何解决这个问题?确定表中的列是否由触发器内的序列填充?也许解析触发器主体?
提前感谢您的任何帮助
我的解决方案现在如下所示:
if (IsOracleClient)
{
// reading Trigger Information
string sql = "select'n" +
" a.trigger_body'n" +
" from'n" +
" all_triggers a,'n" +
" all_trigger_cols b'n" +
" where'n" +
" a.table_name = '{0}''n" +
" and b.table_name = a.table_name'n" +
" and b.column_name = '{1}''n" +
" and a.trigger_name = b.trigger_name";
command.CommandText = String.Format(sql, this.Tabelle.ToUpper(), this.PrimaryKeyColumn.ColumnName.ToUpper());
using (System.Data.Common.DbDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
reader.Read();
string body = reader.GetString(0);
if (body.Contains("NEXTVAL"))
this.PrimaryKeyColumn.IsAutoIncrement = true;
}
reader.Close();
}
}
简短回答:您无法从架构信息中判断列是否由序列更新。
您可能使用的 Oracle 版本没有标识列的概念。该功能通常通过表上的序列和触发器进行复制。
在 Oracle DB 中,序列不绑定到特定列。任何给定的序列都可用于获取要插入到所需的任何数字列中的值。该序列可用于许多地方...触发器、过程、函数、单独的应用程序代码等。
我认为解析触发器的主体是一种选择。不过,如果您只关心通过触发器更新列,这是可行的。
这可能是一个不好的建议,但如果你确定数据库中的命名约定,你可能会做出一些假设,比如在序列名称中引用表和/或列名。话又说回来,尽管甲骨文中有一个讨厌的 30 个字符名称限制,可以很容易地打破这些假设。