我有一个解释计划查询,我需要在 .Net 应用程序中使用参数进行调用。当我尝试如下时,它给出了 ORA-1780 错误。我的应用程序中有许多参数化查询,但此脚本不起作用。我该如何解决它?
private static readonly string sql =@"EXPLAIN PLAN SET STATEMENT_ID = :statementId FOR :sqlScript";
using (OracleCommand cmd1 = new OracleCommand(PrepareCostOracleSqlPattern, con))
{
cmd1.Parameters.Add(new OracleParameter("statementId", statementId));
cmd1.Parameters.Add(new OracleParameter("sqlScript", sqlScript));
cmd1.CommandTimeout = 6000;
object result = cmd1.ExecuteNonQuery();
}
ORA-01780:需要字符串文字
您似乎在
EXPLAIN PLAN
语句中使用绑定变量。 Oracle 不允许在 EXPLAIN PLAN
语句的参数中使用绑定变量,类似于 DDL 中不能使用绑定的方式。绑定仅适用于 SQL(选择和 DML)和 PL/SQL。
所以,不要使用
:
和添加参数,而是使用C#约定简单地使用字符串连接来拼接语句id和SQL语句。您不会希望使用可执行 SQL 来执行此操作,但对于解释计划或偶尔的 DDL 等特殊情况来说这是很好的。
EXPLAIN PLAN
不适用于参数化查询;相反,您需要使用字符串连接来构建查询:
类似(未经测试,但您应该了解总体思路):
private static readonly string sql =@"EXPLAIN PLAN SET STATEMENT_ID = '{0}' FOR {1}";
using (OracleCommand cmd1 = new OracleCommand(String.Format(sql, statementId, sqlScript), con))
{
cmd1.CommandTimeout = 6000;
object result = cmd1.ExecuteNonQuery();
}
您可以使用
EXECUTE IMMEDIATE
在 SQL 中复制问题(和解决方案),尝试使用绑定变量和字符串连接的组合:
DECLARE
v_sql VARCHAR2(4000) := 'SELECT * FROM DUAL';
v_id PLS_INTEGER := 42;
BEGIN
EXECUTE IMMEDIATE 'EXPLAIN PLAN SET STATEMENT_ID = :1 FOR :2'
USING v_id, v_sql;
END;
/
失败:
ORA-01780: string literal required
ORA-06512: at line 5
连接SQL语句:
DECLARE
v_sql VARCHAR2(4000) := 'SELECT * FROM DUAL';
v_id PLS_INTEGER := 42;
BEGIN
EXECUTE IMMEDIATE 'EXPLAIN PLAN SET STATEMENT_ID = :1 FOR ' || v_sql
USING v_id;
END;
/
也失败,因为语句 id 需要文字:
ORA-01780: string literal required
ORA-06512: at line 5
使用文字作为语句 id:
DECLARE
v_sql VARCHAR2(4000) := 'SELECT * FROM DUAL';
v_id PLS_INTEGER := 42;
BEGIN
EXECUTE IMMEDIATE 'EXPLAIN PLAN SET STATEMENT_ID = ''' || v_id || ''' FOR :1'
USING v_sql;
END;
/
也会失败,因为 SQL 语句也需要连接:
ORA-00905: missing keyword
ORA-06512: at line 5
连接两者:
DECLARE
v_sql VARCHAR2(4000) := 'SELECT * FROM DUAL';
v_id PLS_INTEGER := 42;
BEGIN
EXECUTE IMMEDIATE 'EXPLAIN PLAN SET STATEMENT_ID = ''' || v_id || ''' FOR ' || v_sql;
END;
/
1 rows affected
有效。