创建调用 ORACLE 数据库以获取指定类型对象的 DDL 的 C# 例程
Create C# routines that calls an ORACLE database to get the DDL for objects of a specified type
我希望能够为特定类型的对象生成 DDL。以下查询将 return 架构 'MYSCHEMA'.
中所有表的 DDL
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(OBJECT_TYPE, O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = 'MYSCHEMA' AND O.OBJECT_TYPE = 'TABLE'
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME
但是,我想排除物理属性、存储属性、表空间和日志记录。我知道如果我 运行 在上面的 SQL 声明之前 SQL 将根据需要生成 SQL,没有这个额外的信息。
exec DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
我希望能够创建一个 C# 函数,该函数 return 是特定所有者(架构)和对象类型的 DDL,例如 TABLE。我假设第一个语句(存储过程的执行)为当前会话设置了一个选项,因此我假设我需要在同一个打开的连接上从 C# 程序执行相同的两个步骤。我的印象是 DBMS_METADATA.SESSION_TRANSFORM 的计算结果为 -1。我不确定这一点。当我尝试使用以下 C# 例程执行 SP 时,出现此错误:
Unspecified error: E_FAIL(0x80004005)
我需要做什么才能使用 C# 代码执行两个 Oracle SQL 语句?
public DataTable GetDdlForObjectsOfTypeInSchema(string objectType, string owner, string connectionString)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
////exec DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
OleDbCommand command = connection.CreateCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "DBMS_METADATA.SET_TRANSFORM_PARAM";
command.Parameters.Add(new OleDbParameter("@TRANSFORM_HANDLE", OleDbType.Numeric) { Value = -1 });
command.Parameters.Add(new OleDbParameter("@NAME", OleDbType.VarChar) { Value = "SEGMENT_ATTRIBUTES" });
command.Parameters.Add(new OleDbParameter("@VALUE", OleDbType.Boolean) { Value = false });
try
{
command.ExecuteNonQuery();
}
catch (System.Exception e2)
{
string msg = e2.Message;
}
//Query
command = connection.CreateCommand();
command.Connection = connection;
command.CommandText = @"
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(REPLACE(OBJECT_TYPE, ' ', '_'), O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = ? AND O.OBJECT_TYPE = ?
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME
";
var oleDbDataAdapter = new OleDbDataAdapter(command);
DataSet dataset = new DataSet();
command.Parameters.Add(new OleDbParameter("@OWNER", OleDbType.Char) { Value = owner });
command.Parameters.Add(new OleDbParameter("@OBJECT_TYPE", OleDbType.Char) { Value = objectType });
try
{
oleDbDataAdapter.Fill(dataset);
return dataset.Tables[0];
}
catch (System.Exception e)
{
return null;
}
return null;
}
}
您需要一次执行 2 个语句。你的选择是
- 创建存储过程
- 使用匿名块
值得庆幸的是,有一种无需存储过程的方法 - 使用匿名块。
并且 here is a good example
你的代码看起来像
command.CommandType = CommandType.Text;
command.CommandText = @"
begin
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
open :rcursor for
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(OBJECT_TYPE, O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = 'MYSCHEMA' AND O.OBJECT_TYPE = 'TABLE'
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME;
end;";
我希望能够为特定类型的对象生成 DDL。以下查询将 return 架构 'MYSCHEMA'.
中所有表的 DDLSELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(OBJECT_TYPE, O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = 'MYSCHEMA' AND O.OBJECT_TYPE = 'TABLE'
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME
但是,我想排除物理属性、存储属性、表空间和日志记录。我知道如果我 运行 在上面的 SQL 声明之前 SQL 将根据需要生成 SQL,没有这个额外的信息。
exec DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
我希望能够创建一个 C# 函数,该函数 return 是特定所有者(架构)和对象类型的 DDL,例如 TABLE。我假设第一个语句(存储过程的执行)为当前会话设置了一个选项,因此我假设我需要在同一个打开的连接上从 C# 程序执行相同的两个步骤。我的印象是 DBMS_METADATA.SESSION_TRANSFORM 的计算结果为 -1。我不确定这一点。当我尝试使用以下 C# 例程执行 SP 时,出现此错误:
Unspecified error: E_FAIL(0x80004005)
我需要做什么才能使用 C# 代码执行两个 Oracle SQL 语句?
public DataTable GetDdlForObjectsOfTypeInSchema(string objectType, string owner, string connectionString)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
////exec DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
OleDbCommand command = connection.CreateCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "DBMS_METADATA.SET_TRANSFORM_PARAM";
command.Parameters.Add(new OleDbParameter("@TRANSFORM_HANDLE", OleDbType.Numeric) { Value = -1 });
command.Parameters.Add(new OleDbParameter("@NAME", OleDbType.VarChar) { Value = "SEGMENT_ATTRIBUTES" });
command.Parameters.Add(new OleDbParameter("@VALUE", OleDbType.Boolean) { Value = false });
try
{
command.ExecuteNonQuery();
}
catch (System.Exception e2)
{
string msg = e2.Message;
}
//Query
command = connection.CreateCommand();
command.Connection = connection;
command.CommandText = @"
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(REPLACE(OBJECT_TYPE, ' ', '_'), O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = ? AND O.OBJECT_TYPE = ?
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME
";
var oleDbDataAdapter = new OleDbDataAdapter(command);
DataSet dataset = new DataSet();
command.Parameters.Add(new OleDbParameter("@OWNER", OleDbType.Char) { Value = owner });
command.Parameters.Add(new OleDbParameter("@OBJECT_TYPE", OleDbType.Char) { Value = objectType });
try
{
oleDbDataAdapter.Fill(dataset);
return dataset.Tables[0];
}
catch (System.Exception e)
{
return null;
}
return null;
}
}
您需要一次执行 2 个语句。你的选择是
- 创建存储过程
- 使用匿名块
值得庆幸的是,有一种无需存储过程的方法 - 使用匿名块。 并且 here is a good example
你的代码看起来像
command.CommandType = CommandType.Text;
command.CommandText = @"
begin
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
open :rcursor for
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(OBJECT_TYPE, O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = 'MYSCHEMA' AND O.OBJECT_TYPE = 'TABLE'
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME;
end;";