【问题标题】:DEFINE vs DECLARE - escaping quotesDEFINE vs DECLARE - 转义引号
【发布时间】:2014-07-15 05:07:14
【问题描述】:

我已经定义了一个变量

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 未定义相关的异常。

问题:

我收到语法异常,因为 myString 中的 abcdef 周围的引号没有转义。 "'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;

【问题讨论】:

标签: stored-procedures plsql oracle10g execute-immediate


【解决方案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;
/

【讨论】:

    【解决方案2】:

    感谢@ShaunPeterson 启发了这个问题的解决方案。虽然它直接解决了问题,但它提供了正确的方法,所以所有+1s 都应该去找他。

    他的回答不足之处在于他“声明”myStrings,而不是“定义”它。

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

    不是

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

    这就是问题的症结所在。在像下面的myStringsVar 这样的过程块中“声明”的PL/SQL 变量不会像“定义”变量那样被替换。根据 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;
    /
    

    【讨论】:

      猜你喜欢
      • 2010-11-11
      • 2018-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 2020-07-31
      • 2011-06-13
      相关资源
      最近更新 更多