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

C# .NET/Oracle:如何以编程方式使用DDL语句执行脚本,c#,oracle,ddl,C#,Oracle,Ddl,我想对C#中的oracle数据库执行一些编程模式操作。因此,我面临一些基本问题 ddl sql语句位于脚本文件中。我不想使用sqlplus.exe,但我想在ODP.NET程序集(System.Oracle.DataAccess)之外使用OracleCommand。下面是我的脚本文件的一个示例: script.sql: DROP TABLE ABCDEF; DROP TABLE GHIJKL; 我想指出: 该脚本包含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:无效字符

我想,也许这些语句的格式有问题。任何暗示都将不胜感激。多谢各位

---编辑---


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

我将尝试一次执行一行,看看是否有任何奇怪的字符阻止执行。(我也不确定您是否可以在一次通话中同时发送所有命令)

您还应删除行末尾的分号

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);
}

正如@Steve所说,分号导致了您的错误。而且您不能将整个文件包装到单个
executeimmediate
命令中,因为该命令一次只能执行一条语句。您需要解析您的文件并单独执行每个命令,删除用于删除命令的分号。正如您所指出的,您的解析必须处理字符串文字,它除了包含分号外,还可能在开始和结束字符串文字的单引号(')中包含双单引号(“”)。

只需将其包装在开始和结束中,它就会顺利工作

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();
  }
}

感谢分号提示

运行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;
        }
    }
public async Task ExecuteScript(字符串_connectionString,字符串脚本)
{
使用(StringReader sr=新StringReader(脚本))
{
var connection=新的OracleConnection(_connectionString);
connection.Open();
字符串sqlCommand=“”;
字符串sqlLine;字节lineNum=0;
而((sqlLine=sr.ReadLine())!=null)
{
sqlLine=sqlLine.Trim();++lineNum;
if(sqlLine.Length>0&&!sqlLine.StartsWith(“--”)
{
sqlCommand+=(sqlCommand.Length>0?Environment.NewLine:)+sqlLine;//接受多行SQL
if(sqlCommand.EndsWith(“;”))
{
sqlCommand=sqlCommand.Substring(0,sqlCommand.Length-1);
var命令=新的OracleCommand(sqlCommand,连接);
尝试
{
wait命令。ExecuteNonQueryAsync();
}
捕获(OracleException-ex)
{
connection.Close();
var e2=新异常($“{lineNum}-{sqlCommand}
{ex.Message}”); 投掷e2; } } } } connection.Close(); 返回; } }
UPDATE:我试图用“DECLARE BEGIN EXECUTE IMMEDIATE'..'END'”来包装脚本的内容,因为这会对DDL语句有所帮助,但运气不好,同样的错误消息谢谢。这种方法的问题是,文本中可能包含分号,这将分解长脚本。那么您是说您在多行上有一个脚本?脚本之间没有可识别的分隔符?然后,您需要以某种方式拆分输入,因为我非常确定用作单个命令结尾的分号是导致错误的原因我不确定“多行上的单个脚本”是什么意思。但是我会有比一行长的“createtable”语句。最后,我需要一种机制来执行使用SQLPlus运行的相同脚本,而不会出现任何问题。如果您有扩展到多行的“命令”,并且在引号中还有带分号的文本文字,然后,唯一可能的解决方案是逐行解析,删除“commands”末尾的分号,但不删除文本文本中的分号。这不是一项容易的任务,您仍然需要分别传递每个“命令”。我没有要测试的Oracle安装,但是,在开始解析之前,我将尝试一个简单的文件sql,其中只有一个命令以分号结尾,然后没有分号,只是为了检查有分号和没有分号的区别。你不能简单地将它们移到sql脚本中吗?当然可以,这只是为了演示!