Programação no Lado do Servidor: PL/SQL, Java e JavaScript

O SQL explica a linguagem SQL (Structured Query Language) e como o banco de dados processa as instruções SQL. Este capítulo explica como os programas PL/SQL (Procedural Language/SQL) ou Java armazenados no banco de dados podem usar SQL.

Introdução à Programação no Lado do Servidor

Em uma linguagem não processual, como o SQL, o conjunto de dados a ser operado é especificado, mas não as operações a serem executadas ou a maneira pela qual devem ser realizadas.

Em um programa de linguagem procedural, a execução da maioria das instruções depende de instruções anteriores ou subsequentes e de estruturas de controle, como loops ou ramificações condicionais, que não estão disponíveis em SQL. Para uma ilustração da diferença entre linguagens procedurais e não processuais, suponha que a seguinte instrução SQL consulte a tabela employees:

SELECT employee_id, department_id, last_name, salary FROM employees;

A instrução anterior solicita dados, mas não aplica lógica aos dados. No entanto, suponhamos que você queira que um aplicativo determine se cada funcionário no conjunto de dados merece um aumento com base no salário e no desempenho do departamento. Uma condição necessária para um aumento é que o funcionário não tenha recebido mais de três aumentos nos últimos cinco anos. Se for necessário um aumento, o aplicativo deverá ajustar o salário e enviar um e-mail ao gerente; caso contrário, o aplicativo deverá atualizar um relatório.

O problema é como os aplicativos de banco de dados procedural que exigem lógica condicional e controle de fluxo de programa podem usar SQL. As abordagens básicas de desenvolvimento são as seguintes:

Este capítulo explica a segunda abordagem. O principal benefício da programação do lado do servidor é que a funcionalidade incorporada ao banco de dados pode ser implantada em qualquer lugar. O banco de dados, e não o aplicativo, determina a melhor maneira de executar tarefas em um determinado sistema operacional. Além disso, os subprogramas aumentam a escalabilidade ao centralizar o processamento de aplicativos no servidor, permitindo que os clientes reutilizem o código. Como as chamadas de subprograma são rápidas e eficientes, uma única chamada pode iniciar um subprograma armazenado com uso intensivo de computação, reduzindo o tráfego de rede.

Você pode usar os seguintes idiomas para armazenar a lógica de dados no Oracle AI Database:

Consulte Também:

Visão Geral de PL/SQL

O PL/SQL fornece uma linguagem procedural armazenada e do lado do servidor que é fácil de usar, integrada ao SQL, robusta, portátil e segura. Você pode acessar e manipular dados do banco de dados usando objetos de procedimento chamados unidades PL/SQL.

Geralmente, as unidades PL/SQL são categorizadas da seguinte forma:

O compilador e o interpretador PL/SQL são incorporados ao Oracle SQL Developer, oferecendo aos desenvolvedores um modelo de desenvolvimento consistente e aproveitado no cliente e no servidor. Além disso, os procedimentos armazenados PL/SQL podem ser chamados de vários clientes de banco de dados, como Pro*C, JDBC, ODBC ou OCI, e do Oracle Reports e Oracle Forms.

Consulte Também:

Subprogramas PL/SQL

Um subprograma PL/SQL é um bloco PL/SQL nomeado que permite ao chamador fornecer parâmetros que podem ser somente entrada, somente saída ou valores de entrada e saída.

Um subprograma resolve um problema específico ou executa tarefas relacionadas e serve como um bloco de construção para aplicativos de banco de dados modulares e de manutenção. Um subprograma é um procedimento PL/SQL ou uma função PL/SQL. Procedimentos e funções são idênticos, exceto que funções sempre retornam um único valor para o chamador, enquanto procedimentos não. O termo procedimento PL/SQL neste capítulo refere-se a um procedimento ou a uma função.

Consulte Também:

Vantagens de Subprogramas PL/SQL

A programação do lado do servidor tem muitas vantagens sobre a programação do lado do cliente.

As vantagens incluem:

Consulte Também:

Criação de Subprogramas PL/SQL

Subprograma armazenado stand-alone é um subprograma criado no nível do esquema com a instrução CREATE PROCEDURE ou CREATE FUNCTION. Os subprogramas definidos em um pacote são denominados subprogramas de pacote e são considerados parte do pacote.

O banco de dados armazena subprogramas no dicionário de dados como objetos de esquema. Um subprograma tem uma especificação, que inclui descrições de quaisquer parâmetros e um corpo.

Exemplo 11-1 Procedimento PL/SQL

Este exemplo mostra parte de uma instrução de criação para o procedimento PL/SQL standalone hire_employees. O procedimento insere uma linha na tabela 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 Também:

Execução de Subprogramas PL/SQL

Os usuários podem executar um subprograma interativamente de várias maneiras.

As opções são:

O gráfico a seguir mostra diferentes aplicativos de banco de dados que chamam hire_employees.

Figura 1: Várias Execuções de um Procedimento Armazenado

Descrição da ilustração cncpt073.gif

Como alternativa, um usuário privilegiado pode usar o Oracle Enterprise Manager ou o SQL*Plus para executar o procedimento hire_employees usando uma instrução como a seguinte:

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

A instrução anterior insere um novo registro para TSMITH na tabela employees.

Um procedimento armazenado depende dos objetos referenciados em seu corpo. O banco de dados rastreia e gerencia automaticamente essas dependências. Por exemplo, se você alterar a definição da tabela employees referenciada pelo procedimento hire_employees de uma maneira que afete esse procedimento, o procedimento deverá ser recompilado para validar se ele ainda funciona conforme projetado. Normalmente, o banco de dados administra automaticamente esse gerenciamento de dependência.

Consulte Também:

Pacotes PL/SQL

Um pacote PL/SQL é um grupo de subprogramas relacionados, juntamente com os cursores e variáveis que eles usam, armazenados juntos no banco de dados para uso contínuo como uma unidade. Os subprogramas empacotados podem ser chamados explicitamente por aplicativos ou usuários.

O Oracle AI Database inclui muitos pacotes fornecidos que estendem a funcionalidade do banco de dados e fornecem acesso PL/SQL a recursos SQL. Por exemplo, o pacote UTL_HTTP permite que chamadas HTTP do PL/SQL e SQL acessem dados na Internet ou chamem Cartuchos do Oracle Web Server. Você pode usar os pacotes fornecidos ao criar aplicativos ou como uma fonte de ideias ao criar seus próprios procedimentos armazenados.

Vantagens dos Pacotes PL/SQL

Os pacotes PL/SQL oferecem várias vantagens para o desenvolvedor de aplicativos.

As vantagens incluem:

Criação de Pacotes PL/SQL

Você cria um pacote em duas partes: a especificação e o corpo. A especificação do pacote declara todas as construções públicas do pacote, enquanto o corpo do pacote define todas as construções (públicas e privadas) do pacote.

O exemplo a seguir mostra parte de uma instrução que cria a especificação de pacote para employees_management, que encapsula vários subprogramas usados para gerenciar um banco de dados de funcionário. Cada parte do pacote é criada com uma instrução 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;

A especificação declara a função hire_employees, os procedimentos fire_employees e salary_raise, e a exceção no_sal. Todos esses objetos de programa público estão disponíveis para os usuários que têm acesso ao pacote.

A instrução CREATE PACKAGE BODY define objetos declarados na especificação. O corpo do pacote deve ser criado no mesmo esquema que o pacote. Depois de criar o pacote, você poderá desenvolver aplicativos que chamem qualquer um desses procedimentos ou funções públicos ou que gerem qualquer uma das exceções públicas do pacote.

Consulte Também: Referência de Linguagem PL/SQL do Oracle AI Database para saber mais sobre a instrução CREATE PACKAGE

Execução de Subprogramas de Pacote PL/SQL

Acionadores de banco de dados, subprogramas armazenados, programas de aplicativos 3GL e ferramentas Oracle podem fazer referência ao conteúdo do pacote.

O gráfico a seguir mostra os aplicativos de banco de dados chamando procedimentos e funções no pacote employees_management.

Figura 2: Chamando Subprogramas em um Pacote PL/SQL

Descrição da ilustração cncpt075.gif

Os aplicativos de banco de dados chamam explicitamente os procedimentos empacotados conforme necessário. Depois de receber os privilégios do pacote employees_management, um usuário poderá executar explicitamente qualquer um dos procedimentos contidos nele. Por exemplo, o SQL*Plus pode emitir a seguinte instrução para executar o procedimento do pacote hire_employees:

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

Consulte Também:

Blocos Anônimos PL/SQL

Bloco anônimo PL/SQL é uma unidade não nomeada e não persistente do código PL/SQL.

Os usos típicos para blocos anônimos incluem:

Blocos anônimos não têm vantagens de reutilização de código de subprogramas armazenados. A Tabela 11-1 resume as diferenças entre os dois tipos de unidades PL/SQL.

Tabela 1 - Diferenças entre Blocos Anônimos e Subprogramas

É a Unidade PL/SQL… Blocos Anônimos Subprogramas
Especificado com um nome? Não Sim
Compilado com cada reutilização? Não Não
Armazenado no Banco de Dados? Não Sim
Invocável por outros aplicativos? Não Sim
Capaz de retornar valores de variáveis de vínculo? Sim Sim
Capaz de retornar valores de função? Não Sim
Capaz de aceitar parâmetros? Não Sim

Um bloco anônimo consiste em uma parte declarativa opcional, uma parte executável e um ou mais handlers de exceção opcionais. O bloco anônimo de amostra a seguir seleciona o sobrenome de um funcionário em uma variável e imprime o nome:

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;

O Oracle AI Database compila o bloco PL/SQL e o coloca no shared pool da SGA, mas não armazena o código-fonte ou a versão compilada no banco de dados para reutilização além da instância atual. Ao contrário dos gatilhos, um bloco anônimo é compilado toda vez que é carregado na memória. O Shared SQL permite que blocos PL/SQL anônimos no shared pool sejam reutilizados e compartilhados até que sejam liberados do shared pool.

Consulte Também: Oracle AI Database Development Guide para saber mais sobre blocos PL/SQL anônimos

Construções de Linguagem PL/SQL

Os blocos PL/SQL podem incluir várias construções de linguagem PL/SQL diferentes.

Essas construções incluem o seguinte:

O PL/SQL pode executar instruções SQL dinâmicas cujo texto completo não é conhecido até o tempo de execução. As instruções SQL dinâmicas são armazenadas em strings de caracteres que são inseridas ou criadas pelo programa no run-time. Essa técnica permite criar procedimentos de finalidades gerais. Por exemplo, você pode criar um procedimento que opere em uma tabela cujo nome não seja conhecido até o run-time.

Consulte Também:

Coleções e registros PL/SQL

Muitas técnicas de programação usam tipos de coleta, como matrizes, sacos, listas, tabelas aninhadas, conjuntos e árvores.

Para suportar técnicas de coleta em aplicações de banco de dados, o PL/SQL fornece os tipos de dados TABLE e VARRAY. Esses tipos permitem declarar matrizes associativas, tabelas aninhadas e matrizes de tamanho variável.

Coleções

Uma coleção PL/SQL é um grupo ordenado de elementos, todos do mesmo tipo.

Cada elemento tem um subscrito exclusivo que determina sua posição na coleta. Para criar uma coleção, primeiro você define um tipo de coleção e, em seguida, declara uma variável desse tipo.

As coleções funcionam como os arrays encontrados na maioria das linguagens de programação de terceira geração. Além disso, as coletas podem ser passadas como parâmetros. Assim, você pode usá-los para mover colunas de dados para dentro e para fora de tabelas de banco de dados ou entre aplicativos do lado do cliente e subprogramas armazenados.

Registros

Um registro PL/SQL é uma variável composta que pode armazenar valores de dados com diferentes tipos, semelhantes a um tipo de estrutura em C, C++ ou Java. Os registros são úteis para armazenar dados das linhas das tabelas ou determinadas colunas de linhas das tabelas.

Suponha que você tenha dados sobre um funcionário, como nome, salário e data de contratação. Estes itens são diferentes em tipo, mas logicamente relacionados. Um registro que contém um campo para cada item permite tratar os dados como uma unidade lógica.

Você pode usar o atributo %ROWTYPE para declarar um registro que represente uma linha ou linha de tabela extraída de um cursor. Com registros definidos pelo usuário, você pode declarar seus próprios campos.

Consulte Também: Referência de Linguagem PL/SQL do Oracle AI Database para saber como usar registros PL/SQL

Como o Código PL/SQL É Executado

O PL/SQL suporta execução interpretada e execução nativa.

Na execução interpretada, o código-fonte PL/SQL é compilado em uma representação chamada bytecode. Um computador virtual portátil implementado como parte do Oracle AI Database executa esse código de bytes.

A execução nativa oferece o melhor desempenho em unidades computacionalmente intensivas. Nesse caso, o código-fonte das unidades PL/SQL é compilado diretamente no código-objeto da plataforma fornecida. Este código de objeto está vinculado ao Oracle AI Database.

O mecanismo PL/SQL define, compila e executa unidades PL/SQL. Esse mecanismo é um componente especial de muitos produtos Oracle, incluindo o Oracle AI Database. Embora muitos produtos Oracle tenham componentes PL/SQL, este tópico abrange especificamente as unidades PL/SQL que podem ser armazenadas no Oracle AI Database e processadas usando o mecanismo PL/SQL do Oracle AI Database. A documentação de cada ferramenta Oracle descreve seus recursos de PL/SQL.

O gráfico a seguir ilustra o mecanismo PL/SQL contido no Oracle AI Database.

Figura 3: O Mecanismo PL/SQL e o Oracle AI Database

Descrição da ilustração cncpt070.gif

A unidade PL/SQL é armazenada em um banco de dados. Quando um aplicativo chama um procedimento armazenado, o banco de dados carrega a unidade PL/SQL compilada no pool compartilhado na Área Global do Sistema (SGA). Os executores de instruções PL/SQL e SQL trabalham juntos para processar as instruções no procedimento.

Você pode chamar um procedimento armazenado de outro bloco PL/SQL, que pode ser um bloco anônimo ou outro procedimento armazenado. Por exemplo, você pode chamar um procedimento armazenado do Oracle Forms.

Um procedimento PL/SQL executado no Oracle AI Database pode chamar um procedimento externo ou uma função gravada na linguagem de programação C e armazenada em uma biblioteca compartilhada. A rotina C é executada em um espaço de endereço separado do Oracle AI Database.

Consulte Também:

Visão Geral do Java no Oracle AI Database

O Java surgiu como a linguagem de programação orientada a objetos de sua escolha.

O Java inclui os seguintes recursos:

O banco de dados fornece aos programas Java um mecanismo de processamento de dados dinâmico que suporta consultas complexas e várias exibições de dados. As solicitações do cliente são montadas como consultas de dados para processamento imediato. Os resultados da consulta são gerados dinamicamente.

A combinação de Java e Oracle AI Database ajuda a criar aplicações baseadas em componentes e centradas na rede que podem ser facilmente atualizadas à medida que as necessidades de negócios mudam. Além disso, você pode mover aplicativos e armazenamentos de dados para fora da área de trabalho e para redes inteligentes e servidores centrados na rede. Mais importante ainda, você pode acessar esses aplicativos e armazenamentos de dados de qualquer dispositivo cliente.

A figura a seguir mostra uma configuração tradicional de cliente/servidor de duas camadas na qual os clientes chamam procedimentos armazenados Java da mesma forma que chamam subprogramas PL/SQL.

Figura 4: Configuração de Cliente/Servidor de Duas Camadas

Descrição da ilustração cncpt236.gif

Visão Geral do Java Virtual Machine (JVM)

Uma JVM é um processador virtual que executa o código Java compilado.

O código-fonte Java é compilado para instruções de máquina de baixo nível, conhecidas como bytecodes, que são independentes de plataforma. Os bytecodes Java são interpretados por meio da JVM em direção a ações dependentes de plataforma.

Visão Geral do Oracle JVM

A Oracle JVM é um ambiente padrão compatível com Java que executa qualquer aplicativo Java puro. É compatível com as especificações JLS e JVM.

A JVM da Oracle suporta o formato binário Java padrão e as APIs. Além disso, o Oracle AI Database adere à semântica de linguagem Java padrão, incluindo o carregamento dinâmico de classes em tempo de execução.

A figura a seguir ilustra como os aplicativos Oracle Java residem na parte superior das bibliotecas de classes principais Java, que residem na parte superior da JVM Oracle. Como o sistema de suporte Oracle Java está localizado dentro do banco de dados, a JVM interage com as bibliotecas de banco de dados, em vez de interagir diretamente com o sistema operacional.

Figura 5: Estrutura do Componente Java

Descrição da ilustração cncpt206.gif

Ao contrário de outros ambientes Java, a Oracle JVM está incorporada ao Oracle AI Database. Existem algumas diferenças importantes entre a JVM do Oracle e as JVMs típicas do cliente. Por exemplo, em um ambiente Java padrão, você executa um aplicativo Java por meio do interpretador emitindo o seguinte comando na linha de comando, em que classname é o nome da classe que a JVM interpreta primeiro:

java classname

O comando anterior faz com que o aplicativo seja executado dentro de um processo no sistema operacional. No entanto, se você não estiver usando a interface de linha de comando, deverá carregar o aplicativo no banco de dados, publicar a interface e, em seguida, executar o aplicativo em um dicionário de dados do banco de dados.

Consulte Também: Consulte o Oracle AI Database Java Developer's Guide para obter uma descrição de outras diferenças entre a JVM do Oracle e as JVMs típicas do cliente

Principais Componentes do Oracle JVM

A JVM da Oracle é executada no mesmo espaço de processo e de endereço que o kernel do banco de dados, compartilhando seus heaps de memória e acessando diretamente seus dados relacionais. Esse design otimiza o uso da memória e aumenta o throughput.

A JVM da Oracle fornece um ambiente de runtime para objetos Java. Ele suporta totalmente estruturas de dados Java, despacho de método, tratamento de exceções e threads no nível de linguagem. Ele também suporta todas as bibliotecas de classes Java básicas, incluindo java.lang, java.io, java.net, java.math e java.util.

A ilustração a seguir mostra os principais componentes da JVM Oracle.

Figura 6: Principais Componentes da JVM Oracle

Descrição da ilustração cncpt254.gif

A JVM da Oracle incorpora o namespace Java padrão nos esquemas de banco de dados. Esse recurso permite que os programas Java acessem objetos Java armazenados no Oracle AI Database e em servidores de aplicativos em toda a empresa.

Além disso, a JVM da Oracle está totalmente integrada à arquitetura de memória compartilhada e escalável do banco de dados. Os programas Java usam chamadas, sessões e vidas de objetos com eficiência, sem a intervenção do usuário. Consequentemente, os objetos de negócios Java de camada intermediária e JVM da Oracle podem ser dimensionados, mesmo quando têm um estado de sessão longa.

Consulte Também: Oracle AI Database Java Developer's Guide para obter uma descrição dos principais componentes da Oracle JVM

Ambiente de Programação Java

A Oracle fornece aos desenvolvedores de aplicativos empresariais uma solução Java de ponta a ponta para criar, implementar e gerenciar aplicativos Java.

A solução consiste em interfaces programáticas do lado do cliente e do lado do servidor, ferramentas para suportar o desenvolvimento do Java e uma Java Virtual Machine integrada ao Oracle AI Database. Todos esses produtos são compatíveis com os padrões Java.

O ambiente de programação Java consiste nos seguintes recursos adicionais:

Procedimentos Armazenados Java

Procedimento armazenado em Java é um método Java publicado em SQL e armazenado no banco de dados.

Como um subprograma PL/SQL, um procedimento Java pode ser chamado diretamente com produtos como o SQL*Plus ou indiretamente com um trigger. Você pode acessá-lo em qualquer OCI cliente, pré-compilador ou JDBC do Oracle Net.

Para publicar métodos Java, você grava especificações de chamada, que mapeiam nomes de métodos Java, tipos de parâmetros e tipos de retorno para suas contrapartes SQL. Quando chamado por aplicativos cliente, um procedimento armazenado em Java pode aceitar argumentos, fazer referência a classes Java e retornar valores de resultado Java.

Os aplicativos que chamam o método Java fazem referência ao nome da especificação de chamada. O sistema de run-time procura a definição de especificação de chamada no dicionário de dados Oracle e executa o método Java correspondente.

Além disso, você pode usar o Java para desenvolver programas avançados, independentemente da linguagem PL/SQL. O Oracle AI Database fornece uma implementação totalmente compatível da linguagem de programação Java e da JVM.

Consulte Também: O Oracle AI Database Java Developer's Guide explica como escrever procedimentos armazenados em Java, como acessá-los em PL/SQL e como acessar a funcionalidade PL/SQL do Java

Integração Java e PL/SQL

Você pode chamar programas PL/SQL existentes em programas Java e Java em programas PL/SQL. Essa solução protege e utiliza seus códigos PL/SQL e Java.

O Oracle AI Database oferece JDBC para acessar dados SQL do Java no cliente e no servidor.

Drivers JDBC

JDBC é um protocolo de acesso ao banco de dados que permite estabelecer conexão com um banco de dados e executar instruções e consultas SQL no banco de dados.

As bibliotecas de classe Java básicas fornecem apenas uma API JDBC, java.sql. No entanto, o JDBC foi projetado para permitir que os fornecedores forneçam drivers que ofereçam a especialização necessária para um determinado banco de dados. O Oracle fornece os drivers JDBC distintos mostrados na tabela a seguir.

Drivers JDBC da Tabela 2

Driver Descrição
Driver JDBC Thin Você pode usar o driver JDBC Thin para gravar aplicativos e applets Java puros que acessam dados do Oracle SQL. O driver JDBC Thin é especialmente adequado para aplicativos e applets baseados na Web, porque você pode baixá-lo dinamicamente de uma página da Web, semelhante a qualquer outro applet Java.
Driver JDBC OCI O driver JDBC OCI acessa o código nativo específico da Oracle, ou seja, código não Java e bibliotecas na camada cliente ou intermediária, proporcionando um aumento de desempenho em comparação com o driver JDBC Thin, ao custo de tamanho significativamente maior e instalação no lado do cliente.
Driver interno do servidor JDBC O Oracle AI Database usa o driver interno do servidor quando o código Java é executado no servidor. Ele permite que os aplicativos Java em execução na JVM da Oracle no servidor acessem dados definidos localmente, ou seja, dados no mesmo sistema e no mesmo processo, com JDBC. Ele proporciona um aumento de desempenho, devido à sua capacidade de usar as bibliotecas subjacentes do Oracle RDBMS diretamente, sem a sobrecarga de uma conexão de rede intermediária entre o código Java e os dados SQL. Ao suportar a mesma interface Java-SQL no servidor, o Oracle AI Database não exige que você retrabalhe o código ao implantá-lo.

Consulte Também:

Visão geral do JavaScript no Oracle AI Database

O JavaScript é uma das linguagens de programação mais populares atualmente. O Oracle AI Database implantado no Linux x86-64 ou no Linux aarch64 adiciona JavaScript à lista de idiomas suportados para desenvolvimento no lado do servidor.

Você pode armazenar módulos do JavaScript no banco de dados, processando dados onde eles residem, oferecendo melhorias potencialmente significativas em relação às abordagens de desenvolvimento do lado do cliente. JavaScript é executado pelo Multilingual Engine (MLE).

Os desenvolvedores têm a opção de executar o código JavaScript standalone e armazenar o código JavaScript nativamente no banco de dados como módulos.

Armazenando Lógica de Negócios como Módulos no Banco de Dados

Assim como no desenvolvimento do lado do cliente relacionado ao JavaScript, o código pode ser armazenado em conjunto na forma de um módulo.

Os desenvolvedores com um plano de fundo PL/SQL podem pensar em um módulo JavaScript como o equivalente a um corpo de pacote PL/SQL, mas escrito em JavaScript. Funções declaradas em um módulo podem ser marcadas para serem exportadas ou mantidas privadas.

O JavaScript no Oracle AI Database adere ao padrão ECMAScript 2023 e oferece aos desenvolvedores uma ampla gama de possibilidades para armazenar lógica de negócios no banco de dados.

Observação:

Consulte também:

Veja abaixo um exemplo de criação de um módulo JavaScript com 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;
}
/

O módulo JavaScript, também conhecido como Módulo MLE, agora é armazenado no esquema do usuário. Sua única função, string2obj(), pode ser exposta a SQL e PL/SQL criando uma Especificação de Chamada. As Especificações de Chamada são unidades de programa PL/SQL que permitem chamar o código JavaScript em todos os lugares em que SQL e PL/SQL podem ser chamados. A Especificação de Chamada para string2obj() pode ser escrita da seguinte forma:

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

Com a função criada, ela pode ser chamada de 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.

Execução Dinâmica do Código JavaScript

Os desenvolvedores de framework e qualquer pessoa que deseje executar código JavaScript autônomo sem a necessidade de armazenar código no banco de dados pode fazer uso do pacote DBMS_MLE e de suas sub-rotinas.

O Oracle Application Express e o Database Actions, por exemplo, integram o DBMS_MLE, ocultando o fato de que um pacote PL/SQL é chamado nas capas.

Em comparação com os módulos MLE, o uso de DBMS_MLE dificulta a gravação de aplicativos inteiros. Por exemplo, é mais difícil dividir logicamente um aplicativo em entidades separadas. O recurso Depuração Pós-Execução requer módulos, dificultando a solução de problemas em trechos de código. Os pipelines de Integração Contínua (CI) também podem ter dificuldades com o linting de código PL/SQL e JavaScript no mesmo arquivo. Da mesma forma, há um possível problema com seu Ambiente de Desenvolvimento Integrado (IDE), pois a maioria terá dificuldade em trabalhar com PL/SQL e JavaScript na mesma janela.

Observação:

Consulte também:

Procedimentos Armazenados JavaScript em Linha

As especificações de chamada MLE embutidas incorporam o código JavaScript diretamente nas DDLs CREATE FUNCTION e CREATE PROCEDURE.

Se você quiser implementar rapidamente uma funcionalidade simples usando JavaScript, as especificações de chamada MLE inline podem ser uma boa escolha. Com essa opção, você não precisa implantar um módulo separado que contenha o código JavaScript. Em vez disso, a função JavaScript é incorporada à definição da própria especificação de chamada.

A cláusula MLE LANGUAGE é usada para especificar que a função é implementada usando JavaScript. A string que segue o nome do idioma é tratada como o corpo de uma função JavaScript que implementa a funcionalidade da especificação de chamada. Quando o código é executado, os parâmetros PL/SQL são automaticamente convertidos no tipo JavaScript padrão e passados para a função JavaScript como parâmetros com o mesmo nome. Observe que os nomes de parâmetros sem aspas são mapeados para nomes JavaScript em letras maiúsculas. O valor retornado por uma função JavaScript é convertido no tipo de retorno da especificação de chamada PL/SQL, assim como acontece com as especificações de chamada para módulos MLE.

Observação:

Consulte também:

Visão Geral de Acionadores

Um trigger de banco de dados é uma unidade de programa armazenada compilada, gravada em PL/SQL, Java ou JavaScript, que o Oracle Database chama ("dispara") automaticamente em determinadas situações.

Um trigger é acionado sempre que ocorre uma das seguintes operações:

  1. instruções DML em uma tabela ou view específica, emitidas por qualquer usuário

    As instruções DML modificam dados nos objetos de esquema. Por exemplo, a inserção e a exclusão de linhas são operações DML.

  2. Instruções DDL emitidas por um usuário específico ou por qualquer usuário

    As instruções DDL definem objetos de esquema. Por exemplo, a criação de uma tabela e a adição de uma coluna são operações DDL.

  3. Eventos do banco de dados

    Logon ou logoff do usuário, erros e inicialização ou shutdown do banco de dados são eventos que podem chamar acionadores.

Triggers são objetos de esquema que são semelhantes a subprogramas, mas diferem na forma como são chamados. Um subprograma é executado explicitamente por um usuário, aplicativo ou acionador. Os triggers são implicitamente chamados pelo banco de dados quando um evento de trigger ocorre.

Consulte Também:

Vantagens dos Triggers

O uso correto de triggers permite que você crie e implante aplicativos mais robustos e que usem o banco de dados com mais eficiência.

Você pode usar acionadores para:

Você pode usar triggers para impor regras de negócios de nível inferior comuns a todos os aplicativos cliente. Por exemplo, vários aplicativos podem acessar a tabela employees. Se um acionador nesta tabela garantir o formato dos dados inseridos, essa lógica de negócios não precisará ser reproduzida em todos os clientes. Como o acionador não pode ser contornado pelo aplicativo, a lógica de negócios no acionador é usada automaticamente.

Você pode usar triggers e constraints de integridade para definir e impor qualquer tipo de regra de integridade. No entanto, a Oracle recomenda que você só use triggers para impor regras de negócios complexas não definíveis usando uma constrição de integridade.

O uso excessivo de gatilhos pode resultar em interdependências complexas que podem ser difíceis de manter em um aplicativo grande. Por exemplo, quando um trigger é chamado, uma instrução SQL dentro de sua ação de trigger pode potencialmente acionar outros triggers, resultando em triggers em cascata que podem produzir efeitos indesejados.

Consulte Também:

automaticamente em determinadas situações.")

Tipos de Triggers

Os gatilhos podem ser categorizados de acordo com seus meios de invocação e o tipo de ações que eles executam.

O Oracle Database suporta os seguintes tipos de triggers:

Consulte Também:

automaticamente em determinadas situações.")

Tempo para Triggers

É possível definir o tempo de acionamento - se a ação de acionamento deve ser executada antes ou depois da instrução de acionamento.

Um gatilho simples é um único trigger em uma tabela que permite especificar ações para exatamente um dos seguintes pontos de tempo:

Para acionadores de instrução e linha, um acionador BEFORE pode aprimorar a segurança e ativar regras de negócios antes de fazer alterações no banco de dados. O trigger AFTER é ideal para ações de log.

Um gatilho composto pode ser acionado em vários pontos de tempo. Os gatilhos compostos ajudam a programar uma abordagem na qual as ações que você implementa para vários pontos de tempo compartilham dados comuns.

Consulte Também: Referência de Linguagem PL/SQL do Oracle AI Database para saber mais sobre triggers compostos

automaticamente em determinadas situações.")

Criação de Triggers

A instrução CREATE TRIGGER cria ou substitui um trigger de banco de dados.

Um trigger PL/SQL tem a seguinte forma sintática geral:

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

Um trigger de PL/SQL tem os seguintes componentes básicos:

Consulte Também:

automaticamente em determinadas situações.")

Exemplo: Instrução CREATE TRIGGER

Este exemplo cria um trigger que é acionado quando uma instrução INSERT, UPDATE ou DELETE é executada em uma tabela de itens de linha.

Suponha que você crie as tabelas orders e lineitems com as instruções a seguir. A tabela orders contém uma linha para cada ordem exclusiva, enquanto a tabela lineitems contém uma linha para cada item em uma ordem.

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

A instrução a seguir cria um trigger de amostra que atualiza automaticamente a tabela orders com o número de itens em uma ordem:

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

Em lineitems_trigger, a instrução de acionamento é INSERT, UPDATE ou DELETE na tabela lineitems. Não existe restrição de acionamento. O trigger é chamado para cada linha alterada. O acionador tem acesso aos valores de coluna antigos e novos da linha atual afetada pela instrução de acionamento. Existem dois nomes de correlação para cada coluna da tabela que está sendo modificada: o valor antigo (:old) e o novo (:new). Se uma sessão atualizar ou inserir linhas em lineitems para um pedido, após a ação, o acionador calculará o número de itens neste pedido e atualizará a tabela orders com a contagem.

Exemplo: Chamando um Acionador no Nível da Linha

Nesse cenário, um cliente inicia dois pedidos e adiciona e remove itens de linha dos pedidos.

O cenário é baseado no TRIGGER criado em Exemplo: Instrução CREATE TRIGGER.

Cenário de Acionador no Nível de Linha da Tabela 3

Instrução SQL Instrução SQL Acionada Descrição
SQL> INSERT INTO orders
 (order_id) VALUES (78);

  1 row created. 
 

O cliente cria um pedido com o ID 78. nesse ponto, o cliente não tem itens no pedido.

Como nenhuma ação é executada na tabela lineitems, o trigger não é chamado.

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

  1 row created. 
 

O cliente cria um pedido separado com o ID 92. nesse ponto, o cliente não tem itens no pedido.

Como nenhuma ação é executada na tabela lineitems, o trigger não é chamado.

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;

O cliente adiciona um item ao pedido 78.

O INSERT chama o trigger. A instrução acionada aumenta a contagem de itens de linha do pedido 78 de 0 para 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; 

O cliente adiciona um item adicional ao pedido 78.

O INSERT chama o trigger. A instrução acionada aumenta a contagem de itens de linha do pedido 78 de 1 para 2.

SQL> SELECT * FROM orders;

  ORDER_ID LINE_ITEMS_COUNT
 --------- ----------------
 78 2
 92 0
  O cliente consulta o status dos dois pedidos. A ordem 78 contém dois itens. A ordem 92 não contém itens.
SQL> SELECT * FROM lineitems;

  ORDER_ID SEQ_NO
 ---------- ----------
 78 1
 78 2
  O cliente consulta o status dos itens de linha. Cada item é identificado exclusivamente pelo ID da ordem e pelo número de sequência.
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;

o cliente move os itens de linha que estavam no pedido 78 para o pedido 92.

A instrução UPDATE altera 2 linhas nas tabelas lineitems, que chamam o trigger uma vez para cada linha.

Cada vez que o trigger é chamado, as duas condições IF no trigger são atendidas. A primeira condição aumenta a contagem para a ordem 92, enquanto a segunda condição diminui a contagem para a ordem 78. Assim, quatro instruções UPDATE totais são executadas.

SQL> SELECT * FROM orders;

  ORDER_ID LINE_ITEMS_COUNT
 --------- ----------------
 78 0
 92 2
  O cliente consulta o status dos dois pedidos. O efeito líquido é que a contagem de itens de linha para a ordem 92 aumentou de 0 para 2, enquanto a contagem para a ordem 78 diminuiu de 2 para 0.
SQL> SELECT * FROM lineitems;

  ORDER_ID SEQ_NO
 ---------- ----------
 92 1
 92 2
  O cliente consulta o status dos itens de linha. Cada item é identificado exclusivamente pelo ID da ordem e pelo número de sequência.
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;

Agora o cliente remove todos os itens de linha de todos os pedidos.

A instrução DELETE altera 2 linhas nas tabelas lineitems, que chamam o trigger uma vez para cada linha. Para cada chamada de trigger, somente uma condição IF no trigger é atendida. Cada vez que a condição diminui a contagem para a ordem 92 em 1. Assim, duas instruções UPDATE totais são executadas.

SQL> SELECT * FROM orders;

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

  SQL> SELECT * FROM lineitems;

  no rows selected
 

O cliente consulta o status dos dois pedidos. Nenhuma ordem contém itens de linha.

O cliente também consulta o status dos itens de linha. Não existem itens.

Execução de Triggers

O Oracle Database executa um trigger internamente usando as mesmas etapas da execução do subprograma.

A única diferença sutil é que uma conta de usuário tem o direito de acionar um trigger se tiver o privilégio de executar a instrução de acionamento. Com essa exceção, o banco de dados valida e executa acionadores da mesma forma que os subprogramas armazenados.

Consulte Também: Referência de Linguagem PL/SQL do Oracle AI Database para saber mais sobre a execução do trigger

automaticamente em determinadas situações.")

Armazenamento de Triggers

O Oracle Database armazena triggers PL/SQL em forma compilada em um esquema de banco de dados, assim como os procedimentos armazenados PL/SQL.

Quando uma instrução CREATE TRIGGER é submetida a commit, o código PL/SQL compilado é armazenado no banco de dados. O shared pool remove o código-fonte do trigger PL/SQL.

O gráfico a seguir mostra um aplicativo de banco de dados com instruções SQL que chamam acionadores PL/SQL implicitamente. Os acionadores são armazenados separadamente de suas tabelas associadas.

Figura 7: Triggers

Descrição da ilustração cncpt076.gif

Os triggers Java são armazenados da mesma maneira que os triggers PL/SQL. No entanto, um trigger Java faz referência ao código Java que foi compilado separadamente com uma instrução CALL. Assim, criar um trigger Java envolve a criação de código Java e a criação do trigger que faz referência a esse código Java.

Consulte Também: Referência de Linguagem PL/SQL do Oracle AI Database para saber mais sobre como compilar e armazenar triggers

automaticamente em determinadas situações.")