DEFINE vs DECLARE - 逃避报价

时间:2014-07-15 05:07:14

标签: stored-procedures plsql oracle10g execute-immediate

我定义了一个变量

define myStrings = "'abc','def'"

我稍后需要在过程块中使用并转换为varchars

的表
declare
    type varcharListType is table of varchar(200);
    myList varcharListType;

begin
    myList := varcharListType(&myStrings);
    .
    .
    .
end;
/

我试图在过程块中的创建查询中使用IN子句内的变量或表

execute immediate 'create table tmp_foo '
               || 'as select * from bar '
               || 'where bar_val in (&myStrings) ';

我尝试过使用the REPLACE功能

myNewStrings := replace(&myStrings, '''' , '''''');

但是我收到了与abcdef未定义相关的异常。

ISSUE:

我收到语法异常,因为abc中的defmyString周围的引号未被转义。值"'abc','def'"必须是“已定义”而不是“声明”,以便稍后替换。

问题:

是否有可能以一种方式'定义'变量,我可以将它既作为表类型值又作为execute immediate语句中的字符串使用?

重播:

创建

create table bar (bar_id number not null, bar_val varchar2(20), 
  constraint bar_pk primary key (bar_id)
  enable 
);

插入

insert into bar (bar_id, bar_val)
values (1, 'abc'),
       (2, 'def'),
       (3, 'ghi');

示例程序

set verify off;
set serveroutput on; 

define myStrings = "'abc','def'"

declare
    type varcharListType is table of varchar(20);
    myList varcharListType;

begin
    myList := varcharListType(&myStrings);

    execute immediate 'create table tmp_foo '
                   || 'as select * from bar '
                   || 'where bar_val in (&myStrings) ';

    for i in myList.FIRST..myList.LAST loop
        dbms_output.put_line('VALUE: ' || myList(i));
    end loop;
end;
/

set serveroutput off;
set verify on;

2 个答案:

答案 0 :(得分:1)

下面是我要采用的approch,注意在循环中使用tablen,这是因为DBMS_UTILITY.COMMA_TO_TABLE过程在表的末尾添加了一个空值。

希望你能找到这个有用的

declare

  myStrings varchar2(100) := '''abc'',''def''';
  myList dbms_utility.uncl_array;
  tablen number :=0;

begin

  DBMS_UTILITY.COMMA_TO_TABLE ( replace(myStrings, '''', ''),  tablen,  myList); 

  execute immediate 'create table tmp_foo '
               || 'as select * from bar '
               || 'where bar_val in (' ||myStrings||')';

  for i in myList.FIRST..tablen loop
    dbms_output.put_line('VALUE: ' || myList(i));
  end loop;
end;
/

答案 1 :(得分:0)

感谢@ShaunPeterson鼓励解决此问题。虽然它直接解决了问题,但它提供了正确的方法,因此所有+1都应该归他所有。

他的回答不明确的是他'宣布'myStrings而不是'定义'它。

declare
  myStrings varchar2(100) := '''abc'',''def''';

不是

define myStrings = "'abc','def'"

这里是问题的症结所在。在PL / SQL中,为下面的myStringsVar之类的过程块“声明”的变量不像“已定义”变量那样被替换。根据OP的要求,'myStrings'首先被'定义'然后被转换为在过程块中使用。

因此得到的解决方案如下所示:

define myStrings = "''abc'',''def''"

declare

  myStringsVar varchar2(100) := '&myStrings';
  myList dbms_utility.uncl_array;
  tablen number :=0;

begin

  DBMS_UTILITY.COMMA_TO_TABLE ( replace(myStringsVar, '''', ''),  tablen,  myList); 

  execute immediate 'create table tmp_foo '
               || 'as select * from bar '
               || 'where bar_val in (' || myStringsVar||')';

  for i in myList.FIRST..tablen loop
    dbms_output.put_line('VALUE: ' || myList(i));
  end loop;
end;
/