簡體   English   中英

創建調用 ORACLE 數據庫以獲取指定類型對象的 DDL 的 C# 例程

[英]Create C# routines that calls an ORACLE database to get the DDL for objects of a specified type

我希望能夠為特定類型的對象生成 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,而無需此額外信息。

exec DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );

我希望能夠創建一個 C# function 返回特定所有者(模式)和 object 類型的 DDL,例如 TABLE。 我假設第一條語句,即存儲過程的執行,為當前 session 設置了一個選項,所以我假設我需要在同一個打開的連接上從 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 條語句。 你的選擇是

  1. 創建存儲過程
  2. 使用匿名塊

值得慶幸的是,有一種方法可以在沒有存儲過程的情況下做到這一點 - 使用匿名塊。 這是一個很好的例子

你的代碼看起來像

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;";


暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM