7

如何正确进行以下更新:

using (OracleConnection conn = new OracleConnection())
using (selCmd)
{

    string sql1 = "update Table1 set name = joe where id = 10;"
    string sql2 = "update Table2 set country = usa where region = americas;"
    string sql3 = "update Table3 set weather = sunny where state = CA;"
    string sql4 = "update Table4 set engine = v8 where maker = benz;"

    cmdUpdate.CommandText = sql(#);
    cmdUpdate.Connection = conn;
    recs = cmdUpdate.ExecuteNonQuery();
}

如果这是一笔交易,我全都知道或一无所知,但我只是想看看它是如何以正确的方法工作的。

我正在考虑迭代一组项目 [sql1,sql2,sql3,sql4] 并在 CommandText 中传递 sql(#) 并每次执行 ExecuteNonQuery。

4

3 回答 3

10

如果我没记错的话,可以在一个字符串中连接多个 SQL 语句,用分号 (;) 分隔。否则,执行多个ExecuteNonQuery()调用没有任何问题。

string sql1 = "BEGIN update Table1 set name = 'joe' where id = 10;",
       sql2 = "update Table2 set country = 'usa' where region = 'americas';",
       sql3 = "update Table3 set weather = 'sunny' where state = 'CA';",
       sql4 = "update Table4 set engine = 'v8' where maker = 'benz'; END;";

string sql = string.Format("{0}{1}{2}{3}",sql1,sql2,sql3,sql4);

using (OracleConnection conn = new OracleConnection())
using (OracleCommand cmdUpdate = new OracleCommand(sql, conn))
{
    conn.Open();
    recs = cmdUpdate.ExecuteNonQuery();
}
于 2012-11-28T00:42:48.387 回答
2

我最近在一些旧代码中遇到了这个问题。我们动态构建 SQL 调用链(支持 Oracle 和 Sql Server)。由于当前没有 Oracle 生产实施,因此没有人测试 Oracle 操作并且没有出现客户错误。我找到了一个构建命令链的代码,然后,对于它使用的 Oracle String.Split(';')。然后,它使用循环来执行事务中的每个语句:rowsAffecter += ExecuteNonQuery....

我不喜欢这个想法,因为没有参数化它是危险的方法,因为一些数据可以包含;. 但即使参数化到位......

...为 Oracle ( )制作匿名块的问题之一是不会返回行数(返回 -1),有时需要判断是否有更新。"begin... end;"ExecuteNonQuery

为了解决这个问题,我已经这样做了

private string AppendOracleCountOrNothing(StringBuilder sql)
{
    if (_myProvider == Providers.Oracle)
        sql.AppendLine("rowCnt := rowCnt + SQL%ROWCOUNT;");
}


public void SomeMethod()
{
    var longSqlChain = new StringBuilder(2000);

    longSqlChain.Append("Insert into table...;");
    AppendOracleCountOrNothing(longSqlChain);
    if (someCondition)
    {
        longSqlChain.AppendLine("Update anotherTable...;");
        AppendOracleCountOrNothing(longSqlChain);
    } 

    // may be, add some more sql to longSqlChain here....

    int rowsAffected;
    if (_myProvider == Providers.Oracle)
    {
        longSqlChain.Insert(0, @"DECLARE
            rowCnt number(10) := 0
            BEGIN
            ").AppendLine(@":1 := rowCnt;
            END;");
        // Now, here we have some abstract wrappers that hide provider specific code. 
        // But the idea is to prepare provider specific output parameter and then parse its value
        IDataParameter p = ParameterWrapper.PrepareParameter(":1", 0, ParameterDirection.Output, myProvider); // note IDataParameter 
        SqlExecWrapper.ExecuteNonQuery(_myProvider, CommandType.Text, sql, new[]{p});
        rowsAffected = p.GetParameterValue(); // GetParameterValue is an extension on IDataParameter 
    }
    else // sql server
    {
        rowsAffected = SqlExecWrapper.ExecuteNonQuery(_myProvider, CommandType.Text, sql, null);
    }
}

这样我们就可以访问 DB 并获取受此调用影响的返回行数。查询也可以参数化。同样,最好开发抽象层,因此,您可以调用类似的东西parameterizer.CreateParameter(10),这将在您的 sql 语句中将参数添加到集合并生成:1, :2, :3, etc.(oracle)和@1, @2, @3, etc.(sql server)。

于 2018-04-11T14:42:02.543 回答
1

另一种方法是创建一个简单的扩展方法 (ExecuteMultipleNonQuery),它简单地将字符串拆分为所有分号并在循环中执行每个语句:

public static class DbCommandExtensions {

    public static void ExecuteMultipleNonQuery(this IDbCommand dbCommand)
    {
        var sqlStatementArray = dbCommand.CommandText.Split(new string[] {";"}, StringSplitOptions.RemoveEmptyEntries);
        foreach (string sqlStatement in sqlStatementArray)
        {
            dbCommand.CommandText = sqlStatement;
            dbCommand.ExecuteNonQuery();
        }
    }

}
于 2014-06-03T11:19:23.423 回答