我想对C#中的oracle数据库进行一些程序化的模式操作。因此,我在努力解决一些基本问题。
ddl sql语句位于脚本文件中。我不想使用sqlplus.exe,但我想在ODP.NET程序集(System.Oracle.DataAccess)中使用OracleCommand。这是我的脚本文件的一个例子:
script.sql:
DROP TABLE ABCDEF;
DROP TABLE GHIJKL;
我想指出:
以下代码应该执行我的脚本:
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#编程。
答案 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
命令中,因为它一次只能执行一个语句。您将需要解析您的文件并自行执行每个命令,删除分隔命令的分号。正如您所指出的,您的解析必须处理字符串文字,除了包含分号之外,还可以在单引号(')中包含加倍的单引号(''),用于开始和结束字符串文字。