创建调用 ORACLE 数据库以获取指定类型对象的 DDL 的 C# 例程

Posted

技术标签:

【中文标题】创建调用 ORACLE 数据库以获取指定类型对象的 DDL 的 C# 例程【英文标题】:Create C# routines that calls an ORACLE database to get the DDL for objects of a specified type 【发布时间】:2021-01-24 01:47:46 【问题描述】:

我希望能够为特定类型的对象生成 DDL。以下查询将返回架构“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# 函数,该函数返回特定 OWNER(模式)和对象类型(例如 TABLE)的 DDL。我假设第一条语句(存储过程的执行)为当前会话设置了一个选项,所以我假设我需要在同一个打开的连接上从 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;
            
        

【问题讨论】:

【参考方案1】:

您需要一次性执行 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;";


【讨论】:

以上是关于创建调用 ORACLE 数据库以获取指定类型对象的 DDL 的 C# 例程的主要内容,如果未能解决你的问题,请参考以下文章

oracle中用SQL语句创建和管理表

Oracle获取数据库中的对象创建语句

JDBC 调用函数或存储过程

oracle中使用impdp数据泵导入数据提示“ORA-31684:对象类型已经存在”错误的解决

是否可以从另一个调用 oracle 对象类型构造函数?

oracle 如何返回多条记录