【问题标题】:Using String Concatenation in Oracle dynamic SQL在 Oracle 动态 SQL 中使用字符串连接
【发布时间】:2014-12-10 15:27:15
【问题描述】:

我正在尝试从 Oracle 存储过程返回一个游标。在我的 SP 中,我正在创建一个动态 SQL,但出现以下错误:

ORA-00604:递归 SQL 级别 1 发生错误
ORA-01003: 没有解析语句

这是我的代码,只有当我使用管道在我的 SQL 中添加变量时才会出现错误

PROCEDURE GET_EXP_INV_RECORD
(
OUT_REVENUE_DETAILS_CUR OUT OUTCURSOR, --  TYPE OUTCURSOR IS REF CURSOR
IN_SEQ_NO IN SOME_TABLE.SEQ#%TYPE
)AS
 L_SQL_QUERY varchar2(32000);
 L_LOC_BLR VARCHAR2(50)     := 'Bangalore';
 L_LOC_PUNE VARCHAR2(50)    := 'Pune';
 L_LOC_MAS VARCHAR2(50)     := 'Chennai';


 L_SQL_QUERY :=     'SELECT   
CASE WHEN CONDITION1  THEN  ' ||  L_LOC_BLR || -- POTENTIAL ERROR SOURCE
 ' WHEN CONDITION2  THEN  ' || L_LOC_PUNE   ||
 ' ELSE    ' || L_LOC_MAS ||  
 ' END AS LOCATION FROM MY_TABLE WHERE SOME_COL = SOME_VAL';

 OPEN OUT_REVENUE_DETAILS_CUR FOR L_SQL_QUERY;
EXCEPTION
  WHEN OTHERS THEN
  -- LOG THE ERROR
  ROLLBACK;
  RETURN; 
END GET_EXP_INV_RECORD;

如果我将变量 L_LOC_BLR 替换为实际字符串,它可以正常工作。 你能帮我找出这个错误的原因吗?

谢谢

【问题讨论】:

  • 打开游标时最好使用USING和绑定变量
  • 使用dynamic sql,始终在开发环境中使用dbms_output 进行测试。所以,发布dbms_output.put_line的输出。

标签: sql oracle cursor


【解决方案1】:

最常见的原因 - 你忘了引用你的字符串文字。

您可以单手轻松地调查问题 - 您应该只记录您的 SQL。在您的过程中添加 dbms_output.put_line(l_sql_query),查看输出并尝试手动执行它 - 您会看到原因。

无论如何,在大多数情况下,您的方法都是糟糕的设计。您应该改用绑定变量:

PROCEDURE GET_EXP_INV_RECORD
(
OUT_REVENUE_DETAILS_CUR OUT OUTCURSOR, --  TYPE OUTCURSOR IS REF CURSOR
IN_SEQ_NO IN SOME_TABLE.SEQ#%TYPE
)AS
 L_SQL_QUERY varchar2(32000);
 L_LOC_BLR VARCHAR2(50)     := 'Bangalore';
 L_LOC_PUNE VARCHAR2(50)    := 'Pune';
 L_LOC_MAS VARCHAR2(50)     := 'Chennai';


 L_SQL_QUERY :=     'SELECT ' ||  
 ' CASE WHEN CONDITION1  THEN  :L_LOC_BLR ' || -- POTENTIAL ERROR SOURCE
 ' WHEN CONDITION2  THEN  :L_LOC_PUNE ' ||
 ' ELSE :L_LOC_MAS ' ||  
 ' END AS LOCATION FROM MY_TABLE WHERE SOME_COL = SOME_VAL';

 OPEN OUT_REVENUE_DETAILS_CUR FOR L_SQL_QUERY 
     USING L_LOC_BLR, L_LOC_PUNE, L_LOC_MAS;

EXCEPTION
  WHEN OTHERS THEN
  DBMS_OUTPUT.PUT_LINE('ERROR SQL:' || L_SQL_QUERY);
  ROLLBACK;
  RETURN; 
END GET_EXP_INV_RECORD;

【讨论】:

  • 没有必要使用绑定变量,它不涉及设计。检查这个docs.oracle.com/database/121/TGSQL/tgsql_cursor.htm#TGSQL849
  • 如果您的意思是 cursor_sharing=force 之类的东西,那么它就是设计糟糕的应用程序的逃生舱,仅此而已。你可以阅读 Tom Kyte 的书籍和文章,比如tkyte.blogspot.ru/2008/02/…
  • 我不知道管道出了什么问题,但使用变量已经为我解决了这个问题。感谢您的宝贵时间。
【解决方案2】:

我认为你错过了下面的报价

 L_SQL_QUERY :=     'SELECT   
CASE WHEN CONDITION1  THEN  ''' ||  L_LOC_BLR || -- POTENTIAL ERROR SOURCE
 ''' WHEN CONDITION2  THEN  ''' || L_LOC_PUNE   ||
 ''' ELSE    ''' || L_LOC_MAS ||  
 ''' END AS LOCATION FROM MY_TABLE WHERE SOME_COL = SOME_VAL';

【讨论】:

  • @Ravi 使用 into 语句或普通游标在执行立即执行中运行字符串 sql
  • 普通光标是调用Java程序
猜你喜欢
  • 2011-07-27
  • 2023-03-25
  • 1970-01-01
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-14
  • 2014-08-08
相关资源
最近更新 更多