Programación en el Servidor: PL/SQL, Java y JavaScript

SQL explica el lenguaje de lenguaje de consulta estructurado (SQL) y cómo la base de datos procesa las sentencias SQL. En este capítulo se explica cómo los programas SQL o de lenguaje de procedimiento (PL/SQL) o Java almacenados en la base de datos pueden utilizar SQL.

Introducción a la Programación del Servidor

En un lenguaje no procedimental como SQL, se especifica el conjunto de datos que se van a operar, pero no las operaciones que se van a realizar o la forma en que se van a llevar a cabo.

En un programa de lenguaje de procedimiento, la mayoría de las ejecuciones de sentencias dependen de sentencias anteriores o posteriores y de estructuras de control, como bucles o bifurcaciones condicionales, que no están disponibles en SQL. Para ver una ilustración de la diferencia entre lenguajes de procedimiento y no de procedimiento, suponga que la siguiente sentencia SQL consulta la tabla employees:

SELECT employee_id, department_id, last_name, salary FROM employees;

La sentencia anterior solicita datos, pero no aplica lógica a los datos. Sin embargo, suponga que desea que una aplicación determine si cada empleado del juego de datos merece un aumento en función del salario y el rendimiento del departamento. Una condición necesaria para un aumento de sueldo es que el empleado no haya recibido más de tres aumentos en los últimos cinco años. Si se solicita un aumento, la aplicación debe ajustar el salario y enviar un correo electrónico al mánager; de lo contrario, la aplicación debe actualizar un informe.

El problema es cómo las aplicaciones de base de datos de procedimiento que requieren lógica condicional y control de flujo de programa pueden utilizar SQL. Los enfoques básicos de desarrollo son los siguientes:

En este capítulo se explica el segundo enfoque. La principal ventaja de la programación del lado del servidor es que la funcionalidad incorporada en la base de datos se puede desplegar en cualquier lugar. La base de datos y no la aplicación determinan la mejor manera de realizar tareas en un sistema operativo determinado. Además, los subprogramas aumentan la escalabilidad al centralizar el procesamiento de aplicaciones en el servidor, lo que permite a los clientes reutilizar el código. Debido a que las llamadas de subprograma son rápidas y eficientes, una sola llamada puede iniciar un subprograma almacenado con un uso intensivo de recursos informáticos, lo que reduce el tráfico de red.

Puede utilizar los siguientes idiomas para almacenar la lógica de datos en Oracle AI Database:

Consulte además:

Visión General de PL/SQL

PL/SQL proporciona un lenguaje de procedimiento almacenado del lado del servidor que es fácil de usar, sin problemas con SQL, robusto, portátil y seguro. Puede acceder y manipular datos de base de datos mediante objetos de procedimiento denominados unidades PL/SQL.

Las unidades PL/SQL generalmente se clasifican de la siguiente manera:

El compilador e intérprete PL/SQL están embebidos en Oracle SQL Developer, lo que proporciona a los desarrolladores un modelo de desarrollo consistente y aprovechado tanto en el cliente como en el servidor. Además, los procedimientos almacenados PL/SQL se pueden llamar desde varios clientes de base de datos, como Pro*C, JDBC, ODBC u OCI, y desde Oracle Reports y Oracle Forms.

Consulte además:

Subprogramas PL/SQL

Un subprograma PL/SQL es un bloque PL/SQL con nombre que permite al emisor de llamada proporcionar parámetros que solo pueden ser valores de entrada, de salida o de entrada y de salida.

Un subprograma resuelve un problema específico o realiza tareas relacionadas y sirve como bloque de construcción para aplicaciones de base de datos modulares y mantenibles. Un subprograma es un procedimiento PL/SQL o una función PL/SQL. Los procedimientos y las funciones son idénticos salvo que la función siempre devuelven un único valor al emisor de la llamada, mientras que la función no lo hace. El término procedimiento PL/SQL de este capítulo hace referencia a un procedimiento o a una función.

Consulte además:

Ventajas de los Subprogramas PL/SQL

La programación del lado del servidor tiene muchas ventajas sobre la programación del lado del cliente.

Las ventajas incluyen:

Consulte además:

Creación de Subprogramas PL/SQL

Un subprograma almacenado autónomo es un subprograma creado en el nivel de esquema con la sentencia CREATE PROCEDURE o CREATE FUNCTION. Los subprogramas definidos en un paquete se denominan subprogramas de paquetes y se consideran parte del paquete.

La base de datos almacena subprogramas en el diccionario de datos como objetos de esquema. Un subprograma tiene una especificación, que incluye descripciones de cualquier parámetro y un cuerpo.

Ejemplo 11-1 Procedimiento PL/SQL

En este ejemplo se muestra parte de una sentencia de creación para el procedimiento PL/SQL autónomo hire_employees. El procedimiento inserta una fila en la tabla employees.

CREATE PROCEDURE hire_employees
  (p_last_name VARCHAR2, p_job_id VARCHAR2, p_manager_id NUMBER,
   p_hire_date DATE, p_salary NUMBER, p_commission_pct NUMBER,
   p_department_id NUMBER)
IS
BEGIN
.
.
.
  INSERT INTO employees (employee_id, last_name, job_id, manager_id, hire_date,
    salary, commission_pct, department_id)
  VALUES (emp_sequence.NEXTVAL, p_last_name, p_job_id, p_manager_id,
          p_hire_date, p_salary, p_commission_pct, p_department_id);
.
.
.
END;

Consulte además:

Ejecución de Subprogramas PL/SQL

Los usuarios pueden ejecutar un subprograma de forma interactiva de varias formas.

Las opciones son las siguientes:

En el siguiente gráfico se muestran diferentes aplicaciones de base de datos que llaman a hire_employees.

Figura 1: Ejecución Múltiple de un Procedimiento Almacenado

Descripción de la ilustración cncpt073.gif

Como alternativa, un usuario con privilegios puede utilizar Oracle Enterprise Manager o SQL*Plus para ejecutar el procedimiento hire_employees mediante una sentencia como la siguiente:

EXECUTE hire_employees ('TSMITH', 'CLERK', 1037, SYSDATE, 500, NULL, 20);

La sentencia anterior inserta un nuevo registro para TSMITH en la tabla employees.

Un procedimiento almacenado depende de los objetos a los que se hace referencia en su cuerpo. La base de datos realiza un seguimiento y gestiona automáticamente estas dependencias. Por ejemplo, si modifica la definición de la tabla employees a la que hace referencia el procedimiento hire_employees de forma que afecte a este procedimiento, se debe recompilar el procedimiento para validar que aún funciona según lo diseñado. Normalmente, la base de datos administra automáticamente dicha gestión de dependencias.

Consulte además:

Paquetes PL/SQL

Un paquete PL/SQL es un grupo de subprogramas relacionados, junto con los cursores y variables que utilizan, almacenados juntos en la base de datos para su uso continuo como una unidad. Las aplicaciones o los usuarios pueden llamar explícitamente a los subprogramas empaquetados.

Oracle AI Database incluye muchos paquetes proporcionados que amplían la funcionalidad de la base de datos y proporcionan acceso PL/SQL a las funciones SQL. Por ejemplo, el paquete UTL_HTTP permite llamadas HTTP de PL/SQL y SQL para acceder a datos en Internet o llamar a cartuchos de Oracle Web Server. Puede utilizar los paquetes proporcionados al crear aplicaciones o como fuente de ideas al crear sus propios procedimientos almacenados.

Ventajas de los Paquetes PL/SQL

Los paquetes PL/SQL proporcionan una serie de ventajas al desarrollador de aplicaciones.

Las ventajas incluyen:

Creación de Paquetes PL/SQL

Un paquete se crea en dos partes: la especificación y el cuerpo. La especificación del paquete declara todas las construcciones públicas del paquete, mientras que el cuerpo del paquete define todas las construcciones (públicas y privadas) del paquete.

En el siguiente ejemplo se muestra parte de una sentencia que crea la especificación de paquete para employees_management, que encapsula varios subprogramas utilizados para gestionar una base de datos de empleados. Cada parte del paquete se crea con una sentencia diferente.

CREATE PACKAGE employees_management AS
  FUNCTION hire_employees (last_name VARCHAR2, job_id VARCHAR2, manager_id NUMBER,
    salary NUMBER, commission_pct NUMBER, department_id NUMBER) RETURN NUMBER;
  PROCEDURE fire_employees(employee_id NUMBER);
  PROCEDURE salary_raise(employee_id NUMBER, salary_incr NUMBER);
.
.
.
  no_sal EXCEPTION;
END employees_management;

La especificación declara la función hire_employees, los procedimientos fire_employees y salary_raise, y la excepción no_sal. Todos estos objetos de programa público están disponibles para los usuarios que tienen acceso al paquete.

La sentencia CREATE PACKAGE BODY define los objetos declarados en la especificación. El cuerpo del paquete se debe crear en el mismo esquema que el paquete. Después de crear el paquete, puede desarrollar aplicaciones que llamen a cualquiera de estos procedimientos o funciones públicos o que emitan cualquiera de las excepciones públicas del paquete.

Consulte también: Referencia de lenguaje PL/SQL de Oracle AI Database para obtener más información sobre la sentencia CREATE PACKAGE

Ejecución de Subprogramas de Paquete PL/SQL

Los disparadores de base de datos, los subprogramas almacenados, los programas de aplicación 3GL y las herramientas de Oracle pueden hacer referencia al contenido de los paquetes.

En el siguiente gráfico se muestran las aplicaciones de base de datos que llaman a procedimientos y funciones en el paquete employees_management.

Figura 2: Llamada a Subprogramas en un Paquete PL/SQL

Descripción de la ilustración cncpt075.gif

Las aplicaciones de base de datos llaman explícitamente a los procedimientos empaquetados según sea necesario. Después de otorgar los privilegios para el paquete employees_management, un usuario puede ejecutar explícitamente cualquiera de los procedimientos que contiene. Por ejemplo, SQL*Plus puede emitir la siguiente sentencia para ejecutar el procedimiento del paquete hire_employees:

EXECUTE employees_management.hire_employees ('TSMITH', 'CLERK', 1037, SYSDATE, 500, NULL, 20);

Consulte además:

Bloques Anónimos PL/SQL

Un bloque anónimo PL/SQL es una unidad PL/SQL sin nombre y no persistente.

Los usos típicos de los bloques anónimos incluyen:

Los bloques anónimos no tienen las ventajas de reutilización de código de los subprogramas almacenados. La Tabla 11-1 resume las diferencias entre los dos tipos de unidades PL/SQL.

Tabla 1 Diferencias entre bloques anónimos y subprogramas

Es la unidad PL/SQL... Bloques Anónimos Subprogramas
¿Se ha especificado con un nombre? No Sí
¿Se compila con cada reutilización? No No
¿Se almacenan en la Base de Datos? No Sí
¿Invocable por otras aplicaciones? No Sí
¿Se pueden devolver valores de variables ligadas? Sí Sí
¿Capaz de devolver valores de función? No Sí
¿Capaz de aceptar parámetros? No Sí

Un bloque anónimo consta de una parte declarativa opcional, una parte ejecutable y uno o más manejadores de excepciones opcionales. El siguiente bloque anónimo de ejemplo selecciona los apellidos de un empleado en una variable e imprime el nombre:

DECLARE
  v_lname VARCHAR2(25);
BEGIN
  SELECT last_name
    INTO v_lname
  FROM employees
  WHERE employee_id = 101;
  DBMS_OUTPUT.PUT_LINE('Employee last name is '||v_lname);
END;

Oracle AI Database compila el bloque PL/SQL y lo coloca en el pool compartido de SGA, pero no almacena el código fuente ni la versión compilada en la base de datos para su reutilización más allá de la instancia actual. A diferencia de los disparadores, un bloque anónimo se compila cada vez que se carga en la memoria. El SQL compartido permite reutilizar y compartir bloques PL/SQL anónimos en el pool compartido hasta que se vacíen del pool compartido.

Consulte también: Guía de desarrollo de Oracle AI Database para obtener más información sobre bloques PL/SQL anónimos

Construcciones de Lenguaje PL/SQL

Los bloques PL/SQL pueden incluir varias construcciones de lenguaje PL/SQL diferentes.

Estas construcciones incluyen las siguientes:

PL/SQL puede ejecutar sentencias SQL dinámico cuyo texto completo no se conoce hasta el tiempo de ejecución. Las sentencias SQL dinámicas se almacenan en cadenas de caracteres que el programa introduce o crea en tiempo de ejecución. Esta técnica permite crear procedimientos de uso general. Por ejemplo, puede crear un procedimiento que funcione en una tabla cuyo nombre no se conoce hasta el tiempo de ejecución.

Consulte además:

Recopilaciones y Registros PL/SQL

Muchas técnicas de programación utilizan tipos de recopilación, como matrices, bolsas, listas, tablas anidadas, juegos y árboles.

Para soportar técnicas de recopilación en aplicaciones de base de datos, PL/SQL proporciona los tipos de dato TABLE y VARRAY. Estos tipos permiten declarar matrices asociativas, tablas anidadas y matrices de tamaño variable.

Recopilaciones

Una recopilación PL/SQL es un grupo ordenado de elementos, todos del mismo tipo.

Cada elemento tiene un subíndice único que determina su posición en la recopilación. Para crear una recopilación, primero debe definir un tipo de recopilación y, a continuación, declarar una variable de ese tipo.

Las colecciones funcionan como las matrices que se encuentran en la mayoría de los lenguajes de programación de tercera generación. Además, las recopilaciones se pueden transferir como parámetros. Por lo tanto, puede utilizarlas para mover columnas de datos a y fuera de las tablas de base de datos o entre aplicaciones de cliente y subprogramas almacenados.

Registros

Un registro PL/SQL es una variable compuesta que puede almacenar valores de datos de diferentes tipos, similares a un tipo de estructura en C, C++ o Java. Los registros son útiles para contener datos de las filas de tablas o determinadas columnas de filas de tablas.

Supongamos que tiene datos sobre un empleado, como el nombre, el salario y la fecha de contratación. Estos elementos son de tipo diferente, pero lógicamente relacionados. Un registro que contiene un campo para cada artículo le permite tratar los datos como una unidad lógica.

Puede utilizar el atributo %ROWTYPE para declarar un registro que represente una fila de tabla o una fila recuperada de un cursor. Con los registros definidos por el usuario, puede declarar sus propios campos.

Consulte también: Referencia de lenguaje PL/SQL de Oracle AI Database para aprender a utilizar registros PL/SQL

Ejecución de PL/SQL

PL/SQL soporta tanto la ejecución interpretada como la ejecución nativa.

En la ejecución interpretada, el código fuente PL/SQL se compila en una representación de código de byte. Una computadora virtual portátil implementada como parte de Oracle AI Database ejecuta este código de byte.

La ejecución nativa ofrece el mejor rendimiento en unidades con un uso intensivo de computación. En este caso, el código fuente de las unidades PL/SQL se compila directamente en el código de objeto para la plataforma especificada. Este código de objeto está enlazado a Oracle AI Database.

El motor PL/SQL define, compila y ejecuta unidades PL/SQL. Este motor es un componente especial de muchos productos de Oracle, incluido Oracle AI Database. Aunque muchos productos de Oracle tienen componentes PL/SQL, este tema trata específicamente las unidades PL/SQL que se pueden almacenar en Oracle AI Database y procesar mediante el motor PL/SQL de Oracle AI Database. En la documentación de cada herramienta de Oracle se describen sus capacidades PL/SQL.

En el siguiente gráfico se ilustra el motor PL/SQL incluido en Oracle AI Database.

Figura 3: Motor PL/SQL y Oracle AI Database

Descripción de la ilustración cncpt070.gif

La unidad PL/SQL se almacena en una base de datos. Cuando una aplicación llama a un procedimiento almacenado, la base de datos carga la unidad PL/SQL compilada en el pool compartido en el área global del sistema (SGA). Los ejecutores de sentencias SQL y PL/SQL trabajan juntos para procesar las sentencias del procedimiento.

Puede llamar a un procedimiento almacenado desde otro bloque PL/SQL, que puede ser un bloque anónimo u otro procedimiento almacenado. Por ejemplo, puede llamar a un procedimiento almacenado desde Oracle Forms.

Un procedimiento PL/SQL que se ejecuta en Oracle AI Database puede llamar a una función o procedimiento externo escrito en lenguaje de programación C y almacenado en una biblioteca compartida. La rutina C se ejecuta en un espacio de direcciones independiente del de Oracle AI Database.

Consulte además:

Visión general de Java en Oracle AI Database

Java se ha convertido en el lenguaje de programación orientado a objetos elegido.

Java incluye las siguientes funciones:

La base de datos proporciona programas Java con un motor de procesamiento de datos dinámico que soporta consultas complejas y varias vistas de datos. Las solicitudes de los clientes se ensamblan como consultas de datos para su procesamiento inmediato. Los resultados de la consulta se generan dinámicamente.

La combinación de Java y Oracle AI Database le ayuda a crear aplicaciones basadas en componentes y centradas en la red que se pueden actualizar fácilmente a medida que cambian las necesidades empresariales. Además, puede mover aplicaciones y almacenes de datos fuera del escritorio y a redes inteligentes y servidores centrados en la red. Más importante aún, puede acceder a estas aplicaciones y almacenes de datos desde cualquier dispositivo cliente.

En la siguiente figura se muestra una configuración de cliente/servidor tradicional de dos niveles en la que los clientes llaman a procedimientos almacenados Java de la misma forma que llaman a subprogramas PL/SQL.

Figura 4: Configuración de cliente/servidor de dos niveles

Descripción de la ilustración cncpt236.gif

Visión General de Java Virtual Machine (JVM)

Un JVM es un procesador virtual que ejecuta código Java compilado.

El código fuente de Java compila con instrucciones de máquina de bajo nivel, conocidas como códigos de bytes, que son independientes de la plataforma. Los códigos de byte Java se interpretan a través de JVM en acciones dependientes de la plataforma.

Visión General de Oracle JVM

Oracle JVM es un entorno estándar compatible con Java que ejecuta cualquier aplicación Java pura. Es compatible con JLS y las especificaciones de JVM.

Oracle JVM soporta las API y el formato binario Java estándar. Además, Oracle AI Database se adhiere a la semántica estándar del lenguaje Java, incluida la carga dinámica de clases en tiempo de ejecución.

En la siguiente figura se muestra cómo residen las aplicaciones Java de Oracle sobre las bibliotecas de clases principales de Java, que residen sobre la JVM de Oracle. Puesto que el sistema de soporte de Oracle Java se encuentra en la base de datos, JVM interactúa con las bibliotecas de la base de datos, en lugar de interactuar directamente con el sistema operativo.

Figura 5: Estructura de componentes Java

Descripción de la ilustración cncpt206.gif

A diferencia de otros entornos Java, Oracle JVM está integrado en Oracle AI Database. Existen algunas diferencias importantes entre la JVM de Oracle y las JVM de cliente típicas. Por ejemplo, en un entorno Java estándar, ejecute una aplicación Java mediante el intérprete emitiendo el siguiente comando en la línea de comandos, donde classname es el nombre de la clase que JVM interpreta en primer lugar:

java classname

El comando anterior hace que la aplicación se ejecute dentro de un proceso en el sistema operativo. Sin embargo, si no utiliza la interfaz de línea de comandos, debe cargar la aplicación en la base de datos, publicar la interfaz y, a continuación, ejecutar la aplicación en un diccionario de datos de base de datos.

Consulte también: Consulte Oracle AI Database Java Developer's Guide para obtener una descripción de otras diferencias entre la JVM de Oracle y las JVM de cliente habituales

Componentes Principales de Oracle JVM

Oracle JVM se ejecuta en el mismo espacio de proceso y espacio de dirección que el núcleo de base de datos al compartir sus pilas de memoria y acceder directamente a sus datos relacionales. Este diseño optimiza el uso de la memoria y aumenta el rendimiento.

Oracle JVM proporciona un entorno de tiempo de ejecución para objetos Java. Soporta completamente estructuras de datos Java, distribución de métodos, manejo de excepciones y threads de nivel de lenguaje. También soporta todas las bibliotecas de clases Java principales, incluidas java.lang, java.io, java.net, java.math y java.util.

En la siguiente ilustración se muestran los componentes principales de Oracle JVM.

Figura 6: Componentes Principales de Oracle JVM

Descripción de la ilustración cncpt254.gif

Oracle JVM embebebe el espacio de nombres Java estándar en los esquemas de base de datos. Esta función permite a los programas Java acceder a los objetos Java almacenados en Oracle AI Database y los servidores de aplicaciones de toda la empresa.

Además, Oracle JVM está estrechamente integrado con la arquitectura de memoria compartida escalable de la base de datos. Los programas Java utilizan la duración de las llamadas, las sesiones y los objetos de forma eficaz sin la intervención del usuario. En consecuencia, los objetos de negocio Java de capa media y JVM de Oracle se pueden escalar, incluso cuando tienen un estado de sesión larga.

Consulte también: Guía del desarrollador de Oracle AI Database Java para obtener una descripción de los componentes principales de Oracle JVM

Entorno de programación Java

Oracle proporciona a los desarrolladores de aplicaciones empresariales una solución Java integral para crear, desplegar y gestionar aplicaciones Java.

La solución consta de interfaces programáticas del lado del cliente y del servidor, herramientas para soportar el desarrollo de Java y una Java Virtual Machine integrada con Oracle AI Database. Todos estos productos son compatibles con los estándares Java.

El entorno de programación Java consta de las siguientes funciones adicionales:

Procedimientos Almacenados Java

Un procedimiento almacenado en Java es un método Java publicado en SQL y almacenado en la base de datos.

Al igual que sucede con un subprograma PL/SQL, se puede llamar directamente a un procedimiento Java con productos como SQL*Plus o indirectamente con un disparador. Puede acceder a ella desde cualquier cliente-OCI, precompilador o JDBC de Oracle Net.

Para publicar métodos Java, se escriben especificaciones de llamada, que asignan nombres de métodos Java, tipos de parámetros y tipos de retorno a sus equivalentes SQL. Cuando las llaman las aplicaciones cliente, un procedimiento almacenado Java puede aceptar argumentos, hacer referencia a clases Java y devolver valores de resultados Java.

Aplicaciones que llaman al método Java haciendo referencia al nombre de la especificación de llamada. El sistema de tiempo de ejecución busca la definición de especificación de llamada en el diccionario de datos de Oracle y ejecuta el método Java correspondiente.

Además, puede utilizar Java para desarrollar programas potentes independientemente de PL/SQL. Oracle AI Database proporciona una implementación totalmente compatible del lenguaje de programación Java y JVM.

Consulte también: Oracle AI Database Java Developer's Guide explica cómo escribir procedimientos almacenados en Java, cómo acceder a ellos desde PL/SQL y cómo acceder a la funcionalidad PL/SQL desde Java

Integración de Java y PL/SQL

Puede llamar a programas PL/SQL existentes desde programas Java y Java desde PL/SQL. Esta solución protege y aprovecha el código PL/SQL y Java.

Oracle AI Database ofrece JDBC para acceder a datos SQL desde Java tanto en el cliente como en el servidor.

Controladores JDBC

JDBC es un protocolo de acceso a base de datos que permite conectarse a una base de datos y ejecutar sentencias SQL y consultas a la base de datos.

Las bibliotecas de clases Java principales proporcionan solo una API de JDBC, java.sql. Sin embargo, JDBC está diseñado para permitir a los proveedores suministrar controladores que ofrecen la especialización necesaria para una base de datos concreta. Oracle proporciona los distintos controladores JDBC que se muestran en la siguiente tabla.

Tabla 2 Controladores JDBC

Controlador Descripción
Controlador JDBC Thin Puede utilizar el controlador JDBC Thin para escribir aplicaciones y applets Java puros que accedan a los datos de Oracle SQL. El controlador JDBC Thin es especialmente adecuado para aplicaciones y applets basados en Web, ya que puede descargarlo dinámicamente desde una página Web, similar a cualquier otro applet de Java.
Controlador JDBC OCI El controlador JDBC OCI accede al código nativo específico de Oracle, es decir, al código que no es Java y a las bibliotecas del cliente o de la capa media, lo que proporciona un aumento del rendimiento en comparación con el controlador JDBC Thin, a costa de un tamaño significativamente mayor y de una instalación del cliente.
Controlador interno del servidor JDBC Oracle AI Database utiliza el controlador interno del servidor cuando el código Java se ejecuta en el servidor. Permite a las aplicaciones Java que se ejecutan en Oracle JVM en el servidor acceder a datos definidos localmente, es decir, datos en el mismo sistema y en el mismo proceso, con JDBC. Proporciona un aumento del rendimiento, debido a su capacidad para utilizar las bibliotecas subyacentes de Oracle RDBMS directamente, sin la sobrecarga de una conexión de red intermedia entre el código Java y los datos SQL. Al admitir la misma interfaz Java-SQL en el servidor, Oracle AI Database no requiere que vuelva a procesar el código al desplegarlo.

Consulte además:

Visión general de JavaScript en Oracle AI Database

JavaScript es uno de los lenguajes de programación más populares en la actualidad. Oracle AI Database desplegado en Linux x86-64 o Linux aarch64 agrega JavaScript a la lista de lenguajes soportados para el desarrollo del lado del servidor.

Puede almacenar módulos de JavaScript en la base de datos, procesando datos donde residen ofreciendo mejoras potencialmente significativas sobre los enfoques de desarrollo del lado del cliente. JavaScript es ejecutado por Multilingual Engine (MLE).

Los desarrolladores pueden elegir entre ejecutar código JavaScript independiente y almacenar código JavaScript de forma nativa en la base de datos como módulos.

Almacenamiento de la Lógica de Negocio como Módulos en la Base de Datos

Al igual que con el desarrollo del lado del cliente relacionado con JavaScript, el código se puede almacenar juntos en forma de módulo.

Los desarrolladores con un fondo PL/SQL pueden pensar en un módulo JavaScript como el equivalente de un cuerpo de paquete PL/SQL, pero escrito en JavaScript. Las funciones declaradas en un módulo se pueden marcar para exportarse o mantenerse privadas.

JavaScript en Oracle AI Database cumple con el estándar ECMAScript 2023 y ofrece a los desarrolladores una amplia gama de posibilidades para almacenar la lógica de negocio dentro de la base de datos.

Nota:

Consulte también:

A continuación, se muestra un ejemplo de creación de un módulo JavaScript con MLE:

create mle module if not exists example_module
language javascript as

export function string2obj(inputString) {
   if ( inputString === undefined ) {
      throw `must provide a string in the form of key1=value1;...;keyN=valueN`;
   }

   let myObject = {};
   if ( inputString.length === 0 ) {
      return myObject;
   }

   const kvPairs = inputString.split(";");
   kvPairs.forEach( pair => {
      const tuple = pair.split("=");
      if ( tuple.length === 1 ) {
          tuple[1] = false;
      } else if ( tuple.length != 2 ) {
          throw "parse error: you need to use exactly one '=' between key and value and not use '=' in either key or value";
      }
      myObject[tuple[0]] = tuple[1];
  });

  return myObject;
}
/

El módulo JavaScript, también conocido como módulo MLE, ahora se almacena en el esquema del usuario. Su única función, string2obj(), se puede exponer a SQL y PL/SQL mediante la creación de una especificación de llamada. Las especificaciones de llamada son unidades de programa PL/SQL que permiten llamar al código JavaScript dondequiera que se pueda llamar a SQL y PL/SQL. La especificación de llamada para string2obj() se puede escribir de la siguiente manera:

create function if not exists p_string_to_JSON(p_str varchar2) return JSON
as mle module example_module
   signature 'string2obj(string)';
/

Con la función creada, se puede llamar desde SQL:

declare
   l_json   JSON;
   l_string VARCHAR2(100);
begin
   l_string := 'a=1;b=2;c=3;d';
   l_json := p_string_to_JSON(l_string);
   dbms_output.put_line(json_serialize(l_json PRETTY));
end;
/

{
  "a" : "1",
  "b" : "2",
  "c" : "3",
  "d" : false
}

PL/SQL procedure successfully completed.

Ejecución dinámica de código JavaScript

Los desarrolladores de marcos y cualquier persona que desee ejecutar código JavaScript independiente sin necesidad de almacenar código en la base de datos pueden utilizar el paquete DBMS_MLE y sus subrutinas.

Oracle Application Express y Database Actions, por ejemplo, integran DBMS_MLE, ocultando el hecho de que se llama a un paquete PL/SQL en las cubiertas.

En comparación con los módulos MLE, el uso de DBMS_MLE dificulta la escritura de aplicaciones completas. Por ejemplo, es más difícil dividir lógicamente una aplicación en entidades separadas. La función de depuración posterior a la ejecución requiere módulos que dificulten la resolución de problemas en los fragmentos de código. Los pipelines de integración continua (CI) también pueden tener problemas con la introducción de código PL/SQL y JavaScript en el mismo archivo. Del mismo modo, existe un problema potencial con el entorno de desarrollo integrado (IDE), ya que la mayoría tendrá dificultades para trabajar con PL/SQL y JavaScript en la misma ventana.

Nota:

Consulte también:

Procedimientos almacenados en línea JavaScript

Las especificaciones de llamada de MLE en línea embeben código JavaScript directamente en las DDL CREATE FUNCTION y CREATE PROCEDURE.

Si desea implantar rápidamente una funcionalidad sencilla mediante JavaScript, las especificaciones de llamada MLE en línea pueden ser una buena opción. Con esta opción, no es necesario desplegar un módulo independiente que contenga el código JavaScript. En su lugar, la función JavaScript está integrada en la definición de la especificación de llamada en sí.

La cláusula MLE LANGUAGE se utiliza para especificar que la función se implanta mediante JavaScript. La cadena que sigue al nombre de idioma se trata como el cuerpo de una función JavaScript que implementa la funcionalidad de la especificación de llamada. Cuando se ejecuta el código, los parámetros PL/SQL se convierten automáticamente al tipo JavaScript por defecto y se transfieren a la función JavaScript como parámetros con el mismo nombre. Tenga en cuenta que los nombres de parámetros sin comillas se asignan a nombres JavaScript en mayúsculas. El valor devuelto por una función JavaScript se convierte en el tipo de retorno de la especificación de llamada PL/SQL, al igual que con las especificaciones de llamada para módulos MLE.

Nota:

Consulte también:

Visión General de Disparadores

Un disparador de base de datos es una unidad de programa almacenada compilada, escrita en PL/SQL, Java o JavaScript, que Oracle Database llama automáticamente en determinadas situaciones.

Un disparador arranca cada vez que se produce una de las siguientes operaciones:

  1. Sentencias DML en una tabla o vista concreta, emitidas por cualquier usuario

    Las sentencias DML modifican los datos de los objetos de esquema. Por ejemplo, la inserción y supresión de filas son operaciones DML.

  2. Sentencias DDL emitidas por un usuario concreto o cualquier usuario

    Las sentencias DDL definen objetos de esquema. Por ejemplo, la creación de una tabla y la adición de una columna son operaciones DDL.

  3. Eventos de base de datos

    La conexión o desconexión del usuario, los errores y el inicio o cierre de la base de datos son eventos que pueden llamar a disparadores.

Los disparadores son objetos de esquema que son similares a los subprogramas pero que difieren en la forma en que se llaman. Un subprograma lo ejecuta explícitamente un usuario, una aplicación o un disparador. La base de datos llama implícitamente a los disparadores cuando se produce un evento disparador.

Consulte además:

Ventajas de los disparadores

El uso correcto de los disparadores permite crear y desplegar aplicaciones más sólidas y que utilizan la base de datos de forma más eficaz.

Puede utilizar disparadores para:

Puede utilizar disparadores para aplicar reglas de negocio de bajo nivel comunes para todas las aplicaciones cliente. Por ejemplo, varias aplicaciones pueden acceder a la tabla employees. Si un disparador de esta tabla garantiza el formato de los datos insertados, no es necesario reproducir esta lógica de negocio en todos los clientes. Puesto que la aplicación no puede eludir el disparador, la lógica de negocio del disparador se utiliza automáticamente.

Puede utilizar tanto disparadores como restricciones de integridad para definir y aplicar cualquier tipo de regla de integridad. Sin embargo, Oracle recomienda que solo utilice disparadores para aplicar reglas de negocio complejas que no se puedan definir mediante una restricción de integridad.

El uso excesivo de disparadores puede dar lugar a interdependencias complejas que pueden ser difíciles de mantener en una aplicación grande. Por ejemplo, cuando se llama a un disparador, una sentencia SQL dentro de su acción de disparador puede arrancar otros disparadores, lo que da como resultado disparadores en cascada que pueden producir efectos no deseados.

Consulte además:

automáticamente en ciertas situaciones.")

Tipos de disparadores

Los disparadores se pueden clasificar según sus medios de llamada y el tipo de acciones que realizan.

Oracle Database soporta los siguientes tipos de disparadores:

Consulte además:

automáticamente en ciertas situaciones.")

Tiempo para disparadores

Puede definir el tiempo del disparador, independientemente de si la acción del disparador se va a ejecutar antes o después de la sentencia disparadora.

Un disparador simple es un único disparador en una tabla que permite especificar acciones para exactamente uno de los siguientes puntos de temporización:

Para los disparadores de sentencia y fila, un disparador BEFORE puede mejorar la seguridad y activar las reglas de negocio antes de realizar cambios en la base de datos. El disparador AFTER es ideal para registrar acciones.

Un disparador compuesto puede arrancar en varios puntos en temporización. Los disparadores compuestos ayudan a programar un enfoque en el que las acciones que implanta para varios puntos de temporización comparten datos comunes.

Consulte también: Referencia de lenguaje PL/SQL de Oracle AI Database para obtener más información sobre los disparadores compuestos

automáticamente en ciertas situaciones.")

Creación de disparadores

La sentencia CREATE TRIGGER crea o sustituye un disparador de base de datos.

Un disparador PL/SQL tiene el siguiente formato sintáctico general:

CREATE TRIGGER trigger_name
  triggering_statement
  [trigger_restriction]
BEGIN
 triggered_action;
END;

Un disparador PL/SQL tiene los siguientes componentes básicos:

Consulte además:

automáticamente en ciertas situaciones.")

Ejemplo: sentencia CREATE TRIGGER

En este ejemplo se crea un disparador que se arranca cuando se ejecuta una sentencia INSERT, UPDATE o DELETE en una tabla de líneas de ítem.

Supongamos que crea las tablas orders y lineitems con las siguientes sentencias. La tabla orders contiene una fila para cada orden único, mientras que la tabla lineitems contiene una fila para cada elemento de un orden.

CREATE TABLE orders
( order_id NUMBER PRIMARY KEY,
  /* other attributes */
  line_items_count NUMBER DEFAULT 0 );

CREATE TABLE lineitems
( order_id REFERENCES orders,
  seq_no   NUMBER,
  /* other attributes */
  CONSTRAINT lineitems PRIMARY KEY(order_id,seq_no) );

La siguiente sentencia crea un disparador de ejemplo que actualiza automáticamente la tabla orders con el número de elementos en un orden:

CREATE OR REPLACE TRIGGER lineitems_trigger
  AFTER INSERT OR UPDATE OR DELETE ON lineitems
  FOR EACH ROW
BEGIN
  IF (INSERTING OR UPDATING)
  THEN
    UPDATE orders SET line_items_count = NVL(line_items_count,0)+1
    WHERE order_id = :new.order_id;
  END IF;
  IF (DELETING OR UPDATING)
  THEN
    UPDATE orders SET line_items_count = NVL(line_items_count,0)-1
    WHERE order_id = :old.order_id;
  END IF;
END;
/

En lineitems_trigger, la sentencia disparadora es INSERT, UPDATE o DELETE en la tabla lineitems. No existe ninguna restricción disparadora. Se llama al disparador para cada fila cambiada. El disparador tiene acceso a los valores de columna antiguos y nuevos de la fila actual afectada por la sentencia disparadora. Existen dos nombres de correlación para cada columna de la tabla que se va a modificar: el valor antiguo (:old) y el nuevo (:new). Si una sesión actualiza o inserta filas en lineitems para un pedido, después de la acción, el disparador calcula el número de artículos en este pedido y actualiza la tabla orders con el recuento.

Ejemplo: Llamada a un Disparador de Nivel de Fila

En este escenario, un cliente inicia dos pedidos y agrega y elimina líneas de ítem de los pedidos.

El escenario se basa en el disparador creado en el ejemplo: sentencia CREATE TRIGGER.

Tabla 3 Escenario de disparador de nivel de fila

Sentencia SQL Sentencia SQL Disparada Descripción
SQL> INSERT INTO orders
 (order_id) VALUES (78);

  1 row created. 
 

El cliente crea un pedido con el ID 78. En este punto, el cliente no tiene artículos en la orden.

Puesto que no se realiza ninguna acción en la tabla lineitems, no se llama al disparador.

SQL> INSERT INTO orders
 (order_id) VALUES (92);

  1 row created. 
 

El cliente crea un pedido independiente con el ID 92. En este punto, el cliente no tiene artículos en la orden.

Puesto que no se realiza ninguna acción en la tabla lineitems, no se llama al disparador.

SQL> INSERT INTO lineitems
  (order_id, seq_no)
 VALUES (78,1);

  1 row created. 
UPDATE orders
  SET line_items_count =
  NVL(NULL,0)+1
 WHERE order_id = 78;

El cliente agrega un artículo al pedido 78.

INSERT llama al disparador. La sentencia disparada aumenta el recuento de líneas de artículo de la orden 78 de 0 a 1.

SQL> INSERT INTO lineitems
  (order_id, seq_no)
  VALUES (78,2);

  1 row created. 
UPDATE orders
  SET line_items_count =
  NVL(1,0)+1
 WHERE order_id = 78; 

El cliente agrega un artículo adicional a la orden 78.

INSERT llama al disparador. La sentencia disparada aumenta el recuento de líneas de artículo de la orden 78 de 1 a 2.

SQL> SELECT * FROM orders;

  ORDER_ID LINE_ITEMS_COUNT
 --------- ----------------
 78 2
 92 0
  El cliente consulta el estado de los dos pedidos. La Orden 78 contiene dos artículos. La orden 92 no contiene artículos.
SQL> SELECT * FROM lineitems;

  ORDER_ID SEQ_NO
 ---------- ----------
 78 1
 78 2
  El cliente consulta el estado de las líneas de ítem. Cada artículo se identifica de forma exclusiva mediante el ID de pedido y el número de secuencia.
SQL> UPDATE lineitems
  SET order_id = 92;

  2 rows updated.
UPDATE orders
  SET line_items_count =
  NVL(NULL,0)+1
 WHERE order_id = 92;

  UPDATE orders
  SET line_items_count =
  NVL(2,0)-1
 WHERE order_id = 78; 
UPDATE orders
  SET line_items_count =
  NVL(1,0)+1
 WHERE order_id = 92;

  UPDATE orders
  SET line_items_count =
  NVL(1,0)-1
 WHERE order_id = 78;

El cliente mueve las líneas de ítem de la orden 78 a la orden 92.

La sentencia UPDATE cambia 2 filas en las tablas lineitems, que llama al disparador una vez para cada fila.

Cada vez que se llama al disparador, se cumplen ambas condiciones IF en el disparador. La primera condición aumenta el recuento de la orden 92, mientras que la segunda condición disminuye el recuento de la orden 78. Por lo tanto, se ejecutan cuatro sentencias UPDATE totales.

SQL> SELECT * FROM orders;

  ORDER_ID LINE_ITEMS_COUNT
 --------- ----------------
 78 0
 92 2
  El cliente consulta el estado de los dos pedidos. El efecto neto es que el recuento de líneas de artículo de la orden 92 ha aumentado de 0 a 2, mientras que el recuento de la orden 78 ha disminuido de 2 a 0.
SQL> SELECT * FROM lineitems;

  ORDER_ID SEQ_NO
 ---------- ----------
 92 1
 92 2
  El cliente consulta el estado de las líneas de ítem. Cada artículo se identifica de forma exclusiva mediante el ID de pedido y el número de secuencia.
SQL> DELETE FROM lineitems;

  2 rows deleted.
UPDATE orders
  SET line_items_count =
  NVL(2,0)-1
 WHERE order_id = 92;

  UPDATE orders
  SET line_items_count =
  NVL(1,0)-1
 WHERE order_id = 92;

El cliente ahora elimina todas las líneas de artículo de todas las órdenes.

La sentencia DELETE cambia 2 filas en las tablas lineitems, que llama al disparador una vez para cada fila. Para cada llamada de disparador, solo se cumple una condición IF en el disparador. Cada vez que la condición disminuye el recuento de la orden 92 en 1. Por lo tanto, se ejecutan dos sentencias UPDATE totales.

SQL> SELECT * FROM orders;

  ORDER_ID LINE_ITEMS_COUNT
 --------- ----------------
 78 0
 92 0

  SQL> SELECT * FROM lineitems;

  no rows selected
 

El cliente consulta el estado de los dos pedidos. Ninguna de las órdenes contiene líneas de artículo.

El cliente también consulta el estado de las líneas de ítem. No existen artículos.

Ejecución de activadores

Oracle Database ejecuta un disparador internamente mediante los mismos pasos que para la ejecución del subprograma.

La única diferencia sutil es que una cuenta de usuario tiene derecho a disparar un disparador si tiene el privilegio de ejecutar la sentencia disparadora. Con esta excepción, la base de datos valida y ejecuta los disparadores de la misma forma que los subprogramas almacenados.

Consulte también: Referencia de lenguaje PL/SQL de Oracle AI Database para obtener más información sobre la ejecución de disparadores

automáticamente en ciertas situaciones.")

Almacenamiento de Disparadores

Oracle Database almacena disparadores PL/SQL en formato compilado en un esquema de base de datos, al igual que los procedimientos almacenados PL/SQL.

Cuando se confirma una sentencia CREATE TRIGGER, el código PL/SQL compilado se almacena en la base de datos. El pool compartido elimina el código fuente del disparador PL/SQL.

En el siguiente gráfico se muestra una aplicación de base de datos con sentencias SQL que llaman implícitamente a disparadores PL/SQL. Los disparadores se almacenan independientemente de sus tablas asociadas.

Figura 7: Disparadores

Descripción de la ilustración cncpt076.gif

Los disparadores Java se almacenan de la misma forma que los disparadores PL/SQL. Sin embargo, un disparador Java hace referencia al código Java que se ha compilado por separado con una sentencia CALL. Por lo tanto, la creación de un disparador Java implica la creación de código Java y la creación del disparador que hace referencia a este código Java.

Consulte también: Referencia de lenguaje PL/SQL de Oracle AI Database para obtener más información sobre la compilación y el almacenamiento de disparadores

automáticamente en ciertas situaciones.")