0

我定义了一个变量

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, '''' , '''''');

但我得到一个与未定义相关的abc异常def

问题:

我得到一个语法异常,因为周围abcdefin的引号myString没有被转义。该值"'abc','def'"必须是“定义”而不是“声明”,以便稍后替换。

问题:

是否可以“定义”一个变量,使我既可以将其用作表类型值,也可以将其用作执行立即语句中的字符串?

重现:

创造

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;
4

2 回答 2

1

下面是我要采用的方法,注意在循环中使用 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;
/
于 2014-07-17T05:57:10.683 回答
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;
/
于 2014-07-18T01:31:30.933 回答