PL / SQL Nuevas características y mejoras de Oracle Database 11g



Mejoras en expresiones regulares de las funciones integradas de SQL

El REGEXP_INSTR y REGEXP_SUBSTR funciones incluyen un nuevo SUBEXPR parámetro que limita la coincidencia de patrón para una subexpresión específico en el patrón de búsqueda. 

 SQL> SELECT REGEXP_INSTR ('1234567890 ',' (123) (4 (56) (78)), 1, 1, 0, 'i', 1) de la doble;

 REGEXP_INSTR ('1234567890 ',' (123) (4 (56) (78)) ', 1,1,0,' I ', 1)
 -------------------------------------------------- -------
                                                         1

 Una fila seleccionada.

 SQL> SELECT REGEXP_INSTR ('1234567890 ',' (123) (4 (56) (78)), 1, 1, 0, 'i', 3) de la doble;

 REGEXP_INSTR ('1234567890 ',' (123) (4 (56) (78)) ', 1,1,0,' I ', 3)
 -------------------------------------------------- -------
                                                         5

 Una fila seleccionada.

 SQL> SELECT REGEXP_SUBSTR ('1234567890 ',' (123) (4 (56) (78)), 1, 1, 'i', 0) de la doble;

 REGEXP_S
 --------
 12345678

 Una fila seleccionada.

 SQL> SELECT REGEXP_SUBSTR ('1234567890 ',' (123) (4 (56) (78)), 1, 1, 'i', 1) de la doble;

 REG
 ---
 123

 Una fila seleccionada.

 SQL> SELECT REGEXP_SUBSTR ('1234567890 ',' (123) (4 (56) (78)), 1, 1, 'i', 3) de la doble;

 RE
 -
 56

 Una fila seleccionada.

 SQL> 
El nuevo REGEXP_COUNT función devuelve el número de veces que el patrón de búsqueda aparece en cadena de origen. 

SQL> SELECT REGEXP_COUNT ('123 123 123 123 ', '123', 1, 'i') de la doble;

 REGEXP_COUNT ('123123123123 ', '123', una 'I')
 ----------------------------------------
                                        4

 Una fila seleccionada.

 SQL> SELECT REGEXP_COUNT ('123 123 123 123 ', '123', 9 'i') de la doble;

 REGEXP_COUNT ('123123123123 ', '123', 9 'I')
 ----------------------------------------
                                        2

 Una fila seleccionada.

 SQL> 

SIMPLE_INTEGER tipo de datos

El SIMPLE_INTEGER tipo de datos es un subtipo de la PLS_INTEGER tipo de datos y puede aumentar drásticamente la velocidad de la aritmética de enteros en el código nativo compilado, pero sólo muestra las mejoras de rendimiento marginal en código interpretado. El procedimiento siguiente se compara el rendimiento de la SIMPLE_INTEGER y PLS_INTEGER tipos de datos. 
CREAR O CAMBIAR simple_integer_test_proc PROCEDIMIENTO AS
   l_start número;
   NÚMERO l_loops: = 10000000;
   l_pls_integer PLS_INTEGER: = 0;
   l_pls_integer_incr PLS_INTEGER: = 1;
   l_simple_integer SIMPLE_INTEGER: = 0;
   l_simple_integer_incr SIMPLE_INTEGER: = 1;
 INICIO

   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     l_pls_integer: = + l_pls_integer l_pls_integer_incr;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("PLS_INTEGER: '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');

   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     l_simple_integer: = + l_simple_integer l_simple_integer_incr;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("SIMPLE_INTEGER: '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');


 END simple_integer_test_proc;
 / 
Cuando se ejecuta en el modo por defecto interpreta la mejora del rendimiento de la SIMPLE_INTEGER tipo de datos no es espectacular. 
SQL> JUEGO DE serveroutput
 SQL> EXEC simple_integer_test_proc;
 PLS_INTEGER: 47 hsecs
 SIMPLE_INTEGER: 44 hsecs

 PL / SQL terminado con éxito.

 SQL> 
Nos nativa compilar el procedimiento mediante la alteración de la PLSQL_CODE_TYPE valor de la sesión y volver a compilar el procedimiento. 
ALTER SET SESSION PLSQL_CODE_TYPE = Nativo;
 ALTER PROCEDIMIENTO COMPILAR simple_integer_test_proc; 
Compilar de forma nativa el procedimiento produce importantes mejoras de velocidad para ambos tipos de datos, pero más aún para el SIMPLE_INTEGER tipo de datos. 
SQL> JUEGO DE serveroutput
 SQL> EXEC simple_integer_test_proc;
 PLS_INTEGER: 10 hsecs
 SIMPLE_INTEGER: 2 hsecs

 PL / SQL terminado con éxito.

 SQL> 
Las mejoras de velocidad son el resultado de dos diferencias fundamentales entre los dos tipos de datos. En primer lugar, SIMPLE_INTEGER y PLS_INTEGER tienen el mismo rango (-2.147.483.648 a 2.147.483.647), pero SIMPLE_INTEGER arropa cuando se excede de sus límites, en lugar de tirar un error como PLS_INTEGER . 
JUEGO DE serveroutput
 DECLARE
   l_simple_integer SIMPLE_INTEGER: = 2147483645;
 INICIO
   For i in 1 ..  4 LOOP
     l_simple_integer: = l_simple_integer + 1;
     DBMS_OUTPUT.PUT_LINE (to_char (l_simple_integer, 'S9999999999'));
   END LOOP;

   For i in 1 ..  4 LOOP
     l_simple_integer: = l_simple_integer - 1;
     DBMS_OUTPUT.PUT_LINE (to_char (l_simple_integer, 'S9999999999'));
   END LOOP;
 END;
 /
 +2147483646
 +2147483647
 -2147483648
 -2147483647
 -2147483648
 +2147483647
 +2147483646
 +2147483645

 PL / SQL terminado con éxito.

 SQL> 
En segundo lugar, SIMPLE_INTEGER nunca puede tener un valor NULL, ya sea cuando se declara, o por la cesión. 
DECLARE
   l_simple_integer SIMPLE_INTEGER;
 INICIO
   NULL;
 END;
 /
                    *
 ERROR en línea 2:
 ORA-06550: línea 2, columna 20:
 PLS-00218: una variable declarada como NOT NULL deben tener una asignación de inicialización

 SQL>

 DECLARE
   l_simple_integer SIMPLE_INTEGER: = 0;
 INICIO
   l_simple_integer: = NULL;
 END;
 /
                       *
 ERROR en la línea 4:
 ORA-06550: línea 4, columna 23:
 PLS-00382: la expresión es de tipo incorrecto
 ORA-06550: línea 4, columna 3:
 PL / SQL: Instrucción omite

 SQL> 
La eliminación de desbordamiento y el resultado NULL comprobación en una reducción significativa en los gastos generales en comparación con PLS_INTEGER .

CONTINUAR Declaración

El CONTINUE saltos declaración de la iteración de bucle de corriente y empieza el siguiente. Se puede utilizar por sí mismo, o como parte de un CONTINUE WHEN la declaración, como se muestra a continuación. 
JUEGO DE serveroutput
 DECLARE
   NÚMERO l_number: = 0;
 INICIO
   For i in 1 ..  100 LOOP
     Continuar cuando MOD (i, 2) = 0;

     - Hacer algo aquí!
     l_number: = l_number + 1;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("continuar cuando: '| | l_number);

   l_number: = 0;

   For i in 1 ..  100 LOOP
     SI MOD (i, 2) = 0 THEN
       CONTINUE;
     END IF;

     - Hacer algo aquí!
     l_number: = l_number + 1;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("SI .. CONTINUAR: '| | l_number);
 END;
 /
 Continuar cuando: 50
 SI ..  CONTINUAR: 50

 PL / SQL terminado con éxito.

 SQL> 
Este tipo de proceso siempre ha sido posible utilizando IF declaraciones ya sea por su propia cuenta o con las excepciones o GOTO declaraciones, pero la CONTINUE declaración es más claro y trae PL / SQL en línea con langauges otros. Los siguientes ejemplos muestran el tipo de código necesario para realizar la misma tarea antes de la CONTINUE sentencia se añadió a PL / SQL. 
JUEGO DE serveroutput
 DECLARE
   ex_continue excepción;
   NÚMERO l_number: = 0;
 INICIO
   For i in 1 ..  100 LOOP
     INICIO
       SI MOD (i, 2)! = 0 THEN
         RAISE ex_continue;
       END IF;

       - Hacer algo aquí!
       l_number: = l_number + 1;
     EXCEPCIÓN
       CUANDO ENTONCES ex_continue
         NULL;
     END;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("Excepción: '| | l_number);

   l_number: = 0;

   For i in 1 ..  100 LOOP
     SI MOD (i, 2)! = 0 THEN

       - Hacer algo aquí!
       l_number: = l_number + 1;

     END IF;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("SI: '| | l_number);

   l_number: = 0;

   For i in 1 ..  100 LOOP
     SI MOD (i, 2) = 0 THEN
       GOTO label_continue;
     END IF;

     - Hacer algo aquí!
     l_number: = l_number + 1;

     <<Label_continue>>
     NULL;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("GOTO: '| | l_number);
 END;
 /
 EXCEPCIÓN: 50
 SI: 50
 GOTO: 50

 PL / SQL terminado con éxito.

 SQL> 

Secuencias en PL / SQL Expresiones

El NEXTVAL y CURRVAL pseudocolumnas secuencia de ahora se puede acceder en expresiones PL / SQL, así como consultas. Esto hace que el código de aspecto sencillo, y la documentación sugiere que mejora el rendimiento. El siguiente ejemplo se compara la velocidad de los métodos nuevos y originales de acceder a estos valores de secuencia. 
CREAR inicio de la secuencia test1_seq CON 1.000.000;

 JUEGO DE serveroutput
 DECLARE
   l_start número;
   NÚMERO l_loops: = 100000;
   l_value número;
 INICIO

   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     SELECCIONAR test1_seq.NEXTVAL
     EN l_value
     De la doble;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("NEXTVAL SELECT = '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');

   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     l_value: = test1_seq.NEXTVAL;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("expresión NEXTVAL = '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');

   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     SELECCIONAR test1_seq.CURRVAL
     EN l_value
     De la doble;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("CURRVAL SELECT = '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');

   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     l_value: = test1_seq.CURRVAL;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("Expresión CURRVAL = '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');

 END;
 /
 NEXTVAL SELECT = 2196 hsecs
 Expresión NEXTVAL = 2203 hsecs
 CURRVAL SELECT = 1007 hsecs
 Expresión CURRVAL = 1003 hsecs

 PL / SQL terminado con éxito.

 SQL> 
Se puede ver que en cuanto al tiempo transcurrido se refiere, hay poca diferencia entre los dos métodos.

Mejoras en el SQL dinámico

Nativas SQL dinámico y el paquete DBMS_SQL ahora soportan sentencias de SQL dinámico de más de 32 KB. El EXECUTE IMMEDIATE declaración, ABIERTA PARA declaración y DBMS_SQL.PARSEprocedimiento aceptar todas las sentencias SQL en la forma de CLOB.

El DBMS_SQL.TO_REFCURSOR función convierte un cursor ID DBMS_SQL en un REF CURSOR. 

JUEGO DE serveroutput
 DECLARE
   l_cursor número;
   l_return número;

   l_ref_cursor SYS_REFCURSOR;
   TIPO ES t_emp_tab TABLA DE ROWTYPE% emp;
   l_emp_tab t_emp_tab;
 INICIO
   l_cursor: DBMS_SQL.open_cursor =;

   DBMS_SQL.parse (l_cursor, 'SELECT * FROM emp ", DBMS_SQL.NATIVE);

   l_return: DBMS_SQL.EXECUTE = (l_cursor);

   - Connvert de DBMS_SQL a un REF CURSOR.
   l_ref_cursor: DBMS_SQL.to_refcursor = (l_cursor);
   FETCH GRANEL l_ref_cursor reunir en l_emp_tab;

   DBMS_OUTPUT.PUT_LINE ("número de empleados: '| | l_emp_tab.count);

   L_ref_cursor cerca;
 END;
 /
 Número de empleados: 14

 PL / SQL terminado con éxito.

 SQL> 
El DBMS_SQL.TO_CURSOR_NUMBER función convierte un REF CURSOR en un cursor DBMS_SQL ID. 
JUEGO DE serveroutput
 DECLARE
   l_ref_cursor SYS_REFCURSOR;

   l_cursor número;
   NÚMERO l_count: = 0;
 INICIO
   L_ref_cursor ABIERTO "SELECT * FROM emp;

   l_cursor: DBMS_SQL.to_cursor_number = (l_ref_cursor);

   MIENTRAS DBMS_SQL.fetch_rows (l_cursor)> 0 LOOP
     l_count: = l_count + 1;
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("número de empleados: '| | l_count);

   DBMS_SQL.close_cursor (l_cursor);
 END;
 /
 Número de empleados: 14

 PL / SQL terminado con éxito.

 SQL> 
Además, el paquete DBMS_SQL ahora soporta todos los tipos de datos con el apoyo de SQL dinámico nativo.

Generalizada Invocación

Generalizada invocación permite un subtipo para invocar un método de un tipo primario (supertipo) con la siguiente sintaxis. 
(AUTO COMO supertype_name). Method_name 
El siguiente ejemplo muestra esto en acción.

En primer lugar, crear un tipo con algunos atributos y una función miembro. 

CREAR O CAMBIAR TIPO my_type como objeto (
   número de identificación,
   Descripción VARCHAR2 (50),
   Show_attributes funciones miembro RETORNO VARCHAR2)
   NO FINAL;
 /

 CREAR O CAMBIAR my_type tipo de cuerpo como

   Show_attributes funciones miembro RETORNO VARCHAR2 IS
   INICIO
     RETURN 'id =' | | Identificación | | 'descripción =' | | descripción;
   END;

 END;
 / 
A continuación, crear un subtipo de este objeto, lo que añade un nuevo atributo y método, así como anular la show_attributes función miembro. 
CREAR O CAMBIAR my_subtype tipo bajo my_type (
   short_desc VARCHAR2 (10),
   ABSOLUTA show_attributes función miembro RETORNO VARCHAR2,
   Show_parent_attributes funciones miembro RETORNO VARCHAR2);
 /

 CREAR O CAMBIAR my_subtype tipo de cuerpo como

   ABSOLUTA show_attributes miembro de devolución de funciones VARCHAR2 IS
   INICIO
     RETURN (yo como my_type) show_attributes | | 'short_desc =' | | short_desc.;
   END;

   Show_parent_attributes funciones miembro RETORNO VARCHAR2 IS
   INICIO
     RETURN (yo como my_type) show_attributes.;
   END;

 END;
 / 
Observe el método del tipo de padres que se accede utilizando la sintaxis de invocación generalizada. El código siguiente crea un subtipo, y llama a sus funciones miembro. 
JUEGO DE serveroutput
 DECLARE
   my_subtype l_subtype: = my_subtype (1, 'Descripción extensa para el 1', 'S descripción 1');
 INICIO
   DBMS_OUTPUT.PUT_LINE ("show_attributes = '| | l_subtype.show_attributes);
   DBMS_OUTPUT.PUT_LINE ("show_parent_attributes = '| | l_subtype.show_parent_attributes);
 END;
 /
 show_attributes = id = 1 Descripción descripción = largo por 1 short_desc Desc = S 1
 show_parent_attributes = id = 1 = Descripción detallada descripción de un

 PL / SQL terminado con éxito.

 SQL> 
Un tipo se puede invocar a las funciones de miembro de cualquier tipo primario de esta manera, independientemente de la profundidad de la herencia.

La notación con nombre y mixtos en las invocaciones del Subprograma PL / SQL

Antes de 11g, PL / SQL invoca desde SQL tenía que tener sus parámetros pasados ​​usando la notación posicional, lo que hace difícil determinar el significado de los parámetros. Oracle 11g permite la notación posicional, el nombre y la mezcla que se utiliza cuando se llama PL / SQL de SQL, como se muestra a continuación. 
- Construir una función de prueba con múltiples parámetros.
 CREAR O CAMBIAR test_func FUNCIÓN (p_value_1 EN INCUMPLIMIENTO número 0,
                                      p_value_2 EN número predeterminado 0)
   Devuelve el número AS
 INICIO
   RETORNO p_value_1 + p_value_2;
 END test_func;
 /

 Función creada.

 SQL> - la notación posicional.
 SQL> SELECT test_func (10, 20) de la doble;

 TEST_FUNC (10,20)
 ----------------
               30

 Una fila seleccionada.

 SQL> - notación mixta.
 SQL> SELECT test_func (10, p_value_2 => 20) de la doble;

 TEST_FUNC (10, P_VALUE_2 => 20)
 ---------------------------
                          30

 Una fila seleccionada.

 SQL> - nombre de notación.
 SQL> SELECT test_func (p_value_1 => 10, p_value_2 => 20) de la doble;

 TEST_FUNC (P_VALUE_1 => 10, P_VALUE_2 => 20)
 --------------------------------------
                                     30

 Una fila seleccionada.

 SQL> 

Subprograma automática Inlining

Cada llamada a un procedimiento o función produce una leve, pero medible, sobrecarga en el rendimiento, lo que es especialmente notable cuando el subprograma se llama dentro de un bucle. Evitar procedimientos y funciones no es una opción, ya que va contra el concepto de programación modular, por lo que los programas de voluminosos y difíciles de manejar. Inline subprograma automática puede reducir los gastos generales asociados con los subprogramas de llamada, dejando a su código fuente original en su estado modular normal. Esto se hace mediante la sustitución de las llamadas de subprograma con una copia del código en el subprograma en tiempo de compilación.

El proceso de inclusión entre líneas subprograma es controlada por el PLSQL_OPTIMIZE_LEVEL parámetro y el INLINE pragma. Cuando PLSQL_OPTIMIZE_LEVEL=2 (por defecto), el INLINE pragma determina si la siguiente declaración o una declaración debe ser entre líneas o no. Cuando PLSQL_OPTIMIZE_LEVEL=3 , el optimizador de código en línea de forma automática. En este caso el INLINEpragma se puede desactivar procesos en línea para una declaración, o aumentar la probabilidad de que el optimizador elegirá a una declaración en línea. La relación es más fácil de entender cuando vea el siguiente ejemplo.

Estas pruebas utilizan un bloque anónimo con una función definida en el bloque de declaraciones. La función se llama repetidamente en un bucle. Los ajustes para PLSQL_OPTIMIZE_LEVEL y el INLINEpragma son alterados para cambiar subprograma procesos en línea y fuera. En primer lugar, nos aseguramos de PLSQL_OPTIMIZE_LEVEL=2 y ejecutar el código sin INLINE conjunto pragma. Con estos ajustes, no podemos esperar para ver subprograma inline llevando a cabo. 

ALTER SET SESSION PLSQL_OPTIMIZE_LEVEL = 2;

 JUEGO DE serveroutput
 DECLARE
   NÚMERO l_loops: = 10000000;
   l_start número;
   l_return número;

   Add_numbers FUNCIÓN (p_1 en número,
                         p_2 en número)
     Devuelve el número AS
   INICIO
     RETORNO p_1 + p_2;
   Add_numbers END;

 INICIO
   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     - PRAGMA en línea (add_numbers, 'YES');
     l_return: = add_numbers (1, i);
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("Tiempo transcurrido: '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');
 END;
 /
 Tiempo transcurrido: 509 hsecs

 PL / SQL terminado con éxito.

 SQL> 
Esto se traduce en un lapso de tiempo de 509 hsecs.

A continuación, mantenga la configuración de la optimización de lo mismo, pero incluyen la INLINE pragma con un ajuste de "SÍ" para las llamadas a la ADD_NUMBERS función. Ahora se espera subprograma procesos en línea para tomar su lugar. 

ALTER SET SESSION PLSQL_OPTIMIZE_LEVEL = 2;

 JUEGO DE serveroutput
 DECLARE
   NÚMERO l_loops: = 10000000;
   l_start número;
   l_return número;

   Add_numbers FUNCIÓN (p_1 en número,
                         p_2 en número)
     Devuelve el número AS
   INICIO
     RETORNO p_1 + p_2;
   Add_numbers END;

 INICIO
   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     PRAGMA en línea (add_numbers, 'YES');
     l_return: = add_numbers (1, i);
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("Tiempo transcurrido: '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');
 END;
 /
 Tiempo transcurrido: 245 hsecs

 PL / SQL terminado con éxito.

 SQL> 
Esto le da un tiempo transcurrido de 245 HSEC, que es aproximadamente la mitad de la prueba anterior, lo que implica que inline subprograma está llevando a cabo.

A continuación, asegúrese de que PLSQL_OPTIMIZE_LEVEL=3 y ejecutar el código sin INLINE conjunto pragma. Ahora se espera que el optimizador elija implícitamente a la línea ADD_NUMBERS llamada.
 
ALTER SET SESSION PLSQL_OPTIMIZE_LEVEL = 3;

 JUEGO DE serveroutput
 DECLARE
   NÚMERO l_loops: = 10000000;
   l_start número;
   l_return número;

   Add_numbers FUNCIÓN (p_1 en número,
                         p_2 en número)
     Devuelve el número AS
   INICIO
     RETORNO p_1 + p_2;
   Add_numbers END;

 INICIO
   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     - PRAGMA en línea (add_numbers, 'YES');
     l_return: = add_numbers (1, i);
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("Tiempo transcurrido: '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');
 END;
 /
 Tiempo transcurrido: 245 hsecs

 PL / SQL terminado con éxito.

 SQL> 
Esto le da un tiempo transcurrido de 245 HSEC, lo que implica que inline subprograma está aún en marcha.

Por último, nos aseguramos de PLSQL_OPTIMIZE_LEVEL=3 y ejecutar el código con un INLINE pragma en "NO". Es de esperar que no haya procesos en línea de la ADD_NUMBERS llame ahora. 

ALTER SET SESSION PLSQL_OPTIMIZE_LEVEL = 3;

 JUEGO DE serveroutput
 DECLARE
   NÚMERO l_loops: = 10000000;
   l_start número;
   l_return número;

   Add_numbers FUNCIÓN (p_1 en número,
                         p_2 en número)
     Devuelve el número AS
   INICIO
     RETORNO p_1 + p_2;
   Add_numbers END;

 INICIO
   l_start: DBMS_UTILITY.get_time =;

   For i in 1 ..  l_loops LOOP
     PRAGMA en línea (add_numbers, 'NO');
     l_return: = add_numbers (1, i);
   END LOOP;

   DBMS_OUTPUT.PUT_LINE ("Tiempo transcurrido: '| | (DBMS_UTILITY.get_time - l_start) | |' hsecs ');
 END;
 /
 Tiempo transcurrido: 500 hsecs

 PL / SQL terminado con éxito.

 SQL> 
Esto le da un tiempo transcurrido de 500 hsecs, lo que implica que inline no se llevó a cabo como se esperaba.

El INLINE pragma sólo afecta a los siguientes tipos de declaraciones. 
  • Asignación
  • Llamar
  • Condicional
  • CASE
  • CONTINUE-WHEN
  • EXECUTE IMMEDIATE
  • EXIT-WHEN
  • LOOP
  • RETURN
En todos los casos, afecta a cada llamada a subprograma especificada de la declaración.

El optimizador puede optar por ignorar una INLINE pragma configuración del "SI" si cree inline no es deseable, sino un ajuste de "NO" siempre evitar procesos en línea.

El compilador inlines subprogramas temprano en el proceso de optimización, que puede prevenir más tarde, las optimizaciones más poderosa que tienen lugar. Como resultado, el rendimiento casi siempre mejora con la inclusión entre líneas, pero en algunos casos puede no ser eficaz.

PL / Ámbito de aplicación

PL / Scope es una herramienta que recoge información acerca de los identificadores definidos por el usuario en tiempo de compilación. La recopilación de datos PL / Ámbito de aplicación es controlada por elPLSCOPE_SETTINGS parámetro, que tiene un valor predeterminado de " IDENTIFIERS:NONE ". Cambiar este valor a " IDENTIFIERS:ALL "para permitir la recopilación. 
SQL> ALTER SESIÓN "IDENTIFICADORES: ALL 'PLSCOPE_SETTINGS =;

 Sesión alterado.

 SQL> 
La recolección de datos se realiza para todos los objetos compilados después de la bandera es definida, por lo que ahora debe crear un objeto de reunir algunos datos. 
CREAR O CAMBIAR test_plscope PROCEDIMIENTO (p_in EN número)
   l_var número;
 INICIO
   l_var: = p_in;
  
   l_var: = l_var + 1;
 END;
 / 
Los datos se almacenan en el espacio de tablas SYSAUX, por lo que el espacio actual utilizado para PL / Ámbito de datos se pueden visualizar con la siguiente consulta. 
SELECCIONAR space_usage_kbytes
 DESDE $ v sysaux_occupants
 DONDE occupant_name = 'PL / SCOPE;

 SPACE_USAGE_KBYTES
 ------------------
                384

 Una fila seleccionada.

 SQL> 
Los datos de PL / Ámbito de aplicación está disponible en el _IDENTIFIERS% puntos de vista. La consulta siguiente muestra los datos recopilados durante la elaboración del test_plscope procedimiento. 
COLUMNA FORMATO nombre A30
 SELECCIONAR LPAD ('', nivel * 2, '') | | nombre como nombre, tipo, uso, usage_id, línea, columna
 DE user_identifiers
 EMPIECE CON usage_context_id = 0
 ANTES DE CONECTAR POR usage_id = usage_context_id;

 NOMBRE TIPO DE USO USAGE_ID LÍNEA DE COL
 ------------------------------ ------------------ - --------- ---------- ---------- ----------
   TEST_PLSCOPE Declaración de procedimiento 1 1 11
     TEST_PLSCOPE procedimiento de definición 2 1 11
       FORMAL EN LA DECLARACIÓN P_IN 3 1 25
       L_VAR de declaración de variables 4 2 3
       L_VAR variable de asignación 5 4 3
         FORMAL EN REFERENCIA P_IN 6 4 12
       L_VAR variable de asignación 7 6 3
         L_VAR variable de referencia de 8 6 12

 8 filas seleccionadas.

 SQL> 
Lo más probable es que la mayoría de los usuarios ver los datos de PL / Ámbito de aplicación a través de un IDE PL / SQL, como SQL Developer.

La documentación indica que algunos identificadores no inscrito, salvo que el STANDARD paquete se vuelve a compilar después de la PLSCOPE_SETTINGS parámetro se establece de la siguiente manera.Esto se traduce en más de 7.000 objetos no válidos, la mayoría de los cuales no se vuelva a compilar, incluso cuando se utiliza el guión urlrp.sql. No recomiendo este método si desea que una instancia de trabajo.

PL / SQL compilador nativo genera código nativo directamente

La compilación nativa de código PL / SQL, como es posible desde Oracle 9i. Ver:En estas versiones de la base de datos, el código PL / SQL se convierte en código C, compilar y ejecutar los procedimientos externos. Compilados de forma nativa utilizando PL / SQL es necesario un compilador de C en el servidor y la intervención del DBA. Además, con compilados de forma nativa PL / SQL en un entorno RAC puede ser problemático.

En Oracle 11g, PL / SQL compilación como nativo no requiere compilador de C, sin intervención del DBA y es totalmente compatible en un entorno RAC. Al establecer la PLSQL_CODE_TYPE a un valor deNATIVE , más que el valor predeterminado de INTERPRETED , el código es compilado en código máquina y se almacena en el tablespace SYSTEM. Cuando el código se llama, se carga en la memoria compartida, por lo que es accesible para todas las sesiones de esa instancia. El %_PLSQL_OBJECT_SETTINGS vistas incluyen la corriente PLSQL_CODE_TYPE ajuste para cada objeto de PL / SQL.

Recuerde, la compilación nativa mejorará la velocidad de código de procedimiento, pero no tiene efecto sobre el rendimiento de SQL. Cuando el código lleva a cabo muchas operaciones matemáticas, como elSIMPLE_INTEGER ejemplo, la compilación nativa puede producir considerables mejoras de rendimiento. Si el código es predominantemente realizar SQL, poca mejoría se notará.

Al igual que con versiones anteriores de base de datos, es posible compilar de forma nativa todo el código PL / SQL en la base de datos, siempre y cuando siga el procedimiento de apoyo .

Nueva PL / SQL Advertencia del compilador

Un nuevo PL / SQL advertencia del compilador ha sido añadido a identificar WHEN OTHERS manejadores de excepciones que no hacen re-raise errores usando RAISE o RAISE_APPLICATION_ERROR .Manipuladores de tal excepción a menudo puede ocultar los fracasos de código que generan difícil de identificar los errores. El siguiente ejemplo muestra la advertencia del compilador espera que cuando elPLSQL_WARNINGS bandera está activa. 
SQL> ALTER SESIÓN plsql_warnings = SET "permite: todos;

 Sesión alterado.

 SQL> CREATE OR REPLACE others_test PROCEDIMIENTO AS
   2 EMPEZAR
   3 RAISE_APPLICATION_ERROR (-20000, 'Fuerza y ​​de excepción');
   4 EXCEPCIÓN
   5 CUANDO OTROS ENTONCES
   6 NULL;
   7 END;
   8 /

 SP2-0804: Procedimiento creado con advertencias de compilación

 SQL> SHOW ERRORES
 Los errores de OTHERS_TEST PROCEDIMIENTO:

 Line / Error COL
 -------- ------------------------------------------ -----------------------
 5.8 PLW-06009: Procedimiento "OTHERS_TEST" manejador de los demás no terminan en
          Suba o RAISE_APPLICATION_ERROR

 SQL> 
Esto es sólo un mensaje de advertencia, por lo que sólo identifica el código posible problema, no la impide.

PLS-00436 de restricción en los estados ParaTodos eliminado

La restricción de PLS-00436 se ha eliminado, lo que significa que ahora puede hacer referencia a los elementos individuales de una colección en el SET y WHERE las cláusulas de una instrucción DML en una ParaTodos construir. Para verlo en acción, crear y rellena una tabla de prueba con el siguiente código. 
CREATE TABLE forall_test (
   número de identificación,
   Descripción VARCHAR2 (50)
 );

 INSERT INTO forall_test VALUES (1, 'uno');
 INSERT INTO forall_test VALUES (2, 'dos');
 INSERT INTO forall_test VALUES (3, 'tres');
 INSERT INTO forall_test VALUES (4, 'cuatro');
 INSERT INTO forall_test VALUES (5, 'cinco');
 COMMIT; 
El bloque de PL / SQL a continuación rellena una colección con los datos existentes, que modifica los datos de la colección, a continuación, actualiza la tabla con los datos modificados. La consulta final muestra los datos modificados en la tabla. 
DECLARE
   TIPO ES t_forall_test_tab TABLA DE ROWTYPE forall_test%;
   l_tab t_forall_test_tab;
 INICIO
   - Recuperar los datos existentes en una colección.
   SELECT *
   A GRANEL EN RECOGER l_tab
   DE forall_test;

   - Modificar los datos de la colección.
   For i in l_tab.first ..  l_tab.last LOOP
     l_tab (i) Descripción: = 'Descripción para' | | i;.
   END LOOP;

   - Actualización de la tabla utilizando la colección.
   ParaTodos i EN l_tab.first ..  l_tab.last
     ACTUALIZACIÓN forall_test
     Descripción SET = l_tab (i). Descripción
     WHERE id = l_tab (i) Identificación.;

   COMMIT;
 END;
 /

 SELECT * FROM forall_test;

         ID DESCRIPCIÓN
 ---------- ---------------------------
          1 Descripción de una
          2 Descripción de dos
          3 Descripción de tres
          4 Descripción de 4
          5 Descripción de 5

 5 filas seleccionadas.

 SQL> 
Notificación tanto en el SET y WHERE cláusulas contienen referencias a columnas individuales de la colección. Esto hace que el uso a granel-se une a DML aún más fácil ya que no es necesario para mantener las colecciones múltiples si es necesario hacer referencia a las columnas de la WHERE cláusula. También puede mejorar el rendimiento de las actualizaciones, como las versiones anteriores requiere la actualización de toda la fila con el ROW palabra clave, que incluyen cambios potencialmente innecesario de la clave principal y las columnas de clave