Последняя, не по значимости, а по порядку изложения! 
Стоит отметить, что она имеет очень большую практическую ценность, - и, по большому счету, ее очень не хватало.
Если рассмотреть нижеприведенный анонимный блок, выполненный в среде Oracle Database 11g (11.2.0.4):
[oracle@localhost]$ sqlplus rscott/rtiger
SQL*Plus: Release 11.2.0.4.0 Production on Sun May 3 00:07:27 2015
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> DECLARE
  b BOOLEAN;
BEGIN
  EXECUTE IMMEDIATE
    'begin :x := true; end;'
  USING
    OUT b;
END;
/
    OUT b;
        *
ERROR at line 7:
ORA-06550: line 7, column 9:
PLS-00457: expressions have to be of SQL types
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored
SQL> 
можно увидеть, что ошибка при передаче в динамический блок кода возникает даже когда переменная типа BOOLEAN передается именно в PL/SQL-блок.
Очевидно, что исполняющая среда PL/SQL предполагает, что исполняться будет именно SQL-выражение.
Для того, чтобы обойти это ограничение, приходилось применять вот примерно такой дорогостоящий workaround, связанный с преобразованиями значения из PL/SQL-типа в SQL-тип, и затем обратно:
SQL> create function CharToBoolean(v_pValue in char) return boolean is
begin
  if v_pValue = 'Y' then
    return true;
  end if;
  return false;
end;
/
Function created.
SQL> create function BooleanToChar(v_pValue in boolean) return char is
begin
  if v_pValue then
    return 'Y';
  end if;
  return 'N';
end;
/
Function created.
SQL> DECLARE
  b BOOLEAN;
  s char(1);
BEGIN
  EXECUTE IMMEDIATE
    'begin :x := BooleanToChar(true); end;'
  USING
    OUT s;
  b := CharToBoolean(s);
END;
/
PL/SQL procedure successfully completed.
SQL> 
Конечно-же, это усложняло понимание кода и дальнейшее его сопровождение.
Наконец-то, это ограничение снято в Oracle Database 12c, и приведеный выше первоначальный код теперь выполняется без ошибок:
Причем теперь, стало возможным передавать в динамический блок кода не только переменные типа BOOLEAN, но также PL/SQL-записи и PL/SQL-массивы:
[oracle@localhost Desktop]$ sqlplus / as sysdba
SQL*Plus: Release 12.1.0.2.0 Production on Sun May 3 00:10:28 2015
Copyright (c) 1982, 2014, Oracle.  All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL> DECLARE
  b BOOLEAN;
BEGIN
  EXECUTE IMMEDIATE
    'begin :x := true; end;'
  USING
    OUT b;
END;
/
PL/SQL procedure successfully completed.
SQL> 
Также поддерживается ситуация, когда передача параметра, имеющего PL/SQL, производится в SQL-выражение:
SQL> create or replace package Account_service is
  type
    TArrayOfVarchar2 is table of Varchar2(32) index by pls_integer;
end;
/
Package created.
set serveroutput on
DECLARE
  v_xArray Account_service.TArrayOfVarchar2;
BEGIN
  v_xArray(1) := 'First'; v_xArray(2) := 'Second';
  EXECUTE IMMEDIATE
    'begin
       for v_xIndex in 1..:v_xCount
       loop
         dbms_output.put_line(:v_pArray(v_xIndex));
       end loop;
     end;'
  USING
    IN v_xArray.Count,v_xArray;
END;
/
First
Second
PL/SQL procedure successfully completed.
 
SQL>
К сожалению, хэш-массивы (PL/SQL-массивы c INDEX BY VARCHAR2) пока не поддерживаются.
SQL> create or replace function printArray(v_pArray in Account_service.TArrayOfVarchar2) return number is
begin
  for v_xIndex in 1..v_pArray.count
  loop
    dbms_output.put_line(v_pArray(v_xIndex));
  end loop;
  return 1;
end;
/
Function created.
SQL>DECLARE
  v_xArray Account_service.TArrayOfVarchar2;
  n        number; 
BEGIN
  v_xArray(1) := 'First'; v_xArray(2) := 'Second';
  EXECUTE IMMEDIATE
    'SELECT printArray(:v_pArray) FROM dual'
  INTO 
    n
  USING
    IN v_xArray;
END;
/
First
Second
PL/SQL procedure successfully completed.
SQL>
И необходимо помнить, что динамический блок кода не является замыканием (closure), то есть используемый тип должен быть определен на уровне всей схемы - в спецификации пакета.
Поддержка передачи (и возвращения тоже!) в динамический SQL переменных имеющих PL/SQL-типы - это новая впечатляющая возможность Oracle Database 12c, которая позволяет упростить Ваш код, тем самым сделать его более читабельным и легким в сопровождении.

Спасибо большое за разъяснения.
ОтветитьУдалитьСпасибо за статью!
ОтветитьУдалитьОграничение на передачу хэш-массива можно обойти, если завернуть его в обычный nested table, также объявленный на уровне спецификации.
Спасибо за комментарий.
УдалитьМожете, пожалуйста, привести пример?