使用 oracle 参数绑定变量

bound variables using oracle parameters

寻找在 execute immediate 语句中绑定 oracle 参数的可能性。但现在面临的问题是,由于 Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-01008: not all variables bound exception,我无法在一个语句中执行多个查询。经过研究,我不知道是否可以这样做。

        var cmd = new OracleCommand
        {
            CommandText = "begin " +
                          $"  execute immediate 'CREATE PRIVATE TEMPORARY TABLE ORA$PTT_USERSTMP AS SELECT {string.Join(',', columnNames)} from USERS WHERE 1=0';" +
                          $"  execute immediate 'INSERT INTO ORA$PTT_USERSTMP ({string.Join(',', columnNames)}) VALUES ({string.Join(',', columnNames.Select((c, index) => $":{index + 1}"))})';" +
                          "end;"
        };
        
        cmd.ArrayBindCount = valuesToInsert.First().Count();
        foreach (var value in valuesToInsert)
        {
            cmd.Parameters.Add(new OracleParameter { OracleDbType = GetType(value), Value = value });
        }
        
        await cmd.ExecuteNonQueryAsync();

有什么办法可以做到这一点,或者我应该实施使用多个命令语句并在没有 'execute immediate'

的情况下始终如一地执行它们

更新 1 添加了 using 语句并且它有效但现在遇到另一个问题,我在 oracle 命令中添加了一个语句以从临时更新 table,但面临另一个问题:Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-32462: cannot use an object modified in current transaction,使用以下命令更新语句:

var cmd = new OracleCommand
{
  CommandText = "begin " +
    $"  execute immediate 'CREATE PRIVATE TEMPORARY TABLE ORA$PTT_USERSTMP AS SELECT {string.Join(',', columnNames)} from USERS WHERE 1=0';" +
    $"  execute immediate 'INSERT INTO ORA$PTT_USERSTMP ({string.Join(',', columnNames)}) VALUES ({string.Join(',', columnNames.Select((c, index) => $":{index + 1}"))})' using {string.Join(',', columnNames.Select((c, index) => $":{index + 1}"))};" +
    $"  execute immediate 'UPDATE USERS2 t1 SET ({string.Join(',', columnNames.Where(s => s != idColumnName).Select(s => "t1." + s))}) = (SELECT {string.Join(',', columnNames.Where(s => s != idColumnName).Select(s => "t2." + s))} FROM ORA$PTT_USERSTMP t2 WHERE t1.{idColumnName} = t2.{idColumnName})';" +
    "  execute immediate 'DROP TABLE ORA$PTT_USERSTMP';" +
    "end;"
};

[此处][1] 描述的错误 ORA-32462 简单意味着 table USERS 包含 未提交的更改 并且您不能使用用 CTAS

创建一个 PRIVATE TEMPORARY TABLE
create PRIVATE TEMPORARY TABLE ORA$PTT_USERSTMP as select * from USERS where 1=0;

触发器

ORA-32462: cannot use an object modified in current transaction

因此,如果PTT,您必须commit创建之前的事务,或者如果不可行,则将创建拆分为create tableinsert

简化示例

begin
  execute immediate 'create PRIVATE TEMPORARY TABLE ORA$PTT_USERSTMP (id int, col int)';
  execute immediate 'insert into ORA$PTT_USERSTMP(id,col) values(:1,:2)' using 1, 999;
...

顺便说一下,您可以用 ON COMMIT DROP DEFINITION 定义 PTT,这可以消除 excplicite DROP 的需要 [1]: ORA-32462: cannot use an object modified in current transaction