Programmazione lato server: PL/SQL, Java e JavaScript

SQL spiega il linguaggio SQL (Structured Query Language) e il modo in cui il database elabora le istruzioni SQL. Questo capitolo spiega in che modo i programmi Procedural Language/SQL (PL/SQL) o Java memorizzati nel database possono utilizzare SQL.

Introduzione alla programmazione lato server

In un linguaggio non procedurale come SQL, viene specificato il set di dati su cui operare, ma non le operazioni da eseguire o il modo in cui devono essere eseguite.

In un programma di linguaggio procedurale, la maggior parte dell'esecuzione delle istruzioni dipende dalle istruzioni precedenti o successive e dalle strutture di controllo, come loop o diramazioni condizionali, non disponibili in SQL. Per illustrare la differenza tra le lingue procedurali e non procedurali, si supponga che la seguente istruzione SQL esegua query sulla tabella employees:

SELECT employee_id, department_id, last_name, salary FROM employees;

L'istruzione precedente richiede dati, ma non applica la logica ai dati. Si supponga, tuttavia, che si desideri che un'applicazione determini se ciascun dipendente nel set di dati merita un aumento in base allo stipendio e alle prestazioni del reparto. Una condizione necessaria di un aumento è che il dipendente non ha ricevuto più di tre aumenti negli ultimi cinque anni. Se viene richiesto un aumento, l'applicazione deve adeguare lo stipendio e inviare un'e-mail al manager; in caso contrario, l'applicazione deve aggiornare un report.

Il problema è il modo in cui le applicazioni di database procedurali che richiedono la logica condizionale e il controllo del flusso di programma possono utilizzare SQL. Gli approcci di sviluppo di base sono i seguenti:

Questo capitolo spiega il secondo approccio. Il vantaggio principale della programmazione lato server è che le funzionalità integrate nel database possono essere distribuite ovunque. Il database e non l'applicazione determina il modo migliore per eseguire le attività su un determinato sistema operativo. Inoltre, i sottoprogrammi aumentano la scalabilità centralizzando l'elaborazione delle applicazioni sul server, consentendo ai client di riutilizzare il codice. Poiché le chiamate ai sottoprogrammi sono rapide ed efficienti, una singola chiamata può avviare un sottoprogramma memorizzato ad alta intensità di calcolo, riducendo il traffico di rete.

È possibile utilizzare i seguenti linguaggi per memorizzare la logica dei dati in Oracle AI Database:

Vedere anche:

Panoramica di PL/SQL

PL/SQL offre un linguaggio procedurale memorizzato sul lato server, facile da usare, senza soluzione di continuità con SQL, affidabile, portatile e sicuro. È possibile accedere e manipolare i dati del database utilizzando oggetti procedurali denominati unità PL/SQL.

Le unità PL/SQL in genere sono classificate come segue:

Il compilatore e l'interprete PL/SQL sono incorporati in Oracle SQL Developer, offrendo agli sviluppatori un modello di sviluppo coerente e sfruttato sia sul client che sul server. Inoltre, le stored procedure PL/SQL possono essere richiamate da diversi client di database, come Pro*C, JDBC, ODBC o OCI, e da Oracle Reports e Oracle Forms.

Vedere anche:

Sottoprogrammi PL/SQL

Un sottoprogramma PL/SQL è un blocco PL/SQL denominato che consente al chiamante di fornire parametri che possono essere solo valori di input, solo output o di input e output.

Un sottoprogramma risolve un problema specifico o esegue attività correlate e funge da elemento costitutivo per applicazioni di database modulari e gestibili. Un sottoprogramma è una procedura PL/SQL o una funzione PL/SQL. Le procedure e le funzioni sono identiche tranne che per il fatto che queste restituiscono sempre un valore singolo al chiamante, al contrario di quanto avviene per le procedure. Il termine procedura PL/SQL in questo capitolo fa riferimento a una procedura o a una funzione.

Vedere anche:

Vantaggi dei sottoprogrammi PL/SQL

La programmazione lato server ha molti vantaggi rispetto alla programmazione lato client.

I vantaggi includono:

Vedere anche:

Creazione di sottoprogrammi PL/SQL

Un sottoprogramma memorizzato standalone è un sottoprogramma creato a livello di schema con l'istruzione CREATE PROCEDURE o CREATE FUNCTION. I sottoprogrammi definiti in un pacchetto sono detti sottoprogrammi pacchetto e sono considerati parte del pacchetto.

Il database memorizza i sottoprogrammi nel dizionario dati come oggetti dello schema. Un sottoprogramma ha una specifica, che include descrizioni di qualsiasi parametro e un corpo.

Esempio di procedura PL/SQL 11-1

Questo esempio mostra parte di un'istruzione di creazione per la procedura PL/SQL standalone hire_employees. La procedura inserisce una riga nella tabella 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;

Vedere anche:

Esecuzione di sottoprogrammi PL/SQL

Gli utenti possono eseguire un sottoprogramma in modo interattivo in più modi.

Le opzioni disponibili sono:

L'immagine seguente mostra diverse applicazioni di database che chiamano hire_employees.

Figura 1: esecuzioni multiple di una procedura memorizzata

Descrizione dell'illustrazione cncpt073.gif

In alternativa, un utente con privilegi può utilizzare Oracle Enterprise Manager o SQL*Plus per eseguire la procedura hire_employees utilizzando un'istruzione come quella riportata di seguito.

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

L'istruzione precedente inserisce un nuovo record per TSMITH nella tabella employees.

Una stored procedure dipende dagli oggetti a cui viene fatto riferimento nel relativo corpo. Il database tiene traccia e gestisce automaticamente queste dipendenze. Ad esempio, se si modifica la definizione della tabella employees a cui fa riferimento la procedura hire_employees in un modo che potrebbe influire su questa procedura, la procedura deve essere ricompilata per verificare che funzioni ancora come progettato. In genere, il database amministra automaticamente tale gestione delle dipendenze.

Vedere anche:

Package PL/SQL

Un package PL/SQL è un gruppo di sottoprogrammi correlati, con i cursori esplicitati e le variabili che utilizzano, memorizzati nel database per l'uso continuato come unità. I sottoprogrammi pacchettizzati possono essere richiamati in modo esplicito da applicazioni o utenti.

Oracle AI Database include molti pacchetti forniti che estendono le funzionalità del database e forniscono l'accesso PL/SQL alle funzioni SQL. Ad esempio, il pacchetto UTL_HTTP consente ai callout HTTP di PL/SQL e SQL di accedere ai dati su Internet o di chiamare Oracle Web Server Cartridges. È possibile utilizzare i pacchetti forniti quando si creano applicazioni o come fonte di idee quando si creano le proprie stored procedure.

Vantaggi dei pacchetti PL/SQL

I pacchetti PL/SQL offrono una serie di vantaggi allo sviluppatore dell'applicazione.

I vantaggi includono:

Creazione di pacchetti PL/SQL

Si crea un pacchetto in due parti: la specifica e il corpo. La specifica del pacchetto dichiara tutti i costrutti pubblici del pacchetto, mentre il corpo del pacchetto definisce tutti i costrutti (pubblici e privati) del pacchetto.

L'esempio seguente mostra parte di un'istruzione che crea la specifica di pacchetto per employees_management, che incapsula diversi sottoprogrammi utilizzati per gestire un database di dipendenti. Ogni parte del pacchetto viene creata con un'istruzione diversa.

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 specifica dichiara la funzione hire_employees, le procedure fire_employees e salary_raise e l'eccezione no_sal. Tutti questi oggetti di programma pubblici sono disponibili per gli utenti che hanno accesso al pacchetto.

L'istruzione CREATE PACKAGE BODY definisce gli oggetti dichiarati nella specifica. Il corpo del package deve essere creato nello stesso schema del package. Dopo aver creato il pacchetto, è possibile sviluppare applicazioni che chiamano una qualsiasi di queste procedure o funzioni pubbliche o sollevare una qualsiasi delle eccezioni pubbliche del pacchetto.

Vedere anche: Oracle AI Database PL/SQL Language Reference per informazioni sull'istruzione CREATE PACKAGE

Esecuzione di sottoprogrammi package PL/SQL

I trigger del database, i programmi secondari memorizzati, i programmi applicativi 3GL e gli strumenti Oracle possono fare riferimento ai contenuti dei pacchetti.

L'immagine seguente mostra le applicazioni di database che richiamano procedure e funzioni nel pacchetto employees_management.

Figura 2: Chiamata di sottoprogrammi in un pacchetto PL/SQL

Descrizione dell'illustrazione cncpt075.gif

Le applicazioni di database chiamano esplicitamente le procedure pacchettizzate in base alle esigenze. Dopo aver ottenuto i privilegi per il pacchetto employees_management, un utente può eseguire in modo esplicito una delle procedure in esso contenute. Ad esempio, SQL*Plus può eseguire l'istruzione seguente per eseguire la procedura del package hire_employees:

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

Vedere anche:

Blocchi anonimi PL/SQL

Un blocco anonimo PL/SQL è un'unità PL/SQL senza nome e non persistente.

Gli usi tipici per i blocchi anonimi includono:

I blocchi anonimi non hanno i vantaggi del riutilizzo del codice dei sottoprogrammi memorizzati. La Tabella 11-1 riepiloga le differenze tra i due tipi di unità PL/SQL.

Tabella 1 Differenze tra blocchi anonimi e sottoprogrammi

È l'unità PL/SQL … Blocchi anonimi Sottoprogrammi
Specificare un nome? N. Sì
Compilato con ogni riutilizzo? N. N.
Memorizzato nel database? N. Sì
Richiamabile da altre applicazioni? N. Sì
È possibile restituire i valori delle bind variable? Sì Sì
È possibile restituire i valori della funzione? N. Sì
In grado di accettare parametri? N. Sì

Un blocco anonimo è costituito da una parte dichiarativa facoltativa, una parte eseguibile e uno o più handler di eccezioni facoltativi. Il seguente blocco anonimo di esempio seleziona il cognome di un dipendente in una variabile e stampa il 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;

Oracle AI Database compila il blocco PL/SQL e lo inserisce nello shared pool dell'SGA, ma non memorizza il codice di origine o la versione compilata nel database per il riutilizzo oltre l'istanza corrente. A differenza dei trigger, un blocco anonimo viene compilato ogni volta che viene caricato in memoria. L'istruzione SQL condivisa consente di riutilizzare e condividere blocchi PL/SQL anonimi nello shared pool fino a quando non vengono svuotati dallo shared pool.

Vedere anche: Oracle AI Database Development Guide per ulteriori informazioni sui blocchi PL/SQL anonimi

Costruzioni del linguaggio PL/SQL

I blocchi PL/SQL possono includere una vasta gamma di costrutti di linguaggio PL/SQL diversi.

Questi costrutti includono:

PL/SQL può eseguire istruzioni dynamic SQL il cui testo completo non è noto fino al runtime. Le istruzioni SQL dinamiche vengono memorizzate in stringhe di caratteri inserite o create dal programma in fase di esecuzione. Questa tecnica consente di creare procedure generiche. Ad esempio, è possibile creare una procedura che opera su una tabella il cui nome non è noto fino al runtime.

Vedere anche:

Raccolte e record PL/SQL

Molte tecniche di programmazione utilizzano tipi di raccolta quali array, borse, elenchi, tabelle nidificate, set e alberi.

Per supportare le tecniche di raccolta nelle applicazioni di database, PL/SQL fornisce i tipi di dati TABLE e VARRAY. Questi tipi consentono di dichiarare array associativi, tabelle nidificate e array di dimensioni variabili.

Raccolte

Una raccolta PL/SQL è un gruppo ordinato di elementi, tutti dello stesso tipo.

Ogni elemento ha un subscript che ne ne determina la posizione nella collection. Per creare una raccolta, definire prima un tipo di raccolta, quindi dichiarare una variabile di quel tipo.

Le raccolte funzionano come gli array trovati nella maggior parte dei linguaggi di programmazione di terza generazione. Inoltre, le raccolte possono essere passate come parametri. Pertanto, è possibile utilizzarli per spostare colonne di dati all'interno e all'esterno delle tabelle di database o tra applicazioni lato client e sottoprogrammi memorizzati.

Record

Un record PL/SQL è una variabile composta che può memorizzare valori di dati di diversi tipi, in modo analogo al tipo struct in C, C++ o Java. I record sono utili per contenere i dati delle righe della tabella o di determinate colonne delle righe della tabella.

Si supponga di disporre di dati relativi a un dipendente, ad esempio nome, stipendio e data di assunzione. Questi elementi sono di tipo diverso, ma logicamente correlati. Un record contenente un campo per ogni elemento consente di trattare i dati come un'unità logica.

È possibile utilizzare l'attributo %ROWTYPE per dichiarare un record che rappresenta una riga o una riga di tabella recuperata da un cursore. Con i record definiti dall'utente è possibile dichiarare i propri campi.

Vedere anche: Oracle AI Database PL/SQL Language Reference per informazioni sull'uso dei record PL/SQL

Modalità di esecuzione di PL/SQL

PL/SQL supporta l'esecuzione interpretata e l'esecuzione nativa.

Nell'esecuzione interpretata, il codice sorgente PL/SQL viene compilato in una cosiddetta rappresentazione bytecode. Un computer virtuale portatile implementato come parte di Oracle AI Database esegue questo bytecode.

L'esecuzione nativa offre le migliori prestazioni su unità a uso intensivo di calcolo. In questo caso, il codice sorgente delle unità PL/SQL viene compilato direttamente al codice oggetto per la piattaforma specificata. Questo codice oggetto è collegato a Oracle AI Database.

Il motore PL/SQL definisce, compila ed esegue le unità PL/SQL. Questo motore è un componente speciale di molti prodotti Oracle, tra cui Oracle AI Database. Sebbene molti prodotti Oracle dispongano di componenti PL/SQL, questo argomento descrive in modo specifico le unità PL/SQL che possono essere memorizzate in Oracle AI Database ed elaborate utilizzando il motore PL/SQL di Oracle AI Database. La documentazione di ogni strumento Oracle descrive le funzionalità PL/SQL.

Il grafico seguente illustra il motore PL/SQL contenuto in Oracle AI Database.

Figura 3: Il motore PL/SQL e Oracle AI Database

Descrizione dell'illustrazione cncpt070.gif

L'unità PL/SQL viene memorizzata in un database. Quando un'applicazione chiama una stored procedure, il database carica l'unità PL/SQL compilata nel pool condiviso nell'area globale di sistema (SGA). Gli esecutori delle istruzioni PL/SQL e SQL lavorano insieme per elaborare le istruzioni nella procedura.

È possibile richiamare una stored procedure da un altro blocco PL/SQL, che può essere un blocco anonimo o un'altra stored procedure. Ad esempio, è possibile chiamare una stored procedure da Oracle Forms.

Una procedura PL/SQL in esecuzione su Oracle AI Database può richiamare una funzione o un'operazione esterna scritta nel linguaggio della programmazione C e memorizzata in una libreria condivisa. La routine C viene eseguita in uno spazio di indirizzi separato da quello di Oracle AI Database.

Vedere anche:

Panoramica di Java in Oracle AI Database

Java è emerso come il linguaggio di programmazione orientato agli oggetti di scelta.

Java include le seguenti funzioni:

Il database fornisce ai programmi Java un motore di elaborazione dati dinamico che supporta query complesse e viste multiple di dati. Le richieste client vengono assemblate come query di dati per l'elaborazione immediata. I risultati delle query vengono generati in modo dinamico.

La combinazione di Java e Oracle AI Database ti aiuta a creare applicazioni basate su componenti e incentrate sulla rete che possono essere facilmente aggiornate man mano che le esigenze aziendali cambiano. Inoltre, è possibile spostare applicazioni e data store dal desktop e su reti intelligenti e server incentrati sulla rete. Ancora più importante, è possibile accedere a queste applicazioni e data store da qualsiasi dispositivo client.

La figura seguente mostra una configurazione client/server a due livelli tradizionale in cui i client chiamano le stored procedure Java nello stesso modo in cui chiamano i sottoprogrammi PL/SQL.

Figura 4: Configurazione client/server a due livelli

Descrizione dell'illustrazione cncpt236.gif

Panoramica della Java Virtual Machine (JVM)

JVM è un processore virtuale su cui viene eseguito il codice Java compilato.

Il codice sorgente Java viene compilato in istruzioni per computer di basso livello, note come bytecodes, indipendenti dalla piattaforma. I bytecode Java vengono interpretati tramite JVM in azioni dipendenti dalla piattaforma.

Panoramica di Oracle JVM

Oracle JVM è un ambiente standard compatibile con Java che esegue qualsiasi applicazione Java pura. È compatibile con le specifiche JLS e JVM.

Oracle JVM supporta il formato binario e le API Java standard. Inoltre, Oracle AI Database aderisce alla semantica del linguaggio Java standard, incluso il caricamento dinamico delle classi in fase di runtime.

La figura seguente illustra il modo in cui le applicazioni Oracle Java si trovano al di sopra delle librerie di classe core Java, che si trovano al di sopra di JVM Oracle. Poiché il sistema di supporto Oracle Java si trova all'interno del database, JVM interagisce con le librerie di database anziché interagire direttamente con il sistema operativo.

Figura 5: Struttura dei componenti Java

Descrizione dell'illustrazione cncpt206.gif

A differenza di altri ambienti Java, Oracle JVM è incorporato in Oracle AI Database. Esistono alcune importanti differenze tra JVM Oracle e JVM client standard. Ad esempio, in un ambiente Java standard, è possibile eseguire un'applicazione Java tramite l'interpreter eseguendo il comando seguente nella riga di comando, dove classname è il nome della classe che JVM interpreta per prima:

java classname

Il comando precedente fa sì che l'applicazione venga eseguita all'interno di un processo nel sistema operativo. Tuttavia, se non si utilizza l'interfaccia della riga di comando, è necessario caricare l'applicazione nel database, pubblicare l'interfaccia e quindi eseguire l'applicazione all'interno di un dizionario dati del database.

Vedere anche: Vedere Oracle AI Database Java Developer's Guide per una descrizione delle altre differenze tra JVM Oracle e JVM client standard.

Componenti principali di Oracle JVM

Oracle JVM viene eseguito nello stesso spazio di processo e nello stesso spazio di indirizzamento del kernel del database condividendo i propri heap di memoria e accedendo direttamente ai propri dati relazionali. Questo design ottimizza l'uso della memoria e aumenta il throughput.

Oracle JVM fornisce un ambiente di runtime per gli oggetti Java. Supporta completamente le strutture di dati Java, l'invio dei metodi, la gestione delle eccezioni e i thread a livello di linguaggio. Supporta anche tutte le librerie di classe Java di base, tra cui java.lang, java.io, java.net, java.math e java.util.

La figura seguente mostra i componenti principali di Oracle JVM.

Figura 6: Componenti principali di Oracle JVM

Descrizione dell'illustrazione cncpt254.gif

Oracle JVM incorpora lo spazio di nomi Java standard negli schemi di database. Questa funzione consente ai programmi Java di accedere agli oggetti Java memorizzati in Oracle AI Database e agli application server in tutta l'azienda.

Inoltre, Oracle JVM è strettamente integrato con l'architettura di memoria condivisa scalabile del database. I programmi Java utilizzano le chiamate, le sessioni e le vite degli oggetti in modo efficiente senza l'intervento dell'utente. Di conseguenza, è possibile ridimensionare la JVM Oracle e i business object Java di livello intermedio, anche quando hanno uno stato lungo la sessione.

Vedere anche: Oracle AI Database Java Developer's Guide per una descrizione dei componenti principali di Oracle JVM

Ambiente di programmazione Java

Oracle offre agli sviluppatori di applicazioni aziendali una soluzione Java end-to-end per la creazione, la distribuzione e la gestione di applicazioni Java.

La soluzione è composta da interfacce programmatiche lato client e lato server, strumenti per supportare lo sviluppo Java e una Java Virtual Machine integrata con Oracle AI Database. Tutti questi prodotti sono compatibili con gli standard Java.

L'ambiente di programmazione Java è costituito dalle seguenti funzioni aggiuntive:

Procedure memorizzate Java

Una procedura memorizzata Java è un metodo Java pubblicato in SQL e memorizzato nel database.

Come un sottoprogramma PL/SQL, una procedura Java può essere richiamata direttamente con prodotti come SQL*Plus o indirettamente con un trigger. È possibile accedervi da qualsiasi client-OCI, precompilatore o JDBC di Oracle Net.

Per pubblicare i metodi Java, si scrivono le specifiche delle chiamate, che mappano i nomi dei metodi Java, i tipi di parametri e restituiscono i tipi alle rispettive controparti SQL. Quando viene chiamata dalle applicazioni client, una stored procedure Java può accettare argomenti, fare riferimento a classi Java e restituire i valori dei risultati Java.

Applicazioni che richiamano il metodo Java facendo riferimento al nome della specifica di chiamata. Il sistema runtime cerca la definizione della specifica di chiamata nel dizionario dati Oracle ed esegue il metodo Java corrispondente.

Inoltre, puoi utilizzare Java per sviluppare programmi potenti indipendentemente da PL/SQL. Oracle AI Database fornisce un'implementazione completamente conforme del linguaggio di programmazione Java e della JVM.

Vedi anche: Oracle AI Database Java Developer's Guide spiega come scrivere stored procedure in Java, come accedervi da PL/SQL e come accedere alla funzionalità PL/SQL da Java

Integrazione di Java e PL/SQL

È possibile chiamare i programmi PL/SQL esistenti da programmi Java e Java da PL/SQL. Questa soluzione protegge e sfrutta il tuo codice PL/SQL e Java.

Oracle AI Database offre JDBC per l'accesso ai dati SQL da Java sia sul client che sul server.

Driver JDBC

JDBC è un protocollo di accesso al database che consente di connettersi a un database ed eseguire istruzioni e query SQL al database.

Le librerie di classe Java di base forniscono una sola API JDBC, java.sql. Tuttavia, JDBC è progettato per consentire ai fornitori di fornire driver che offrono la specializzazione necessaria per un determinato database. Oracle fornisce i driver JDBC distinti mostrati nella tabella seguente.

Driver JDBC tabella 2

Driver Descrizione
Driver Thin JDBC È possibile utilizzare il driver Thin JDBC per scrivere applicazioni e applet Java puri che accedono ai dati Oracle SQL. Il driver JDBC Thin è particolarmente adatto per le applicazioni e le applet basate sul Web, poiché è possibile scaricarlo dinamicamente da una pagina Web, simile a qualsiasi altra applet Java.
Driver OCI JDBC Il driver JDBC OCI accede al codice nativo specifico di Oracle, ovvero al codice non Java e alle librerie sul client o sul livello intermedio, fornendo un incremento delle prestazioni rispetto al driver JDBC Thin, a costo di un'installazione lato client e di dimensioni notevolmente maggiori.
Driver interno lato server JDBC Oracle AI Database utilizza il driver interno lato server quando il codice Java viene eseguito sul server. Consente alle applicazioni Java in esecuzione in JVM Oracle sul server di accedere ai dati definiti localmente, ovvero ai dati sullo stesso sistema e nello stesso processo, con JDBC. Offre un miglioramento delle prestazioni, grazie alla sua capacità di utilizzare direttamente le librerie Oracle RDBMS di base, senza il sovraccarico di una connessione di rete che interviene tra il codice Java e i dati SQL. Supportando la stessa interfaccia Java-SQL sul server, Oracle AI Database non richiede di rielaborare il codice durante la distribuzione.

Vedere anche:

Panoramica di JavaScript in Oracle AI Database

JavaScript è uno dei linguaggi di programmazione più popolari oggi. Oracle AI Database distribuito su Linux x86-64 o Linux aarch64 aggiunge JavaScript alla lista dei linguaggi supportati per lo sviluppo lato server.

È possibile memorizzare moduli di JavaScript nel database, elaborando i dati in cui vivono offrendo miglioramenti potenzialmente significativi rispetto agli approcci di sviluppo lato client. JavaScript viene eseguito da Multilingual Engine (MLE).

Gli sviluppatori possono scegliere tra l'esecuzione di codice JavaScript standalone e la memorizzazione del codice JavaScript in modo nativo nel database come moduli.

Memorizzazione della logica aziendale come moduli nel database

Proprio come con lo sviluppo lato client JavaScript, il codice può essere memorizzato insieme sotto forma di un modulo.

Gli sviluppatori con background PL/SQL possono pensare a un modulo JavaScript come l'equivalente di un package body PL/SQL, ma scritto in JavaScript. Le funzioni dichiarate in un modulo possono essere contrassegnate per essere esportate o mantenute private.

JavaScript in Oracle AI Database aderisce allo standard ECMAScript 2023 e offre agli sviluppatori una vasta gamma di possibilità per memorizzare la business logic all'interno del database.

Nota:

Fare riferimento anche a quanto riportato di seguito.

Di seguito è riportato un esempio di creazione di un modulo 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;
}
/

Il modulo JavaScript, noto anche come modulo MLE, è ora memorizzato nello schema dell'utente. La sua unica funzione, string2obj(), può essere esposta a SQL e PL/SQL creando una specifica di chiamata. Le specifiche di chiamata sono program unit PL/SQL che consentono di chiamare il codice JavaScript ovunque sia possibile chiamare SQL e PL/SQL. La specifica di chiamata per string2obj() può essere scritta come segue:

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

Con la funzione creata può essere chiamata da 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.

Esecuzione dinamica del codice JavaScript

Gli sviluppatori di framework e chiunque desideri eseguire codice JavaScript standalone senza la necessità di memorizzare il codice nel database possono utilizzare il pacchetto DBMS_MLE e le relative sottoprogrammi.

Oracle Application Express e Database Actions, ad esempio, integrano DBMS_MLE, nascondendo il fatto che un package PL/SQL viene richiamato sotto le coperte.

Rispetto ai moduli MLE, l'uso di DBMS_MLE rende più difficile scrivere intere applicazioni. Ad esempio, è più difficile dividere logicamente un'applicazione in entità separate. La funzione di debug post-esecuzione richiede moduli che rendono più difficile la risoluzione dei problemi negli snippet di codice. Le pipeline di integrazione continua (CI, Continuous Integration) possono anche avere difficoltà nel fornire codice PL/SQL e JavaScript nello stesso file. Allo stesso modo, c'è un potenziale problema con il tuo ambiente di sviluppo integrato (IDE) poiché la maggior parte avrà difficoltà a lavorare sia con PL/SQL che con JavaScript nella stessa finestra.

Nota:

Fare riferimento anche a quanto riportato di seguito.

Stored procedure JavaScript in linea

Le specifiche di chiamata MLE in linea incorporano il codice JavaScript direttamente nelle DDL CREATE FUNCTION e CREATE PROCEDURE.

Se si desidera implementare rapidamente funzionalità semplici utilizzando JavaScript, le specifiche di chiamata MLE in linea possono essere una buona scelta. Con questa opzione, non è necessario distribuire un modulo separato contenente il codice JavaScript. Piuttosto, la funzione JavaScript è integrata nella definizione della specifica di chiamata stessa.

La clausola MLE LANGUAGE viene utilizzata per specificare che la funzione viene implementata utilizzando JavaScript. La stringa che segue il nome della lingua viene considerata come il corpo di una funzione JavaScript che implementa la funzionalità della specifica di chiamata. Quando il codice viene eseguito, i parametri PL/SQL vengono convertiti automaticamente nel tipo JavaScript predefinito e passati alla funzione JavaScript come parametri con lo stesso nome. Si noti che i nomi dei parametri senza virgolette vengono mappati ai nomi JavaScript con lettere maiuscole. Il valore restituito da una funzione JavaScript viene convertito nel tipo restituito della specifica di chiamata PL/SQL, così come con le specifiche di chiamata per i moduli MLE.

Nota:

Fare riferimento anche a quanto riportato di seguito.

Panoramica dei trigger

Un trigger di database è una program unit memorizzata compilata, scritta in PL/SQL, Java o JavaScript, che Oracle Database richiama ("fuochi") in modo automatico in determinate situazioni.

Un trigger si attiva ogni volta che si verifica una delle seguenti operazioni:

  1. Istruzioni DML presenti in una determinata tabella o vista, rilasciate da qualsiasi utente

    Le istruzioni DML modificano i dati negli oggetti dello schema. Ad esempio, l'inserimento e l'eliminazione di righe sono operazioni DML.

  2. Istruzioni DDL eseguite da un determinato utente o da un qualsiasi utente

    Le istruzioni DDL definiscono gli oggetti dello schema. Ad esempio, la creazione di una tabella e l'aggiunta di una colonna sono operazioni DDL.

  3. Eventi del database

    Login utente o disconnessione, errori e avvio o arresto del database sono eventi che possono richiamare i trigger.

I trigger sono oggetti di schema simili ai sottoprogrammi, ma diversi per la modalità di richiamo. Un sottoprogramma viene eseguito in modo esplicito da un utente, un'applicazione o un trigger. I trigger vengono richiamati in modo implicito dal database quando si verifica un evento di attivazione.

Vedere anche:

Vantaggi dei trigger

L'uso corretto dei trigger consente di creare e distribuire applicazioni più solide e che utilizzano il database in modo più efficace.

È possibile utilizzare i trigger per:

È possibile utilizzare i trigger per applicare regole business di basso livello comuni a tutte le applicazioni client. Ad esempio, diverse applicazioni possono accedere alla tabella employees. Se un trigger in questa tabella garantisce il formato dei dati inseriti, la business logic non deve essere riprodotta in ogni client. Poiché il trigger non può essere aggirato dall'applicazione, la logica aziendale nel trigger viene utilizzata automaticamente.

È possibile utilizzare sia i trigger che i vincoli di integrità per definire e applicare qualsiasi tipo di regola di integrità. Tuttavia, Oracle consiglia di utilizzare solo i trigger per applicare regole aziendali complesse non definibili utilizzando un vincolo di integrità.

L'uso eccessivo di trigger può comportare interdipendenze complesse che possono essere difficili da mantenere in un'applicazione di grandi dimensioni. Ad esempio, quando viene richiamato un trigger, un'istruzione SQL all'interno della relativa azione trigger può potenzialmente attivare altri trigger, con conseguenti trigger a catena in grado di produrre effetti non previsti.

Vedere anche:

automaticamente in certe situazioni.")

Tipi di trigger

I trigger possono essere classificati in base ai loro mezzi di invocazione e al tipo di azioni che eseguono.

Oracle Database supporta i tipi di trigger riportati di seguito.

Vedere anche:

automaticamente in certe situazioni.")

Tempistica per i trigger

È possibile definire la tempistica del trigger, ovvero se l'azione del trigger deve essere eseguita prima o dopo l'istruzione di attivazione.

Un trigger semplice è un singolo trigger in una tabella che consente di specificare azioni per esattamente uno dei seguenti punti temporali:

Per i trigger di istruzione e riga, un trigger BEFORE può migliorare la sicurezza e abilitare le regole business prima di apportare modifiche al database. Il trigger AFTER è ideale per le azioni di log.

Un trigger composto può essere avviato in più punti temporali. I trigger composti aiutano a programmare un approccio in cui le azioni implementate per vari punti temporali condividono dati comuni.

Vedere anche: Oracle AI Database PL/SQL Language Reference per informazioni sui trigger composti

automaticamente in certe situazioni.")

Creazione delle spettanze

L'istruzione CREATE TRIGGER crea o sostituisce un trigger di database.

Un trigger PL/SQL ha il seguente formato sintattico generale:

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

Un trigger PL/SQL dispone dei seguenti componenti di base:

Vedere anche:

automaticamente in certe situazioni.")

Esempio: istruzione CREATE TRIGGER

In questo esempio viene creato un trigger che viene attivato quando un'istruzione INSERT, UPDATE o DELETE viene eseguita in una tabella degli elementi riga.

Si supponga di creare le tabelle orders e lineitems con le istruzioni seguenti. La tabella orders contiene una riga per ogni ordine univoco, mentre la tabella lineitems contiene una riga per ogni elemento di un ordine.

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

L'istruzione seguente crea un trigger di esempio che aggiorna automaticamente la tabella orders con il numero di elementi in un ordine:

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

In lineitems_trigger, l'istruzione di attivazione è un INSERT, UPDATE o DELETE nella tabella lineitems. Nessuna limitazione di attivazione esistente. Il trigger viene richiamato per ogni riga modificata. Il trigger ha accesso ai valori di colonna vecchi e nuovi della riga corrente interessata dall'istruzione di attivazione. Esistono due nomi di correlazione per ogni colonna della tabella in fase di modifica: il vecchio valore (:old) e il nuovo valore (:new). Se una sessione aggiorna o inserisce righe in lineitems per un ordine, dopo l'azione il trigger calcola il numero di elementi in questo ordine e aggiorna la tabella orders con il conteggio.

Esempio: richiamo di un trigger a livello di riga

In questo scenario, un cliente avvia due ordini e aggiunge e rimuove le voci riga dagli ordini.

Lo scenario si basa sul TRIGGER creato in Esempio: istruzione CREATE TRIGGER.

Scenario trigger a livello di riga tabella 3

Istruzione SQL Istruzione SQL attivata Descrizione
SQL> INSERT INTO orders
 (order_id) VALUES (78);

  1 row created. 
 

Il cliente crea un ordine con ID 78. A questo punto il cliente non ha articoli nell'ordine.

Poiché non viene eseguita alcuna azione sulla tabella lineitems, il trigger non viene richiamato.

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

  1 row created. 
 

Il cliente crea un ordine separato con ID 92. A questo punto il cliente non ha articoli nell'ordine.

Poiché non viene eseguita alcuna azione sulla tabella lineitems, il trigger non viene richiamato.

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;

Il cliente aggiunge un articolo all'ordine 78.

Il comando INSERT richiama il trigger. Il rendiconto attivato aumenta il conteggio delle voci riga per l'ordine 78 da 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; 

Il cliente aggiunge un articolo aggiuntivo all'ordine 78.

Il comando INSERT richiama il trigger. L'istruzione attivata aumenta il conteggio delle voci riga per l'ordine 78 da 1 a 2.

SQL> SELECT * FROM orders;

  ORDER_ID LINE_ITEMS_COUNT
 --------- ----------------
 78 2
 92 0
  Il cliente esegue una query sullo stato dei due ordini. L'ordine 78 contiene due elementi. L'ordine 92 non contiene articoli.
SQL> SELECT * FROM lineitems;

  ORDER_ID SEQ_NO
 ---------- ----------
 78 1
 78 2
  Il cliente esegue una query sullo stato delle voci riga. Ogni articolo è identificato in modo univoco dall'ID ordine e dal numero di sequenza.
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;

Il cliente sposta le voci riga dell'ordine 78 nell'ordine 92.

L'istruzione UPDATE modifica 2 righe nelle tabelle lineitems, richiamando il trigger una volta per ogni riga.

Ogni volta che il trigger viene richiamato, vengono soddisfatte entrambe le condizioni IF nel trigger. La prima condizione aumenta il conteggio per l'ordine 92, mentre la seconda condizione riduce il conteggio per l'ordine 78. Pertanto, vengono eseguite quattro istruzioni UPDATE totali.

SQL> SELECT * FROM orders;

  ORDER_ID LINE_ITEMS_COUNT
 --------- ----------------
 78 0
 92 2
  Il cliente esegue una query sullo stato dei due ordini. L'effetto netto è che il conteggio delle voci per l'ordine 92 è aumentato da 0 a 2, mentre il conteggio per l'ordine 78 è diminuito da 2 a 0.
SQL> SELECT * FROM lineitems;

  ORDER_ID SEQ_NO
 ---------- ----------
 92 1
 92 2
  Il cliente esegue una query sullo stato delle voci riga. Ogni articolo è identificato in modo univoco dall'ID ordine e dal numero di sequenza.
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;

Il cliente ora rimuove tutte le voci riga da tutti gli ordini.

L'istruzione DELETE modifica 2 righe nelle tabelle lineitems, richiamando il trigger una volta per ogni riga. Per ogni richiamo del trigger, viene soddisfatta una sola condizione IF nel trigger. Ogni volta che la condizione diminuisce il conteggio per l'ordine 92 di 1. Pertanto, vengono eseguite due istruzioni UPDATE totali.

SQL> SELECT * FROM orders;

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

  SQL> SELECT * FROM lineitems;

  no rows selected
 

Il cliente esegue una query sullo stato dei due ordini. Nessun ordine contiene voci riga.

Il cliente esegue inoltre una query sullo stato delle voci riga. Non esistono articoli.

Esecuzione dei trigger

Oracle Database esegue un trigger internamente utilizzando gli stessi passi dell'esecuzione del sottoprogramma.

L'unica differenza sottile è che un account utente ha il diritto di attivare un trigger se ha il privilegio di eseguire l'istruzione di attivazione. Con questa eccezione, il database convalida ed esegue i trigger allo stesso modo dei sottoprogrammi memorizzati.

Vedere anche: Oracle AI Database PL/SQL Language Reference per ulteriori informazioni sull'esecuzione dei trigger

automaticamente in certe situazioni.")

Memorizzazione dei trigger

Oracle Database memorizza i trigger PL/SQL in formato compilato in uno schema di database, proprio come le stored procedure PL/SQL.

Quando si esegue il commit di un'istruzione CREATE TRIGGER, il codice PL/SQL compilato viene memorizzato nel database. Lo shared pool rimuove il codice sorgente del trigger PL/SQL.

L'immagine riportata di seguito mostra un'applicazione di database con istruzioni SQL che richiamano implicitamente i trigger PL/SQL. I trigger vengono memorizzati separatamente dalle tabelle associate.

Figura 7: Trigger

Descrizione dell'illustrazione cncpt076.gif

I trigger Java vengono memorizzati nello stesso modo dei trigger PL/SQL. Tuttavia, un trigger Java fa riferimento a un codice Java compilato separatamente con un'istruzione CALL. Pertanto, la creazione di un trigger Java implica la creazione di codice Java e la creazione del trigger che fa riferimento a questo codice Java.

Vedere anche: Oracle AI Database PL/SQL Language Reference per informazioni sulla compilazione e la memorizzazione dei trigger

automaticamente in certe situazioni.")