Manuale per la programmazione Tivoli Service Desk 6.0 Developer's Toolkit Script

Capitolo 8: Funzioni di gestione del database

Ritorna all'Indice analitico


Introduzione

Developer's Toolkit è stato specificamente realizzato per semplificare la creazione delle applicazioni del database client/server. Per questo motivo, il linguaggio TSD Script contiene una serie di istruzioni dedicate all'interazione con i database SQL.

L'interfaccia SQL del TSD Script è una parte intrinseca del linguaggio. L'interfaccia SQL sfrutta la flessibilità dei tipi RECORD e LIST del TSD Script. Inoltre, le istruzioni SQL TSD Script offrono la concorrenza passiva incorporata per lo sviluppo di applicazioni affidabili per più utenti.

Un'altra caratteristica particolarmente utile è la possibilità di utilizzare le fetch a vettore con Oracle. La fetch a vettore riduce sensibilmente il tempo necessario per interrogare un database.

Panoramica SQL

SQL, o Structured Query Language, è un linguaggio standard utilizzato per:

Poiché questo manuale non è stato concepito come manuale d'istruzione SQL, è utile avere una certa conoscenza della sintassi SQL prima di leggere questo capitolo.

Database supportati

Di seguito vengono riportati i database (conosciuti anche come origini) supportati dal Developer's Toolkit:

Supporto SQL in Developer's Toolkit

Developer's Toolkit e il linguaggio TSD Script supportano diverse istruzioni SQL e database SQL utilizzati per sviluppare le applicazioni client/server.

Istruzioni SQL non supportate con driver diretti

Alcune istruzioni SQL non vengono supportate da driver diretti di Oracle, Sybase/SQLServer e Informix. Le istruzioni vengono elencate nella tabella seguente.

Questa istruzione... E' supportata solo in...
SQLDeleteCurrent DB2/2
SQLGetCursorName DB2/2
SQLUpdateCurrent DB2/2

Nota: SQLUpdateCurrent e SQLDeleteCurrent richiedono l'utilizzo delle istruzioni nidificate e devono essere utilizzate il meno possibile. Le istruzioni sono generalmente considerate obsolete e non sono largamente supportate.

Attributi e descrizioni delle origini dati

Questa sezione descrive gli attributi disponibili al momento della configurazione dell'origine dati. Gli attributi controllano la funzionalità di un layer di database nel Developer's Toolkit.

Nota: Questi attributi non sono necessari quando si utilizza l'Editor di configurazione SQL per configurare l'origine dati. Consultare la sezione Connessione dell'applicazione ad un database che verrà trattata in seguito in questo capitolo.

Definizione dell'origine di database

Un'origine di database è una raccolta di informazioni identificata da un nome specifico. Viene utilizza per definire il database e la connessione del database.

Nota: La scelta del nome origine è dell'utente. TSD Script non richiede e non riconosce i nomi predefiniti. TSD Script richiede i nomi origine dei dati che non iniziano con un numero. Tuttavia, le applicazioni scritte con TSD Script prevedono determinati nomi origine. Ad esempio, il programma Tivoli Problem Management prevede "ADVISOR" come nome origine dei dati. Consultare la documentazione dell'applicazione per ognuno di questi requisiti.

Attributi origine

Quando si configura un'origine dati, gli attributi, o le caratteristiche, per quell'origine dati vengono elencati utilizzando la sintassi ATTRIB=VALUE. Gli attributi possibili sono:

I seguenti attributi generalmente non vengono utilizzati:

TSD Script utilizza automaticamente i default per ogni DBMS da esso supportato. Questi attributi vengono utilizzati solo per sovrascrivere i default in casi speciali, come ad esempio un'istanza di sensibilità al maiuscolo e minuscolo.

Nella maggior parte dei casi, non è necessario sovrascrivere il default. Molti di questi attributi interessano le caratteristiche avanzate in un database e devono essere modificati solo dall'amministratore del database.

CASE_CONVERSION

Se si utilizza un database con nomi di oggetti sensibili al maiuscolo e minuscolo, è necessario codificare le query con il caso appropriato. Se si creano tutti gli oggetti del database nello stesso caso, (tutti maiuscoli o tutti minuscoli) il TSD Script può convertire tutti i nomi degli oggetti nel caso che si preferisce. I valori possibili per questa voce di attributo sono: UPPER, LOWER o NONE. Il valore di default, qualora questa voce non fosse presente, è NONE.

Nota: Il TSD Script conserva sempre il caso dei literal di stringa citati tra virgolette all'interno di una query.

CASE_SENSITIVE

Questa voce si riferisce al modo in cui il DBMS tratta il caso relativo agli oggetti di database. Gli oggetti di database sono i nomi di tabella, i nomi delle colonne e così via. Se il valore è TRUE, il TSD Script conserva il caso di tutti i nomi degli oggetti (a meno che non sia impostata la voce CASE_CONVERSION). Se la voce CASE_SENSITIVE non è presente, il valore di default è FALSE.

COLUMN_DEFINITION_TABLE

Le seguenti voci possono essere utilizzate per sovrascrivere i nomi delle colonne previste dal TSD Script nella vista del catalogo della colonna di default.

Colonna Default
COL_NAME_COLUMN NAME
COL_REMARKS_COLUMN REMARKS
COL_LENGTH_COLUMN LENGTH
COL_SCALE_COLUMN SCALE
COL_TYPE_COLUMN COLTYPE
COL_NULLS_COLUMN NULLS
COL_TBNAME_COLUMN TBNAME
COL_TBCREATOR_COLUMN TBCREATOR

Nota: Il TSD Script utilizza automaticamente i default per ogni DBMS da esso supportato. Tuttavia, questa voce non viene utilizzata in circostanze normali. Questa voce deve essere utilizzata per sovrascrivere il default in casi speciali. Questa voce contiene la tabella dizionario/catalogo delle colonne o il nome della vista. Poiché i prodotti Tivoli forniscono una vista "involucro" per coerenza, il valore di default è sempre SAI_SYSCOLUMNS.

COMMIT_SELECTS

Questa voce è disponibile solo se MANUAL_COMMITS è TRUE. Se applicabile, l'impostazione di COMMIT_SELECTS di default è TRUE.

Impostare la voce COMMIT_SELECTS su TRUE se si desidera la sincronizzazione automatica dopo la selezione.

DATE_FORMAT

DATE_FORMAT è il formato della data previsto per l'origine dei dati (DBMS). Per la maggior parte dei sistemi, il formato della data di default è: mm/gg/aaaa. Il formato della data di default per Oracle è gg-MES-aa.

E' possibile personalizzare un formato data specificando il formato del giorno, mese, anno e separatore. Mentre viene supportata la maggior parte delle combinazioni di queste voci, esistono alcune eccezioni che non sono supportate. Ad esempio, aaaammgg è supportata, mentre aaaaggmm non lo è.

Specifica del giorno

E' possibile posizionare degli zeri iniziali sia per i giorni che per i mesi. Per posizionare gli zeri iniziali sui giorni, specificare sono una "g" nella data.

Nota: Se si posizionano gli zeri iniziali per i giorni, è necessario inoltre posizionarli per i mesi. Ad esempio, mm/g/aaaa non è accettato.

Esempio Risultato
mm/gg/aaaa 07/08/1999
m/g/aaaa 7/8/1999

Specifica del mese

E' possibile specificare il mese inserendo il numero del mese nell'anno del calendario (1=Gennaio) oppure inserendo il nome del mese. Per specificare il mese secondo i numeri, utilizzare "MM." Per posizionare gli zeri iniziali nei numeri del mese, utilizzare "M." Per specificare il mese secondo il nome, oppure con un'abbreviazione, utilizzare "Mese" o "Mes."
Gli specificativi del nome del mese (sia Mese che Mes) sono sensibili al maiuscolo e minuscolo. Gli specificativi del numero del mese (MM e M) non sono sensibili al maiuscolo e minuscolo.

Nota: Se si posizionano degli zeri iniziali per i mesi, è necessario posizionarli anche per i giorni.

Esempio Risultato
MM 08
M 8
Mese Agosto
Mes Ago
MESE AGOSTO
MES AGO

Specifica dell'anno

Quando si specifica l'anno, è possibile specificare l'anno completo o le ultime due cifre dell'anno.

Attenzione: Tivoli informa che, per le date relative all'anno 2000, si utilizzeranno i numeri completi a quattro cifre.

Esempio Risultato
mm/gg/aaaa 07/08/1999
mm/gg/aa 07/08/99

Separatori

E' possibile utilizzare i seguenti separatori per formattare le date:

Tipo di separatore Esempio Risultato
nessuno aaaammgg 19990626
punti mm.gg.aaaa 06.26.1999
trattini gg-mm-aaaa 26-06-1999
barre mm/gg/aaaa 06/26/1999

DBMS

Per i driver ODBC, si richiede un'elenco DBMS nel file di configurazione SQL. I possibili database che possono essere elencati come voci DBMS= sono:

DEFAULT

Se il valore è TRUE, questa origine dati viene considerata l'origine dati di default al momento della connessione. Viene accettata una sola voce DEFAULT per il file di configurazione SQL. Il valore di default qualora questa voce non fosse presente è FALSE.

DRV

Questo è il nome del driver DBMS e viene richiesto in fase di connessione.

DSN

Questo attributo elenca il nome origine dati per il file di configurazione SQL (solo ODBC).

MANUAL_COMMITS

Questa voce è disponibile per le interfacce dirette; deve essere impostato su TRUE se si desidera che il controllo della transazione sia gestito al livello del TSD Developer's Toolkit.

MULTIPLE_CONNECT

Questa voce viene impostata su TRUE se il DBMS supporta più connessioni simultanee.

MULTIPLE_CONNECT_REQUIRED

Impostare questa voce su TRUE se il DBMS richiede più connessioni per eseguire più di una istruzione aperta alla volta (ad esempio, loop select/fetch nidificati). Il valore di default per Sybase e SQLServer è TRUE. E' FALSE per tutti gli altri database.

Nota: Se necessario, il TSD Script apre altre connessioni.

QUAL

Questo è l'identificativo utilizzato per l'accesso alle tabelle. L'SQL memorizza il proprietario/creatore della tabella nella definizione della tabella. Questo nome proprietario/creatore viene considerato come l'identificativo della tabella. Una combinazione del nome della tabelle e dell'identificativo deve essere utilizzata solo per identificare una tabella all'interno di un database.

SYSQUAL

Questa voce contiene il nome dell'identificativo necessario per accedere alle viste/tabelle del catalogo del sistema. Poiché tutti i prodotti Tivoli forniscono una vista "involucro" per coerenza, il valore di default è lo stesso dell'identificativo corrente (nella stringa di connessione di default).

TABLE_DEFINITION_TABLE

Questa voce contiene la tabella dizionario/catalogo della tabella o il nome della vista. Poiché tutti i prodotti Tivoli forniscono una vista "involucro" per coerenza, il valore di default è sempre SAI_SYSCOLUMNS.

Le cinque voci seguenti possono essere utilizzate per sovrascrivere i nomi delle colonne previste dal TSD Script nella vista del catalogo della tabella di default:

Default del nome del separatore

TAB_NAME_COLUMN NAME
TAB_REMARKS_COLUMN REMARKS
TAB_TYPE_COLUMN TYPE
TAB_CREATOR_COLUMN CREATOR
TAB_COLCOUNT_COLUMN COLCOUNT (per DB2/2 e SQLBase)

TIME_FORMAT

Questa voce è il formato ora previsto per l'origine dei dati. Il valore di default per tutte le voci DBMS è hh:mm:ss. Mentre la maggior parte degli identificativi del formato dell'ora sono validi, alcuni non lo sono. Ad esempio, hh:mm:ss è supportato, mentre mm:hh:ss non lo è.

Consultare la sezione in Riferimento Lingua del TSD 6.0 Script nell'istruzione TimeFormat per ulteriori informazioni sui formati dell'ora validi.


Tempo diviso in 24 ore

Per default, l'ora viene specificata secondo la suddivisione in 24 ore. Per specificare il tempo in 12 ore, inserire il suffisso AM_PM:

Esempio Risultato
hh:mmAM_PM 09:08 PM
hh:mm 21:08

Formati ora sensibili al maiuscolo e minuscolo

L'identificativo del formato non è sensibile al maiuscolo e minuscolo. Ad esempio hh:mm:ss equivale a HH:MM:SS

Inserimento degli zeri iniziali

Per inserire degli zeri iniziali, specificare una sola h, m e s. Ad esempio:

Esempio Risultato
hh:mm:ss 08:35:09
h:m:s 8:35:9

Nota: Se si sceglie di inserire degli zeri iniziali, è necessario inserirli nelle ore, nei minuti e nei secondi.

Specifica dei secondi

Per specificare i secondi, inserire la designazione ss. E' possibile, facoltativamente, omettere i secondi.

Esempio Risultato
hh:mm:ss 08:35:09
h:m 8:35

Separatori

E' possibile specificare i due punti o i punti per formattare l'identificativo dell'ora:

Tipo di separatore Esempio Risultato
nessuno hhmmss 121604
punti hh.mm.ss 12.16.04
due punti hh:mm:ss 12:16:04

UPPERCASE_FUNCTION

Questa voce contiene il nome della funzione specifico per DBMS utilizzato per convertire le colonne in una query in maiuscolo (utilizzato da SQLCreateSearchString). I valori di default sono:

Connessione dell'applicazione ad un database

La connessione o il collegamento ad un database è comune a tutti i DBMS SQL. I mezzi per collegarsi variano a seconda del database utilizzato. Ad esempio:

Per mascherare queste differenze, il TSD Script fornisce una serie di servizi di connessione che utilizza l'istruzione SQLCommand. SQLCommand consente di utilizzare i comandi esterni per le informazioni sulla connessione specifiche per DBMS in un file di configurazione SQL. Questo semplifica il codice dell'applicazione e lo rende portabile.

Nome del file di configurazione SQL

Il nome di default del file di configurazione SQL del Developer's Toolkit è sai_sql.cfg. Il Developer's Toolkit inquiry un file chiamato sai_sql.cfg nella sottodirectory CFG della directory root SAI.

E' possibile sovrascrivere il nome del file che il TSD Script inquiry impostando una variabile di ambiente denominata SAISQLCFG che contenga un nome file diverso. Il valore nella variabile di ambiente SAISQLCFG ha la precedenza sul percorso derivato da SAI_ROOT, se entrambi sono impostati. Viene restituito un errore se il file non viene trovato.

Il file di configurazione SQL viene diviso in sezioni che descrivono un'origine dati. Si consideri un'origine dati come DBMS con la quale si sta lavorando. Solitamente, le origini dati corrispondono ai server di database fisici, sebbene l'idea possa essere estesa in modo da comprendere le origini logiche all'interno di un server (un'origine per database, ad esempio).

Altre ubicazioni per le istruzioni sulla configurazione

Il Developer's Toolkit fornisce un numero di interfacce di database dirette che l'utente può utilizzare, basate sui requisiti del proprio database. Queste interfacce di database dirette costituiscono il metodo di default della connettività del database per il Developer's Toolkit.

Se si desidera utilizzare ODBC, invece che le interfacce di database dirette, è possibile trovare ulteriori informazioni sui driver ODBC nell'Appendice A "Configurazioni ODBC" nella Guida per l'installazione Tivoli Service Desk 6.0.

Se si utilizzano le interfacce di database dirette di default del Developer's Toolkit, consultare il "Processo di configurazione" nel Manuale per l'installazione Tivoli Service Desk 6.0 per le istruzioni complete relative alla configurazione e al test.

Esempio di configurazione del database

Per aggiungere un client database per l'utilizzo iniziale, seguire i seguenti passi:

  1. Dal gruppo di programmi Developer's Toolkit, scegliere l'Editor di configurazione SQL.
    Risultato: Viene visualizzata la casella di dialogo Editor di configurazione SQL.

I seguenti componenti sono presenti nella casella di dialogo Editor di configurazione SQL:

  1. Se non è già stato immesso nelle caselle di testo File, immettere il percorso, l'unità drive e il nome file per il file sai_sql.cfg (l'ubicazione di default è c:\sai\cfg\sai_sql.cfg) e scegliere Aggiungi.
    Risultato: Si è creato un file di configurazione ed è stata aggiunta la prima origine dati. Viene visualizzata la casella di dialogo Selezione driver.
  2. Selezionare il driver di database che si desidera utilizzare dall'elenco dei pallini e selezionare OK.
    Risultato: Viene visualizzata la casella di dialogo Impostazione origine.
  3. Immettere le informazioni rilevanti per il proprio client di database nelle caselle di testo appropriate e selezionare OK o Avanzato.

Risultato: Se si sceglie OK, la procedura viene terminata. Se si sceglie Avanzato dalla casella di dialogo Impostazione origine, viene visualizzata la casella di dialogo Impostazioni opzioni avanzate.

  1. Selezionare Aggiungi.
    Risultato: Viene visualizzata la caselle di dialogo Selezione opzioni.
  2. Selezionare l'opzione che si desidera configurare e scegliere Seleziona.
    Risultato: Viene visualizzata la casella di dialogo Immetti valore opzione.
  3. Nella casella di dialogo Immetti valore opzione, immettere l'opzione dell'attributo e il valore dell'attributo per l'origine che si sta configurando. Per ulteriori informazioni, scegliere ?.
  4. Scegliere OK e uscire dall'Editor di configurazione SQL.

Test della connessione al client di database

Dopo aver aggiunto una nuova connessione del database, è necessario testare la connessione per assicurarsi che funzioni correttamente. Completare questi passi per testare una connessione del database:

  1. Dal gruppo di programmi Developer's Toolkit, scegliere l'Editor di configurazione SQL.
  2. Selezionare l'origine dati che si desidera testare e scegliere Testa connessione.Se la funzione Testa connessione restituisce un messaggio di errore, verificare i parametri immessi nella casella di dialogo Impostazione origine o testare la connessione.

Informazioni sulla connessione nel file di configurazione SQL

Esiste un potenziale problema relativo alla riservatezza se si conservano gli ID e le password nel file di configurazione SQL. Potrebbero inoltre presentarsi delle difficoltà se si conservano le informazioni specifiche della connessione per più di un utente poiché tutti gli utenti possono facilmente accedere al file e le password memorizzate non sono codificate per default.
L'utente deve selezionare la codifica utilizzando l'Editor di configurazione SQL. Per ulteriori informazioni consultare Esempio di configurazione del database in questo manuale.

Il TSD Script dispone di un metodo semplice che fornisce informazioni specifiche per la connessione nell'istruzione della connessione stessa:

ret := SQLCommand('CONNECT SOURCE=DB2_TEST;
UID=FRED; PWD=DERF;'); 

Quando il TSD Script incontra questo tipo di richiesta di connessione, si verifica quanto segue:

La stringa di connessione di default per DB2_TEST è ubicata (DB2_TEST deve essere un'origine nel file di configurazione SQL). Se non si rileva una voce SOURCE=, il TSD Script utilizza il valore di default.

Nota: Quando esistono altri attributi, è necessario immettere SOURCE= prima del nome dell'origine dati.

Una nuova stringa di connessione viene creata sovrapponendo la rimante coppia ATTRIBUTE=VALUE alle voci corrispondenti nella stringa di connessione di default e inserendo le nuove coppie che non si trovano nella stringa di connessione di default.

E' possibile sovrascrivere ogni voce della stringa di connessione di default tranne che il driver (DRV=). Questo consente di avere le informazioni sulla connessione di default (database, identificativo della tabella e così via) che, se necessario, possono essere sovrascritte. E' possibile inoltre riscontrare ciò creando nuove origini dati (un'origine per database, ad esempio).

Eliminazione del file di configurazione SQL

E' possibile fornire tutte le informazioni sulla connessione per SQLCommand ed eliminare il file di configurazione SQL. Tuttavia, è necessario accettare tutti i valori origine di default (come ad esempio MULTI_CONNECT e così via).

Esternare le informazioni specifiche del DBMS spesso si rileva un'operazione appropriata. Tuttavia, alcune volte, potrebbe verificarsi la necessità di eliminare il file di configurazione SQL. In questi casi, il TSD Script consente all'utente di registrare e di connettersi ad una nuova origine non rilevata nel file di configurazione SQL:

ret := SQLCommand('CONNECT NEWSOURCE=MYAPP; 
                   DRV=XOORA;SRVR=X:ORASERV; 
                   UID=MARY; PWD='); 

Database di esempio

Viste e tabelle di database

La restante parte di questo capitolo tratta di un database di esempio chiamato COMPANY. Questo database è composto dalle seguenti tabelle e viste. Gli attributi delle colonne vengono elencati in ogni nome vista o tabella.

Tabella DEPARTMENT

Tabella EMPLOYEE

Tabella MANAGER

Richiamo dei dati con SQLSelectInto

SQLSelectInto

L'istruzione SQLSelectInto fornisce un modo facile per richiamare le informazioni da una vista o tabella SQL. Tratta un numero variabile di argomenti.

Primo argomento

Il primo argomento è sempre un'espressione di stringa che rappresenta un'istruzione SQLSelect come ad esempio:

SELECT * FROM EMPLOYEE WHERE EMPLOYEE_ID='305-83-3811'. 

Nella maggior parte dei casi, SQLSelectInto viene utilizzata per richiamare una riga univoca da una tabella. L'espressione select inoltrata come primo argomento generalmente contiene una clausola nel formato:

WHERE <primary-key>=<value> 

In generale, il formato di un'istruzione select è:

SELECT <column-list> FROM <table-or-view name> WHERE <condition>. 

<column-list> è un elenco di uno o più nomi di colonne separati da virgole (come ad esempio "FIRST_NAME, LAST_NAME"). Se si desidera richiamare tutte le colonne da una tabella, è possibile invece utilizzare l'asterisco (*).

<condition> è una condizione TRUE/FALSE creata generalmente utilizzando un nome di colonna, un operatore relazionale (=, >, <, >=, <=) e un valore (come ad esempio 'SMITH').

Esempi di istruzioni select valide vengono riportati di seguito:

SELECT EMPLOYEE_ID,LAST_NAME FROM EMPLOYEE WHERE 
    DEPARTMENT_ID='SALES' 
SELECT FIRST_NAME,LAST_NAME,PHONE FROM EMPLOYEE 
SELECT * FROM MANAGER 

Argomenti successivi

Il secondo argomento e quelli successivi a SQLSelectInto sono variabili TSD Script. I nomi di queste variabili devono corrispondere ai nomi delle colonne nella vista o tabella SQL alla quale si accede, come riportato in questo esempio:

    VARIABLES
  last_name, first_name: String;
    ACTIONS
  SQLSelectInto('SELECT LAST_NAME,FIRST_NAME FROM
               EMPLOYEE WHERE EMPLOYEE_ID=123',
               last_name,first_name); 

In questi esempi, se le variabili TSD Script sono sensibili al maiuscolo non costituisce un problema per l'elaborazione. Il valore dalla colonna LAST_NAME viene letto nella variabile della stringa last_name. Il valore dalla colonna FIRST_NAME viene letto nella colonna first_name.

Utilizzo di una variabile record

Un modo più semplice per estrarre le informazioni dalle tabelle SQL è quello di utilizzare le variabili record TSD Script. Si definisce un tipo di record dove i campi corrispondono ai nomi delle colonne in una tabella SQL. E' possibile inoltrare un record di quel tipo a SQLSelectInto come riportato di seguito:

  TYPES 
  EmployeeRec IS RECORD 
    employee_ID: Integer; 
    last_name: String; 
    first_name: String; 
    birth_date: Date; 
    salary: Real; 
      END; 
    VARIABLES 
  r: EmployeeRec; 
  SQLSelectInto('SELECT LAST_NAME,FIRST_NAME FROM 
                EMPLOYEE WHERE EMPLOYEE_ID=123',r);


Tipi di record

In generale, si dichiara un tipo di record il cui nome è lo stesso per ogni tabella o vista in un database. Utilizzando le funzioni di collegamento del nome di TSD Script è possibile estrarre le informazioni dal database o inserirle nel database utilizzando le variabili di quel tipo di record.

Nell'esempio precedente, il tipo di record EmployeeRec viene dichiarato, in questo modo i tipi e i nomi del campo corrispondono ai nomi e ai tipi delle colonne nella tabella SQL EMPLOYEE. Quando si inoltra un record (r) di questo tipo a SQLSelectInto, il Developer's Toolkit copia automaticamente le informazioni dalla riga richiesta nei campi corrispondenti. Dopo l'esecuzione di SQLSelectInto, r ha il seguente valore:

r.employee_ID = $Unknown 
r.last_name = 'Brown' 
r.first_name = 'Robert' 
r.birth_date = $Unknown 
r.salary = $Unknown 

Notare che solo le colonne r.LAST_NAME e r.FIRST_NAME hanno dei valori. Tutti i campi in un record si avviano con il valore $Unknown. Poiché l'istruzione SQLSelectInto ha selezionato le colonne LAST_NAME e FIRST_NAME, solo r.LAST_NAME e r.FIRST_NAME erano valori assegnati. Tutti i campi r sarebbero stati completati se fosse stata utilizzata l'istruzione seguente:

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE EMPLOYEE_ID=123',r); 

Utilizzo delle istruzioni Import TSD Script

La corrispondenza tra i tipi di record TSD Script e le tabelle SQL è un processo intuitivo. TSD Script consente di creare un'associazione automatica tra una tabella, una vista e un tipo di record attraverso le istruzioni import.

Questo indica che non è necessario dichiarare manualmente un campo record per ogni colonna di una tabella o di una vista. Consultare il seguente esempio:

  TYPES
  EmployeeRec IS RECORD 
    IMPORT('EMPLOYEE'); 
      END; 

Istruzioni Import

Le istruzioni Import possono essere utilizzate all'interno di una dichiarazione record per creare le dichiarazioni del campo direttamente dai nomi e dai tipi di una vista o tabella SQL.
Se la vista o la tabella viene modificata, la dichiarazione del record automaticamente tiene traccia della modifica. Questo significa che, se si è aggiunta una nuova colonna ADDRESS alla tabella EMPLOYEE, non è necessario aggiungere un nuovo campo

address: String; 

a EmployeeRec. IMPORT è un'istruzione del tempo di analisi. Ogni volta che un modulo contenente un'istruzione IMPORT viene ricreato (analizzato), la vista o la tabella SQL indicata viene letta e le colonne vengono utilizzate per creare le dichiarazioni del campo.

Stringa di connessione

Le impostazioni Import considerano una stringa di connessione che viene specificata insieme al nome della vista o della tabella. Questa stringa di connessione sostituisce la stringa di connessione di default specificata nel file sai_sql.cfg. Per avere una compatibilità con le versioni precedenti, è possibile specificare il nome del database nel formato, 'DATABASE xxx', dove xxx è il nome del database.

Analisi con l'opzione /S

Quando si analizza, è necessario inoltrare l'opzione /S al Programma di analisi TSD Script per sovrascrivere le informazioni sulla connessione o sul database codificato su disco fisso nell'istruzione Import.

L'opzione /S consente di specificare un database al momento dell'analisi, in modo da non rendere necessaria la codifica su disco fisso del nome origine dei dati. Consente inoltre di specificare la password e l'ID utente quando si esegue il Programma di analisi TSD Script dalla richiesta comandi. Questi valori vengono sostituiti per i valori di default specificati nel file sai_sql.cfg.

Il metodo migliore per utilizzare l'opzione /S è quello di specificare tutti i valori tranne l'ID utente e la password nel file sai_sql.cfg file. Quindi, al momento dell'analisi, è possibile inoltrare questi valori. Ad esempio:

/S"UID=UserId;PWD=Password" 

(dove UserId è l'ID utente e Password è la password univoca dell'utente.)

Utilizzo delle parole chiave

Quando si utilizza IMPORT, è possibile utilizzare parole chiave facoltative per chiarire l'ordine del contenuto di IMPORT. Le parole chiave sono:

Se non si specifica alcuna parola chiave, l'ordine della stringa import viene così considerato: nome tabella per primo e poi la stringa di connessione.

Utilizzare lo spazio vuoto e/o le virgole per separare le informazioni sulla connessione e sul nome della tabella.

Nota: E' possibile inoltre utilizzare la parola chiave TABLE o VIEW per identificare i nomi delle viste o delle tabelle. Vengono trattati allo stesso modo.

In questo manuale, le parole chiave appaiono con tutte le lettere maiuscole e non sono sensibili al maiuscolo e minuscolo. Tuttavia, le informazioni sulla connessione e sui nomi delle tabelle possono essere sensibili al maiuscolo e minuscolo, a seconda dell'installazione DBMS. Verificare queste informazioni con l'amministratore della LAN o con un responsabile del database. E' possibile inoltre consultare i manuali forniti con il DBMS per accertarsi che l'argomento relativo alla sensibilità al maiuscolo e minuscolo sia già stato trattato in una pubblicazione.

Esempi di istruzione IMPORT

Esistono molti modi per costruire una stringa import valida. I seguenti esempi sono stati creati per fornire diverse scelte. Tuttavia, si consiglia di selezionare uno stile e di utilizzarlo costantemente.

Il metodo migliore per utilizzare IMPORT viene riportato di seguito:

Import('ALARMS'); 

La seguente sintassi era supportata in SA-ASE 4.1:

Import('DATABASE ADVISOR TABLE ALARMS');

Per SA-ASE 4.2 e successive, questa sintassi è:

'CONNECT DB=ADVISOR' 

Inoltre i seguenti esempi sono uguali all'esempio precedente:

Import ('CONNECT DB=ADVISOR TABLE ALARMS'); 
Import('TABLE ALARMS CONNECT DB=ADVISOR'); 
Import('ALARMS, CONNECT'); 
Import('TABLE ALARMS'); 
Import('VIEW PROBLEM_VIEW'); 

Nel seguente esempio, notare la mancanza di spazi vuoti all'interno della stringa di connessione:

Import('ALARMS, SRVR=X:ORASRV;DB=ADVISOR'); 

Anche il seguente esempio è corretto:

Import('TABLE ALARMS, CONNECT SRVR=X:ORASRV; DB=ADVISOR); 

Nell'esempio seguente, il carattere "'" è facoltativo.

Import('TABLE ALARMS CONNECT SRVR=X:ORASRV; DB=ADVISOR'); 

Anche il seguente esempio è corretto:

Import('CONNECT SOURCE=ADVTEST;SRVR=X:ORASRV; DB=ADVISOR, TABLE ALARMS);

Esempio non corretto

Notare che la seguente sintassi non è corretta, poiché la stringa 'ADVISOR' non è una stringa di connessione valida ('DB=ADVISOR' è una stringa di connessione valida).

Import('ALARMS,ADVISOR'); (*this is WRONG!*)

Tipi di dati

TSD Script ha sei semplici tipi di dati:

L'istruzione IMPORT ha un approccio generico nel mettere in corrispondenza le colonne ai campi, in base al loro tipo di dati.

Colonna Metti in corrispondenza con...
CHAR, VARCHAR e LONG VARCHAR TSD Script STRINGS
INTEGER TSD Script INTEGERS
DATE TSD Script DATES
TIME TSD Script TIMES
I tipi SQL contenenti punti decimali (fissi o mobili) TSD Script REALS

Il tipo BOOLEAN non è supportato nella maggior parte delle implementazioni SQL. Tuttavia, se si utilizza Oracle o il DB2/2 della IBM, è possibile inserire $ASETYPE=BOOLEAN nel commento per una colonna per poter creare un campo Boolean con l'istruzione IMPORT. Per l'SQLServer, il Developer's Toolkit crea un tipo BOOLEAN definito dall'utente.

Il Developer's Toolkit crea una tabella tipo che crea un collegamento alla vista SYSCOLUMNS per Informix.


Richiamo di più righe

SQLSelectInto è un modo facile per richiamare una riga univoca da una vista o da una tabella. E' possibile utilizzare SQLSelectInto per trovare una riga ma non può effettuare la scansione di una tabella.

Il TSD Script fornisce una variabile del cursore per richiamare più voci da un database all'interno di un loop. Il cursore tiene traccia della posizione corrente in un elenco richiamato.

Processo

Viene di seguito riportato il processo di base per richiamare più righe:

Per consentire il richiamo di più righe, il TSD Script fornisce tre istruzioni:

Il manuale Riferimento Lingua del TSD 6.0 Developer's Toolkit Script fornisce informazioni aggiuntive sulle istruzioni precedenti.

Esempio

Le istruzioni vengono utilizzate nel seguente esempio:

    VARIABLES 
  cursor: SQLCursor; 
  r: EmployeeRec; 
    ACTIONS 
 IF SQLSelect(cursor,'SELECT * FROM EMPLOYEE WHERE 
              SALARY>>0000.00') > 0 THEN 
    WHILE SQLFetch(cursor,r) > 0 DO 
      ProcessEmployee(r); 
      END; 
  SQLCloseCursor(cursor); 
      END; 

Questo esempio esegue la funzione seguente:

L'operazione SQLCloseCursor è molto importante. Quando un cursore SQL è aperto, la maggior parte delle implementazioni SQL blocca tutte le righe nella tabella dei risultati. Queste righe non vengono bloccate fino a quando non viene elaborata l'istruzione SQLCloseCursor.

Nota: Generalmente, non si desidera eseguire le operazioni di interfaccia utente tra le istruzioni SQLSelect e SQLCloseCursor. Inoltre, il TSD Script fornisce un numero limitato di cursori simultanei. Se l'utente dimentica di chiudere i cursori, l'utente alla fine supererà questo limite.

Identificativi

Utilizzo degli identificativi

L'SQL abilita diverse tabelle con lo stesso nome all'interno di un database. Per poterle distinguere, l'SQL memorizza il proprietario/creatore della tabella nella definizione della tabella. Questo nome proprietario/creatore viene considerato come l'identificativo della tabella. Una combinazione del nome della tabelle e dell'identificativo deve essere utilizzata solo per identificare una tabella all'interno di un database. Ad esempio:

mary.address

La maggior parte dei gestori di database SQL utilizza l'ID utente corrente come identificativo nel caso non ne venisse fornito alcuno. Se non si è registrati come utente che ha creato il database e non si fornisce un identificativo, alcune implementazioni SQL continuano a ricerca il database utilizzando, come identificativo, il proprietario del database. In altre implementazioni SQL (come ad esempio DB2/2), l'utente deve necessariamente fornire ogni volta un identificativo.

Sostituzione dell'identificativo

Il TSD Script esegue le sostituzioni appropriate dell'identificativo fino a quando non si immetterà la voce QUAL= nella stringa di connessione.

Il TSD Script esegue la sostituzione in tutte le istruzioni tranne che in:

Se si utilizzano query complesse contenenti nomi di correlazione, la sostituzione non può essere eseguita in modo corretto. In questi casi, il TSD Script fornisce uno pseudo identificativo, $QUAL, che sostituisce l'identificativo corrente (cioè, quello impostato con la voce QUAL= della stringa di connessione).

Ad esempio, per evitare la codifica su disco fisso dell'identificativo, il seguente frammento di codice utilizza $QUAL come identificativo:

ret := SQLExecuteImmediate('DROP TABLE $QUAL.ADDRESS'); 

Virgolette

In TSD Script, tutte le stringhe sono circondate da singoli apici (o apostrofi). In SQL, anche i literal del carattere, della data e dell'ora devono essere inoltre circondati da singoli apici. Ad esempio, per emettere la query SQL, è necessario

SELECT * FROM EMPLOYEE WHERE LAST_NAME='BROWN' 

utilizzare la seguente istruzione TSD Script:

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE
LAST_NAME=''BROWN''',r); 

Guardando l'esempio SQLSelectInto precedente, è possibile notare che i due singoli apici alla sinistra della "B" in "BROWN" risultano in un singolo apice. Sono presenti due singoli apici dopo "N" in "BROWN." Questo fa sì che venga inserito un singolo apice in questa posizione. Il terzo singolo apice dopo la "N" in "BROWN" viene utilizzato per terminare la stringa.

Per inserire un singolo apice in un literal di stringa del TSD Script, è necessario inserire due singoli apici. Ad esempio, per assegnare la stringa "Tom's Place" ad una variabile TSD Script, è necessario utilizzare:

s := 'Tom''s Place';

Concatenamento delle stringhe con le virgolette

Quando si concatenano le stringhe che utilizzano le virgolette, diviene più complicato. In questo esempio, il cognome che si desidera ricerca è memorizzato in una variabile di stringa chiamata last_name:

last_name := 'BROWN'; 
SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
             LAST_NAME=''' & last_name & '''',r); 

Quando si crea una stringa select utilizzando l'operatore di concatenamento del TSD Script (&), è necessario posizionare i singoli apici al lato del valore literal che si desidera ricerca. La query risultante appare così:

SELECT * FROM EMPLOYEE WHERE LAST_NAME = 'BROWN' 

Il singolo apice alla sinistra del cognome viene creato attraverso i tre singoli apici che seguono "LAST_NAME=''.

I primi due apici vengono utilizzati per inserire il singolo apice richiesto, mentre il terzo termina semplicemente la prima costante di stringa, 'SELECT * ... ='.

Il secondo apice singolo necessario viene creato concatenando il literal '''' alla fine dell'intera espressione.

Quando si creano le espressioni select dove il valore inquiryto è una stringa, una data o un'ora, è necessario inserire tre apici prima della variabile che tiene il valore di inquiry e quattro dopo.

Eccezioni

Gli apici non sono necessari quando si inquiryno altri tipi di dati, come di seguito riportato:

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
              AGE=30',r); 

Non sono necessari gli apici intorno a 30, poiché questo è un valore intero. Se il 30 fosse stato inserito in una variabile intera, l'istruzione potrebbe risultare più o meno così:

age := 30; 
SQLSelectInto('SELECT * FROM EMPLOYEE WHERE AGE=' & age,r);

Formattazione dei dati con l'Istruzione SQLFormat

Utilizzo di SQLFormat

L'istruzione SQLFormat è un'istruzione TSD Script utilizzata nella manipolazione SQL. SQLFormat converte un valore dati in una stringa che corrisponde al formato dei dati per il DBMS che si sta attualmente utilizzando.

L'istruzione SQLFormat è utile soprattutto per le variabili ora e data e utilizza la seguente sintassi:

SQLFormat(value: SIMPLE EXPRESSION): STRING;

Nota: Il DBMS può richiedere formati ora e data differenti dai formati di default utilizzati per la visualizzazione dal Developer's Toolkit. Ad esempio, il formato data di default di Oracle è GG-MES-AA, mentre il formato data di default del Developer's Toolkit è MM/GG/AAAA.

L'argomento valore che SQLFormat considera deve essere di tipo semplice, come ad esempio DATE o STRING. SQLFormat restituisce la stringa formattata, non un codice di ritorno, che indica se l'operazione ha avuto esito positivo. Se il valore inoltrato è $Unknown, viene restituita la stringa 'NULL'. La formattazione specifica della stringa dipende dal tipo della stringa:

Esempio

Un file .kb (knowledgebase) di esempio che utilizza SQLFormat viene riportato di seguito:

KNOWLEDGEBASE Example; 
--PUBLIC 
    ROUTINES 
 FUNCTION GetCount(VAL d: DATE): INTEGER; 
PRIVATE 
    ROUTINES 
 FUNCTION GetCount(VAL d: DATE): INTEGER IS 
    VARIABLES 
   retCd : INTEGER; 
   cmd : STRING; 
   $SQLColumn_1 : INTEGER; 
    ACTIONS 
   cmd := 'SELECT COUNT(*) FROM COMPANIES WHERE name = 
          ' & SQLFormat('Joe''s place') & 
          ' AND founded_date='& SQLFormat(d); 
   retCd := SQLSelectInto(cmd, $SQLColumn_1); 
   IF retCd < 0 THEN 
     Exit( retCd ); 
      ELSE 
     Exit( $SQLColumn_1 ); 
      END; 
      END; 

Per ulteriori informazioni sulle istruzioni TSD Script utilizzate nella formattazione dei dati, consultare Riferimento Lingua del TSD 6.0 Developer's Toolkit Script.

Sostituzioni dei nomi

Il TSD Script utilizza l'equivalente dei nomi delle variabili e dei nomi delle colonne per facilitare il richiamo dei dati. Alcune volte, tuttavia, la messa in corrispondenza basata sui nomi non si rivela la scelta migliore o addirittura non può essere utilizzata.

Si consideri la seguente query SQL che può essere utilizzata per determinare il numero di dipendenti (righe) nella tabella EMPLOYEE:

SELECT COUNT(*) FROM EMPLOYEE

Richiamo dei dati senza nomi corrispondenti

Il TSD Script fornisce un metodo semplice per richiamare i dati da una colonna SQL senza basarsi sui nomi corrispondenti. Tutto quello che l'utente deve fare è dichiarare una variabile denominata $SQLCOLUMN_n dove "n" è il numero della colonna che si desidera richiamare. Il tipo di questa variabile deve corrispondere alla colonna richiamata.

Per richiamare il numero di dipendenti (righe) nella tabella EMPLOYEE, è possibile utilizzare il seguente codice:

    VARIABLES
  $SQLCOLUMN_1: INTEGER;
    ACTIONS
  SQLSelectInto('SELECT COUNT(*) FROM
                 EMPLOYEE',$SQLCOLUMN_1);

$SQLCOLUMN_1 è una variabile normale. E' possibile assegnarla, testarla, utilizzarla in espressioni e così via.

Aggiornamento dei dati

Introduzione

Questa sezione descrive come inserire i dati in un database SQL, come cancellare i dati da un database SQL e come modificare i dati in un database SQL.

Inserimento dei dati

L'istruzione SQLInsert può essere utilizzata per inserire nuove righe in una tabella. L'utente deve fornire un nome di tabella seguito dalla(e) variabile(i) che trattiene i dati da inserire. Come la funzione di richiamo, il TSD Script esegue una messa in corrispondenza tra i nomi di variabile TSD Script e i nomi di colonna SQL.

Nell'esempio seguente, i valori vengono assegnati ai diversi campi di una variabile di tipo EmployeeRecord. Per inserire queste informazioni nella tabella EMPLOYEE, si richiama SQLInsert con il nome della variabile e della tabella di destinazione.

VARIABLE 
  r: EmployeeRecord; 
    ACTIONS 
  r.employee_ID:'312-34-3444'; 
  r.last_name:'Brown' 
  r.first_name:'Robert' 
  r.birth_date:'08/05/1964'; 
  r.salary:  $Unknown 
  SQLInsert('EMPLOYEE',r); 

SQLInsert, come SQLSelectInto e SQLSelect, tratta un numero variabile di argomenti. Il primo argomento è il nome della tabella. Gli argomenti restanti rappresentano i valori da inserire in ogni colonna della nuova riga. E' possibile inoltrare un singolo record o un numero di variabili semplici, come dimostrato nell'esempio seguente.

VARIABLE
  employee_ID: STRING; 
  last_name: STRING; 
  first_name: STRING; 
  birth_date: DATE; 
      salary : REAL; 
    ACTIONS 
  employee_ID:'312-34-3444'; 
  last_name:'Brown'; 
  first_name:'Robert'; 
  birth_date:'08/05/1964'; 
  salary:$Unknown; 
  SQLInsert('EMPLOYEE',employee_ID,last_name,
            first_name,birth_date,salary); 

Cancellazione dei dati

SQLDelete può essere utilizzata per cancellare una o più righe da una tabella. Tratta due argomenti: il nome della tabella e una clausola SQL WHERE che identifica le righe da cancellare. La parola WHERE in questa clausola è facoltativa.

Questo esempio cancella ogni dipendente il cui cognome è "Smith."

SQLDelete('EMPLOYEE','LAST_NAME=''Smith'''); 

Il seguente esempio cancella un dipendente con uno specifico numero ID dipendente.

SQLDelete('EMPLOYEE','EMPLOYEE_ID=''123-45-
           6789''');

Modifica dei dati

SQLUpdate può essere utilizzata per modificare le informazioni memorizzate nelle righe esistenti di una tabella. Questa istruzione considera i seguenti argomenti:

Ad esempio, si supponga che la propria società abbia un dipendente con l'ID 345-67-8901 che ha ricevuto un aumento del 10%. E' necessario aggiornare il database per riportare questo cambiamento, come spiegato in questo esempio:

    VARIABLES 
      salary : REAL; 
    ACTIONS 
  IF SQLSelectInto('SELECT SALARY FROM EMPLOYEE 
                  WHERE EMPLOYEE_ID=
                  ''345-67-8901''', 
salary) > 0 THEN 
  salary := salary * 1.10; 
  SQLUpdate('EMPLOYEE','EMPLOYEE_ID='
            '345-67- 8901''',salary); 
      END; 

Nell'esempio successivo, la società ha deciso di dare l'aumento del 10% a tutti i dipendenti. Questo esempio mostra come aggiornare il database con queste informazioni:

    VARIABLES 
      salary : REAL; 
  cursor: SQLCursor; 
    ACTIONS 
  IF SQLSelect(cursor, 
               'SELECT SALARY FROM EMPLOYEE 
               ') > 0 THEN 
WHILE SQLFetch(cursor,salary) > 0 DO 
      salary := salary * 1.10; 
      SQLUpdateCurrent(cursor,salary); 
      END; 
  SQLCloseCursor(cursor); 
      END; 

SQLUpdateCurrent è una versione speciale di SQLUpdate che può essere utilizzata per aggiornare l'ultima riga di un cursore che è stata sottoposta a fetch. Considera i valori e la variabile del cursore da aggiornare come argomenti.

Infine, SQLUpdate (e SQLUpdateCurrent) può considerare un record invece di una sequenza di variabili semplici. Il successivo esempio suppone che:

VARIABLE 
  r: EmployeeRecord; 
    ACTIONS 
  r.employee_ID: = '312-34-3444'; 
  IF SQLSelectInto('SELECT * FROM EMPLOYEE 
                   WHERE EMPLOYEE_ID=''' & 
r.employee_ID & '''',r) > 0 THEN 
    EditEmployee(r); 
    SQLUpdate('EMPLOYEE',
              'EMPLOYEE_ID=''' & r.employee_ID & '''',r);
      END; 

Riepilogando, i seguenti passi vengono eseguiti in questo esempio:

Concorrenza passiva

L'utente può aver notato in questi esempi che i record non sono stati bloccati e nemmeno sono stati presi provvedimenti per impedire a più utenti di accedere agli stessi record.

La caratteristica della concorrenza passiva del Developer's Toolkit's gestisce i problemi tipici legati alla concorrenza riscontrati nelle applicazioni per più utenti, come riepilogato nel seguente elenco:

Il messaggio di errore ha un codice di errore negativo. In alcune situazioni, è possibile voler testare questo codice di errore ed eseguire operazioni diverse a seconda del valore.

Ad esempio, se una sezione di codice dipende dall'esito positivo di un'operazione d'inserimento, è necessario testare quel codice per una avere un risultato positivo da SQLInsert.

Il Developer's Toolkit crea un messaggio di errore per il secondo utente che tenta di cancellare la riga.

Nota: Per implementare il controllo della concorrenza passiva inserire un ulteriore argomento a SQLUpdate.

Considerare il seguente esempio:

VARIABLE 
  r, oldR: EmployeeRecord; 
    ACTIONS 
  r.employee_ID: = '312-34-3444'; 
  IF SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
                    EMPLOYEE_ID=''' & r.employee_ID 
                    & '''', r, oldR) > 0 THEN 
    EditEmployee(r); 
    SQLUpdate('EMPLOYEE',
              'EMPLOYEE_ID=''' & r.employee_ID & 
              '''',r,oldR); 
      END; 

In questo esempio si sono verificati i seguenti eventi:

Quando il TSD Script inizia l'elaborazione dell'istruzione SQLUpdate, esso rileva una variabile record supplementare, oldR. Questo fa sì che il programma:

Se non si rilevano alcune differenze, qualcun altro ha già modificato quella riga e l'aggiornamento viene annullato. SQLUpdate restituisce un codice di errore negativo e un viene visualizzato sullo schermo un messaggio di errore del livello dell'utente. Inoltre, il valore corrente della riga viene inserito in oldR (in modo che l'utente non debba richiamare la versione corrente del record).

La concorrenza passiva è un modo facile ed efficace per assicurare le operazioni appropriate in un ambiente per più utenti. Si verifica un leggero ritardo in quanto è necessario effettuare un secondo richiamo della riga da aggiornare. Tuttavia, la protezione aggiuntiva fornita si rivela utile.

Nota: In generale, è necessario utilizzare sempre il modulo di concorrenza passiva di SQLUpdate a meno che non si è sicuri che non si è verificata alcuna perdita di aggiornamenti.

Elaborazione transaction-oriented

La maggior parte dei motori di database SQL offre la possibilità di raggruppare le operazioni SQL in unità di lavoro. E' possibile utilizzare le funzioni incorporate per assicurare che ogni unità di lavoro abbia esito positivo o negativo nell'insieme.

Nelle elaborazioni normali, tutte le modifiche vengono trasmesse al database appena si verificano. Nell'elaborazione transaction-oriented, le modifiche ai dati vengono gestite in modo diverso.

Descrizione

L'istruzione SQLBeginWork indica l'inizio di un'unità di lavoro. SQLBeginWork indica al motore di database SQL che esso non può chiamare nè SQLCommitSQLRollback fino a quando non riceve l'ordine dall'utente.

L'istruzione SQLCommit indica che tutte le modifiche al database, apportate dall'ultimo richiamo di SQLBeginWork, devono essere applicate al database stesso e rese permanenti.

L'operazione SQLRollback si verifica quando uno dei processi definiti per l'unità di lavoro non ha esito positivo. SQLRollback indica che tutte le modifiche al database, apportate dall'ultimo richiamo dell'istruzione SQLBeginWork, non devono essere eseguite.

Ad esempio, in un'applicazione bancaria, un trasferimento deve avvenire da un deposito di risparmio ad un conto corrente. Questo trasferimento può ridurre la colonna del bilancio in una tabella (SAVINGS_ACCOUNTS) e in un'altra tabella (CHECKING_ACCOUNTS). Questo costituirebbe un problema se un'operazione avesse esito positivo e l'altra avesse esito negativo. Per evitare ciò, un'applicazione transaction-oriented deve:

Esempio

Il frammento di codice seguente illustra i principi trattati in precedenza. Come indicato, questo è un caso in cui diverse operazioni SQL possono avere esito positivo prima di inoltrare le modifiche al database. Specificamente, non si desidera effettuare il commit dopo il primo aggiornamento in quanto il cliente avrà un bilancio dei risparmi inferiore e nessun aumento compensatorio nel bilancio del conto corrente se il secondo aggiornamento ha esito negativo.

PROCEDURE SavingsToCheckingTransfer( 
  VAL savings_ID: STRING, 
  VAL checking_ID: STRING, 
  VAL amount: REAL) IS 
    VARIABLES 
  debited, credited: BOOLEAN; 
  balance: REAL; 
    ACTIONS 
  SQLBeginWork; 
  debited := FALSE; 
   IF SQLSelectInto('SELECT BALANCE FROM 
                     SAVINGS WHERE ACCOUNT_ID=''' &
                     savings_ID & ''''  
                     ,balance) > 0 THEN 
   balance := balance - amount; 
   IF SQLUpdate('SAVINGS', 
                'ACCOUNT_ID=''' & savings_ID & 
'''', balance) > 0 THEN 
     debited := TRUE; 
      END; 
      END; 
  IF debited THEN 
    credited := FALSE; 
    IF SQLSelectInto('SELECT BALANCE FROM CHECKING 
                      WHERE ACCOUNT_ID=''' & 
checking_ID & '''',balance) > 
                     0 THEN 
      balance := balance + amount; 
  IF SQLUpdate('CHECKING', 
               'ACCOUNT_ID=''' & checking_ID & 
              '''' , 
balance) > 0 THEN 
      credited := TRUE; 
      END; 
      END; 
  IF credited THEN 
    SQLCommit; 
      ELSE 
    SQLRollback; 
      END; 
      END; 
      END; 

Valori sconosciuti nelle colonne SQL

Utilizzo dei valori null

Quando si definisce una tabella di database, è possibile specificare se ogni colonna può avere dei valori null. Dichiarare che una colonna può contenere valori null significa che la colonna non deve contenere un valore. (Questo è diverso dall'avere un valore di stringa di vuoto.)

Nota: NULL della SQL ben corrisponde al supporto TSD Script per i valori sconosciuti. Nel TSD Script, ogni variabile inizia con il valore $Unknown. Un'eccezione a tutto ciò sono le variabili record: tutti i campi di una variabile record iniziano con il valore $Unknown.

Messa in corrispondenza dei valori sconosciuti

Poiché i valori vengono scambiati tra il TSD Script e la SQL, viene conservata la messa in corrispondenza tra $Unknown e NULL. Ad esempio, si consideri questo esempio:

  SQLInsert('EMPLOYEE',r); 

In questo esempio, se r.salary è $Unknown, la colonna SALARY per la riga inserita deve contenere un valore NULL.

Altrettanto, se la colonna PHONE fosse NULL per una determinata riga, richiamare quella riga in una variabile record con SQLSelectInto o SQLSelect/SQLFetch fa sì che il campo phone di quella variabile sia $Unknown.

Nel sistema moduli del Developer's Toolkit, anche i valori null vengono supportati. Se un utente lascia un campo di dialogo vuoto, il campo record corrispondente viene impostato su $Unknown.

Nota: Si riceve un errore se si tenta di inserire un valore $Unknown in una colonna che non è stata dichiarata per accettare i valori null. Questo si verifica solitamente solo quando i campi dei moduli vengono lasciati vuoti.

Gestione errori

Nelle applicazioni di tipo aziendale, viene scritta una grande quantità di codici per gestire le condizioni di errore. Una volta scritto il codice, questo deve essere testato. Spesso, questo significa valutare il codice di ritorno da ogni istruzione.

Il Developer's Toolkit comprende un meccanismo automatico di gestione degli errori che riduce il peso della gestione degli errori. Ciò significa che:

Rilevazione dei messaggi di errore

Per default, il Developer's Toolkit rileva le operazioni SQL non riuscite e visualizza i messaggi di errore agli utenti finali.

Il Developer's Toolkit visualizza più informazioni contestuali possibili per identificare la causa dell'errore (errore di colonne duplicate, errore I/E, disco pieno e così via). Se non è importante che un'operazione riporti esito positivo o negativo, non è necessario controllare il valore di ritorno. In questo caso, viene inserito un nuovo dipendente nella tabella EMPLOYEE:

  SQLInsert('EMPLOYEE',r);

Filtraggio dei messaggi di errore

Alcune volte si può voler disabilitare temporaneamente la funzione automatica dei messaggi di errore. $ErrorFilter è una funzione intera di sistema che consente di specificare una soglia di livello degli errori. Gli errori con livelli al di sotto della soglia specificata non creano messaggi di errore.

I seguenti livelli di severità creano messaggi automatici di codice di errore:

Codice severità di errore Descrizione
0 Errore irreversibile
1 Errore non irreversibile
2 Messaggio di avvertenza
3 Messaggio informativo

Ad esempio, impostare $ErrorFilter(3) significa che solo gli errori e le avvertenze con un livello di codice di severità tre, o inferiore, creano messaggi automatici. Gli errori con un livello di codice di riservatezza più alto non causano la visualizzazione di messaggi di errore, e sono distinguibili solo attraverso l'esame dei codici di ritorno dell'istruzione.

I livelli di codice di severità diminuiscono con una severità crescente. Tuttavia, è possibile richiamare ErrorFilter(0) per disabilitare tutti i messaggi tranne quelli irreversibili.

Utilizzo dei comandi per più esecuzioni

Preparazione dei comandi di loop SQL

Se si intende eseguire più volte un comando SQL in un loop, potrebbe essere più efficace preparare (precompilare) una volta il comando al di fuori del loop, quindi eseguire il modulo preparato nel loop.

Il Developer's Toolkit consente di preparare la maggior parte dei comandi SQL ad eccezione delle istruzioni Select e dei comandi che non possono essere preparati in modo dinamico. Consultare la documentazione SQL per le informazioni sui comandi specifici che non possono essere preparati in modo dinamico.

Il Developer's Toolkit fornisce due comandi per preparare un comando SQL:

Nota: SQLPrepare e SQLExecute sono supportate solo in DB2/2, DB2/6000 e Oracle.

Utilizzare SQLPrepare e SQLExecute equivale ad utilizzare SQLExecuteImmediate tranne che per il fatto che l'esecuzione viene rimandata fino a quando non se ne ha bisogno. Il seguente esempio mostra come inserire un elenco di nuovi utenti in una tabella USER con la combinazione SQLPrepare/SQLExecute:

FUNCTION InsertNewUsers(REF users: LIST OF 
                        STRING):INTEGER IS 
    VARIABLES 
  stmt: SQLStatement; 
   retCd : INTEGER; 
    ACTIONS 
  (* insert the user names passed in *) 
  retCd := SQLPrepare(stmt,'INSERT INTO USERS
                      VALUES (?)'); 
  IF retCd <= 0 THEN 
    EXIT retCd; 
      END; 
  (* perform the insertions *) 
  FOR users DO 
    retCd := SQLExecute(stmt,users[$current]); 
    IF retCd <= 0 THEN 
      SQLRollback; (* reverse changes and 
                    release locks *) 
      EXIT retCd; 
      END; 
   END; (* for *) 
  (* release the resources used by this Prepared 
   statement *) 
  SQLCloseStatement(stmt); 
      END; 

Nota: Poiché il TSD Script dispone di un numero limitato di risorse per istruzioni preparate e simultanee, è necessario assicurarsi di chiudere l'istruzione preparata richiamando SQLCloseStatement.

Sostituzione dei contrassegni dei parametri

La sostituzione del Contrassegno dei parametri è parte integrante del processo di utilizzo delle istruzioni preparate. I contrassegni dei parametri, rappresentati dai punti interrogativi (?), sono dei segnaposto per i valori in seguito sostituiti.

Per ogni valore, viene inserito un punto interrogativo nella stringa di istruzione (fornita a SQLPrepare). Le istruzioni per questi valori vengono di seguito riportate:

Nota: Il TSD Script non è in grado di fornire conversioni ugualmente affidabili con i contrassegni dei parametri come avviene invece con i parametri normali (quelli utilizzati in SQLInsert, SQLUpdate, SQLSelectInto e SQLFetch).

Istruzioni SQL nidificate

Nota: Queste istruzioni si applicano solo al Sybase e al Microsoft SQLServer.

Alcuni DBMS supportano solo un'istruzione SQL attiva al momento della connessione. Ad esempio, inserendo un'istruzione SQLSelectInto nel corpo di un loop SQLFetch sono necessarie due istruzioni SQL simultanee con l'SQLServer. Il Developer's Toolkit compensa tutto questo clonando le connessioni. Le connessioni clonate o "secondarie" dispongono di un proprio spazio per le transazioni.

Il modello delle transazioni del Developer's Toolkit fa sì che tutte le connessioni si comportino come se appartenessero alla stessa transazione. Sebbene questo sia qualcosa di non puramente appropriato, (non viene utilizzato alcun protocollo di sincronizzazione a due fasi), nella pratica si rivela essere efficiente. Esiste un semplice requisito che rimanda i commit "automatici" fino a quando il cursore più esterno non viene chiuso per gli ambienti dove i cursori aperti e le istruzioni preparate vengono chiuse su commit o su ripristino.

Nelle versioni precedenti del Developer's Toolkit, tutte le operazioni SQL simultanee o nidificate venivano eseguite all'interno di una transazione. In quelle versioni, SQLBeginWork viene richiamato prima che il cursore più esterno venga aperto, ed è necessario eseguire un commit (o un ripristino) quando il cursore più esterno viene chiuso.

Se si desiderava che le istruzioni venissero eseguite nei loro appositi spazi per la transazione, era necessario aprire connessioni primarie aggiuntive con SQLCommand per le istruzioni.

Il Developer's Toolkit 6.0 non richiede più l'avvolgimento delle transazioni per l'esecuzione simultanea delle istruzioni nella modalità "manuale" del commit. Tuttavia, l'avvolgimento delle transazioni viene ancora richiesto quando si utilizza la modalità "automatica" del commit se il DBMS non consente ai cursori di estendere le transazioni.

A causa delle complessità e degli effetti collaterali nelle istruzioni SQL nidificate (come ad esempio un sovraccarico nelle connessioni, il potenziale stallo che si può verificare quando si accede alla stessa tabella da due connessioni in spazi di transazione differenti e così via), si raccomanda vivamente di evitarle ogni volta che ciò si rende possibile.

E' quasi sempre possibile dividere le operazioni SQL in due parti:

Oltre ad evitare molti degli effetti collaterali delle istruzioni nidificate, questo metodo ha il vantaggio della concorrenza maggiore in quanto l'utente non è costretto ad eseguire le operazioni all'interno di una transazione. A seconda dell'applicazione, tuttavia, è ancora necessaria una transazione per la seconda parte.


Manuale per la programmazione Tivoli Service Desk 6.0 Developer's Toolkit Script

Ritorna all'Indice analitico

Copyright