.NET / Oracle:如何以编程方式使用DDL语句执行脚本

时间:2013-07-18 13:51:35

标签: c# oracle ddl

我想对C#中的oracle数据库进行一些程序化的模式操作。因此,我在努力解决一些基本问题。

ddl sql语句位于脚本文件中。我不想使用sqlplus.exe,但我想在ODP.NET程序集(System.Oracle.DataAccess)中使用OracleCommand。这是我的脚本文件的一个例子:

script.sql:

DROP TABLE ABCDEF; 

DROP TABLE GHIJKL;

我想指出:

  • 该脚本包含DDL语句(数据定义语言)
  • 该脚本包含空行
  • 该脚本包含多个声明

以下代码应该执行我的脚本:

var content = File.ReadAllText("script.sql");

using (var oracleConnection = new OracleConnection(_connectionString))
{
     oracleConnection.Open();

     using (var command = new OracleCommand(content) { Connection = oracleConnection })
     {
          command.CommandType = CommandType.Text;
          command.ExecuteNonQuery();
     }
}

执行此代码,我确实收到了oracle错误:

Oracle.DataAccess.Client.OracleException:ORA-00911:无效字符

我认为,对于语句的格式化可能存在一些问题。任何提示都表示赞赏。谢谢。

--- --- EDIT

以简单的方式总结我的需求:我搜索一种方法来执行任何sql / ddl脚本,该脚本可由SQL Plus执行,以C#编程。

4 个答案:

答案 0 :(得分:5)

只需将其包裹在BEGIN和END中即可顺利运行

var content =string.Format("BEGIN {0} END;", File.ReadAllText("script.sql"));
using (var oracleConnection = new OracleConnection(_connectionString))            
{
  oracleConnection.Open();
  using (var command = new OracleCommand(content) { Connection = oracleConnection })
  {
       command.CommandType = CommandType.Text;
       command.ExecuteNonQuery();
  }
}

答案 1 :(得分:2)

感谢分号提示

我运行oracle脚本的最终代码!

1)它接受: -空行/注释(-)行 -以结尾的多行DDl / DML命令;

2)万一出错,它会抛出行号和sql命令异常!

    public async Task ExecuteScript(string _connectionString, string script)
    {
        using (StringReader sr = new StringReader(script))
        {
            var connection = new OracleConnection(_connectionString);
            connection.Open();

            string sqlCommand = "";
            string sqlLine; byte lineNum = 0;

            while ((sqlLine = sr.ReadLine()) != null)
            {
                sqlLine = sqlLine.Trim(); ++lineNum;

                if (sqlLine.Length > 0 && !sqlLine.StartsWith("--"))
                {
                     sqlCommand += (sqlCommand.Length > 0 ? Environment.NewLine : "") + sqlLine;  // Accept multiline SQL

                    if (sqlCommand.EndsWith(";"))
                    {
                        sqlCommand = sqlCommand.Substring(0, sqlCommand.Length - 1);

                        var command = new OracleCommand(sqlCommand, connection);

                        try
                        {
                            await command.ExecuteNonQueryAsync(); 
                        }
                        catch (OracleException ex)
                        {
                            connection.Close();
                            var e2 = new Exception($"{lineNum} - {sqlCommand} <br/> {ex.Message}");
                            throw e2;
                        }
                    }
                }
            }

            connection.Close();

            return;
        }
    }

答案 2 :(得分:1)

我会尝试一次执行一行,看看你是否有任何阻止执行的怪异角色。 (我也不确定你是否可以在一次通话中将所有命令一起发送)。

此外应删除行尾的分号

int lineNum = 0;
try
{
    string[] cmdTexts = File.ReadAllLines("script.sql");

    using (var oracleConnection = new OracleConnection(_connectionString))
    {
         oracleConnection.Open();
         OracleCommand command = new OracleCommand();
         command.Connection = oracleConnection;
         foreach(string cmd in cmdTexts)
         {
              lineNum++;
              if(cmd.Trim().Length > 0)
              {
                  if(cmd.EndsWith(";"))
                      cmd = cmd.Substring(0, cmd.Length - 1);

                  command.CommandText = cmd;
                  command.ExecuteNonQuery();
              }
         }
    }
}
catch(Exception ex)
{
    MessageBox.Show("Exception on line: " + lineNum + " message: " + ex.Message);
}

答案 3 :(得分:1)

正如@Steve所说,分号导致你的错误。并且您无法将整个文件包装到单个execute immediate命令中,因为它一次只能执行一个语句。您将需要解析您的文件并自行执行每个命令,删除分隔命令的分号。正如您所指出的,您的解析必须处理字符串文字,除了包含分号之外,还可以在单​​引号(')中包含加倍的单引号(''),用于开始和结束字符串文字。