Documenti analoghi
Procedure memorizzate SQL-2003/PSM. Forma base di PSM. Parametri in PSM

Basi di dati. Il Linguaggio SQL. K. Donno - Il Linguaggio SQL

Data Base. Master "Bio Info" Reti e Basi di Dati Lezione 6

Come trattare il risultato di un comando SQL (relazioni) che

Il linguaggio SQL. è di fatto lo standard tra i linguaggi per la gestione di data base relazionali.

Abilità Informatiche A.A. 2010/2011 Lezione 9: Query Maschere Report. Facoltà di Lingue e Letterature Straniere

APPENDICE. Procedure in SQL (1)

Esercitazione query in SQL L esercitazione viene effettuata sul database viaggi e vacanze che prevede il seguente modello E/R:

Triggers. Basi dati attive. Trigger. Indipendenza della conoscenza

SQL e ACCESS. Modello relazionale PROBLEMA ENTITA STUDENTE

MAX, SUM, AVG, COUNT)

Informatica Generale Andrea Corradini Sistemi di Gestione delle Basi di Dati

Appunti di MySql. Evoluzione di un tutorial di base di mysql, scritto da Etel Sverdlov.

User Tools: DataBase Manager

Volumi di riferimento

Azioni. Select e join non consentono di modificare il contenuto del DB. Inserzione di nuovi dati. Azioni desiderate. Aggiornamento di dati

PHP e Structured Query Language

SQL. Laboratorio di Progettazione di Basi di Dati (CdS in Informatica e TPS)

SQL Server. SQL server e un RDBMS di tipo client/server che utilizza Transact-SQL per gestire la comunicazione fra un client e SQL Server

Istruzioni DML di SQL

SQL e applicazioni. Capitolo 8. SQL e linguaggi di programmazione. Applicazioni ed SQL: architettura. Una difficoltà importante.

Capitoli 8 e 9. SQL embedded. Applicazioni tradizionali Applicazioni Internet. Sistemi di basi di dati Raghu Ramakrishnan, Johannes Gehrke

Informatica per le discipline umanistiche 2 lezione 10

DBMS ed Applicazioni Motivazioni

Sistemi Mobili e Wireless Android - Dati persistenti: SQLite

Esercitazione sulle libpq - libreria C per PostgreSQL

Lezione 9. Applicazioni tradizionali

Istruzioni SQL 1. Query di selezione 2 Istruzione SELECT 2 Istruzione SELECT DISTINCT 2 ORDER BY 3 WHERE 3 La condizione LIKE 4 BETWEEN AND 5

Corso Sistemi Informativi Avanzati. Programma 30 set Installazione Macchina Virtuale. Introduzione alla BI nelle Aziende.

Basi di dati (6) Docente: Andrea Bulgarelli. Università di Modena e Reggio Emilia. andrea.bulgarelli@gmail.com Argomento: T-SQL (1.

Il linguaggio SQL: trigger. Versione elettronica: 04.7.SQL.trigger.pdf

Oracle PL/SQL. Motivazioni

Le query. Lezione 6 a cura di Maria Novella Mosciatti

ESEMPI DI QUERY SQL. Esempi di Query SQL Michele Batocchi AS 2012/2013 Pagina 1 di 7

CONCETTO DI ANNIDAMENTO

Lezione 8. Metadati, Viste e Trigger

DBMS (Data Base Management System)

19. LA PROGRAMMAZIONE LATO SERVER

Dispensa di database Access

OSSIF WEB. Manuale query builder

GERARCHIE RICORSIVE - SQL SERVER 2008

Stored Procedures. Antonella Poggi, Claudio Corona. Dipartimento di informatica e Sistemistica SAPIENZA Università di Roma

Archivi e Basi di Dati

Basi di Dati: Corso di laboratorio

IL DAT A B A S E DI ALGE B R A N D O

MySQL Database Management System

OTTAVA ESPERIENZA DI LABORATORIO. L elaborazione dei files in C

JDBC versione base. Le classi/interfacce principali di JDBC

Definizione di domini

MySQL Database Management System

Corso di Informatica Generale 1 IN1. Linguaggio SQL

Utilizzando Microsoft Access. Si crea la tabella Anagrafica degli alunni,le Materie e i voti si mettono alcuni campi

Unità 2.1 Comandi sui database

Programmazione I / Informatica generale Prova scritta 11 Giugno 2008

Progetto di Basi di Dati e Multimidia Laboratorio Struttura dell applicazione web

LA REALIZZAZIONE DI APPLICAZIONI ALCUNE ARCHITETTURE

LA REALIZZAZIONE DI APPLICAZIONI. Quattro parti: Gestione dati. Business rules. Logica applicativa. Interfaccia utente. Molte possibili architetture

QUICK GUIDE ESAMI DI STATO

2104 volume III Programmazione

Introduzione JDBC interfaccia java.sql driver caricare i driver

Laboratorio di Basi di Dati e Web

Stored Procedures. Massimo Mecella Dipartimento di Ingegneria informatica automatica e gestionale Antonio Ruberti Sapienza Università di Roma

Corso sul linguaggio SQL

Corso di Laurea in Ingegneria Gestionale Esame di Informatica a.a settembre 2011

Capitolo 13. Interrogare una base di dati

Basi di dati (8) Docente: Andrea Bulgarelli. Università di Modena e Reggio Emilia. andrea.bulgarelli@gmail.com Argomento: trigger e cursori (1.

La selezione binaria

DBMS ED APPLICAZIONI (CAPITOLO 6) SQL incluso in codice applicativo Embedded SQL Cursori Dynamic SQL JDBC Stored procedures

Introduzione ai database relazionali

IL LINGUAGGIO SQL IDENTIFICATORI E TIPI DI DATI COMANDI E ISTRUZIONI

APPLICAZIONI DELLE BASI DI DATI

Capitolo 7. Esercizio 7.1

Laboratorio Progettazione Web PHP e MySQL - Lezione 9. Andrea Marchetti IIT-CNR andrea.marchetti@iit.cnr.ita 2012/2013

Fondamenti di Informatica T-1, 2009/2010 Modulo 2 Prova d Esame 5 di Giovedì 15 Luglio 2010 tempo a disposizione 2h30'

Esercitazione di riepilogo sulle Query MySQL Giugno 2011 Classe VB Informatica

PROGRAMMA SVOLTO DI INFORMATICA ANNO SCOLASTICO 2013/2014. DOCENTE: Villani Chiara

Progetto: ARPA Fonte Dati. ARPA Fonte Dati. Regione Toscana. Documentazione Database

Basi di dati 9 febbraio 2010 Compito A

Esercitazioni di Progettazione del Software. Esercitazione (Prova al calcolatore del 17 settembre 2010)

Dominio applicativo. Progettazione. v SQL incluso in codice applicativo v Embedded SQL v Cursori v Dynamic SQL v JDBC v Stored procedures

LEGGERE E VISUALIZZARE I DATI FILTRATI E CALCOLATI DI UNA TABELLA IN UNA PAGINA WEB

Funzioni. Il modello console. Interfaccia in modalità console

Vincoli di Integrità Approccio dichiarativo alla loro implementazione

Il database management system Access

Al giorno d oggi, i sistemi per la gestione di database

Registratori di Cassa

Insegnamento di Informatica CdS Scienze Giuridiche A.A. 2006/7. Il trattamento dei dati

SQL: definizione schema

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)


Basi di dati e Web (Moduli: Laboratorio e Siti Web centrati sui Dati) Prova scritta del 14 luglio 2008

Università degli Studi di Ferrara - A.A. 2014/15 Dott. Valerio Muzzioli ORDINAMENTO DEI DATI

SQL Sintassi Dei Comandi

Dall Algoritmo al Programma. Prof. Francesco Accarino IIS Altiero Spinelli Sesto San Giovanni

RELAZIONE PROGETTO DATABASE GESTIONE BIBLIOTECA PERSONALE

Introduzione a MySQL

Creazione manuale delle tabelle (mediante scrittura del codice SQL corrispondente)

Codifica: dal diagramma a blocchi al linguaggio C++

Appunti tratti dal videocorso on-line di Algoritmi e Programmazione Avanzata By ALeXio

MySQL Command Line Client: operazioni fondamentali

Transcript:

SQL e linguaggi di programmazione E possibile eseguire enunciati SQL da un programma scritto in un linguaggio di programmazione quale COBOL, PL/1, RPG, C,... ed avere una interazione tra variabili di programma e oggetti SQL. PROBLEMATICHE: 1. SQL opera in modo orientato agli insiemi, mentre i linguaggi di programmazione imperativi operano in modo orientato al record 2. E necessario poter utilizzare variabili di programma per la composizione di statement SQL e poter copiare valori di campi in variabili di programma 3. E necessario disporre di strumenti per comunicare al programma lo stato delle esecuzioni SQL. BASI DI DATI 1

Istruzioni embedded SQL } Per inserire statement SQL all'interno di un programma scritto in linguaggio ospite, la sintassi generica e: exec sql SQL statement terminator dove terminator e' il '; Esempi: exec sql select from STUDENTE where MATRICOLA = 0 1234 0 ; exec sql update STUDENTE set NOME = 0 Mario 0 where MATRICOLA = 0 1234 0 ; BASI DI DATI 2

SQL e linguaggi strutturati } Per accoppiare linguaggi di programmazione orientati al record con SQL (orientato agli insiemi) si introduce la nozione di cursore: si associa un cursore ad una query di selezione si apre il cursore come se si trattasse di un le sequenziale si acquisisce un record alla volta dal cursore, con la possibilita di consultare i valori dei campi, aggiornare, cancellare si chiude il cursore } Per utilizzare variabili di programma in statement SQL, ogni implementazione di embedded SQL e dotata di adeguati strumenti sintattici. } Per il controllo sulle istruzioni SQL e disponibile un parametro SQLCODE che restituisce al programma ospite un valore che indica l'esito dell'istruzione SQL eseguita: SQLCODE = 0! ok SQLCODE < 0! situazione di errore SQLCODE = 100! non trovato BASI DI DATI 3

Operazioni su singolo record (1) } Selezione: selezione del livello LIV e della CITTA del fornitore F con codice COD pari a :COD exec sql select into LIV; CITTA : LIVELLO; : CITTA from F where COD = : COD ; } Aggiornamento: aumento del livello LIV di una quantita pari a VALORE di tutti i fornitori F di 'Modena' exec sql update F set LIV = LIV + : VALORE where CITTA = 0 Modena 0 ; BASI DI DATI 4

Operazioni su singolo record (2) } Cancellazione: rimozione degli ordini O eseguiti dai fornitori F nella propria CITTA exec sql delete from O where CITTA = ( select CITTA from F where F:COD = O:COD) ; } Inserimento: inserimento di un articolo A con codice :A COD, nome :NOME e peso :PESO exec sql insert into A(COD; NOME; PESO) values (: A COD; : NOME; : PESO) ; BASI DI DATI 5

Operazioni con Cursore (1) } Un cursore e una variabile associata a uno statement SELECT che assume come possibili valori le tuple risultanti dall'esecuzione dello statement stesso. } Ogni cursore viene dichiarato associandolo a uno specico statement SELECT: DECLARE <cursor name> CURSOR FOR <select clause>; } La query non viene eseguita all'atto della sua dichiarazione, ma solo quando il cursore viene aperto. OPEN <cursor name>; } Quando e aperto, il cursore identica una sequenza ordinata di righe, e una specica posizione all'interno dell'ordinamento: sopra una specica riga prima di una specica riga dopo l'ultima riga. L'esecuzione dello statement OPEN posiziona il cursore prima della prima tupla. BASI DI DATI 6

Operazioni con Cursore (2) } L'istruzione FETCH <cursor name> INTO <target list>; genera l'avanzamento del cursore alla riga successiva e la copia dei valori della tupla corrente nelle variabili della <target list> corrispondenti alle colonne indicate nella <select clause>. } Dopo l'esecuzione di n FETCH, pari alla cardinalita del risultato, il cursore e posizionato dopo l'ultima tupla e SQLCODE assume il valore 100. } Quando tutte le righe sono state esaminate possiamo disattivare il cursore con lo statement CLOSE <cursor name>; BASI DI DATI 7

Esempio di utilizzo del Cursore Esempio: Calcolare la media voto di partenza per la tesi di laurea dello studente avente matricola '1234' (media calcolata su tutti esami scartando i due voti peggiori). Disponendo della tabella ESAME, selezioniamo gli esami (con i relativi voti) sostenuti dallo studente in questione. select COD CORSO; VOTO from ESAME where MATRICOLA = 0 1234 0 Volendo trasferire il risultato, una tupla alla volta, alle variabili di programma CORSO e VOTO si introduce un cursore, Cur Esame, che permette di scandire le tuple secondo l'ordine con cui vengono prodotte in fase di esecuzione. Operando algebricamente sui VOTI si puo calcolare la media. ESAME.CORSO Analisi 28 Cur Esame! Fisica I 26 Chimica 30 ESAME.VOTO BASI DI DATI 8

Selezione con Cursore exec sql declare Cur Esame cursor for select COD CORSO, VOTO from ESAME where MATRICOLA = '1234' order by VOTO DESC; for (i=1;i<28;i++) f exec sql fetch Cur Esame into :CORSO,:VOTO; somma voto += VOTO; g media voto = somma voto / 27 * 11 / 3; BASI DI DATI 9

Dichiarazioni di variabili Gli statement Embedded SQL utilizzano variabili C per trasferire dati dal database verso il programma (e viceversa). Tali variabili sono denite in un'apposita sezione: exec sql begin declare section; Dichiarazione di variabili e tipi in linguaggio C exec sql end declare section; La denizione della variabili Embedded SQL puo essere sia globale (esterna alle funzioni e procedure), sia locale, al pari delle comuni variabili C. Tutte le variabili utilizzate in statement embedded vengono denite in una sezione. I tipi di dati accettati dal preprocessore SQL sono i medesimi di quelli presenti nel linguaggio C (per ciascun DBMS esiste una tabella di compatibilita di tipi data tra Embedded SQL e C). BASI DI DATI 10

Utilizzo di etichette } E possibile denire etichette referenziabili, aventi le seguenti caratteristiche: Una label inizia con una lettera (o underscore ' ') E la prima parola di una riga Termina con i due punti ':' Esempio: close cursor: exec sql close cursor1; } Una label non puo precedere una dichiarazione: Esempio: include sqlca: exec sql include sqlca; /* errata */ In generale, e bene utilizzare le label solo in statement di comandi di esecuzione. BASI DI DATI 11

L'utilita DCLGEN L'utilita DCLGEN (Declaration Generator) permette di generare automaticamente una struttura C a partire da una tabella di database. dclgen language dbname tablename filename structname; language e l'host language (nel nostro caso il C) dbname e il nome del database contenente al tabella tablename e il nome della tabella da tradurre structname e il nome della struttura generata. Il tag della struttura e dato da structname seguito da underscore. Esempio: Supponendo che esista la tabella studente nel database Universita e' possibile scrivere: dclgen c Universita studente studente.dcl st rec; BASI DI DATI 12

L'utilita DCLGEN (2) Il comando crea il le 'studente.dcl' che contiene la dichiarazione della tabella e della struttura C corrispondente: /* Description of table studente from database universita */ EXEC SQL DECLARE studente TABLE (MATRICOLA integer not null, COGNOME char(15), NOME char(15), MEDIA_LAUREA float); struct st_rec_ { long MATRICOLA; char COGNOME[16]; char NOME[16]; double MEDIA_LAUREA; } st_rec; Per includere il le nei nostri programmi, durante la dichiarazione delle variabili utilizziamo include: exec sql begin declare section; exec sql include 'studente.dcl'; exec sql end declare section; Ora e' possibile utilizzare la struttura st rec come variabile nei comandi embedded SQL. BASI DI DATI 13

SQL Communications Area SQLCA e la struttura dati predenita per la gestione degli errori generati in ambiente SQL. L' istruzione exec sql include sqlca; specica al preprocessore di includere la variabile sqlca che contiene le informazioni di sistema relative all'ultima istruzione SQL eseguita. sqlca contiene (tra gli altri) i campi: sqlcode: specica lo stato di ritorno di una istruzione SQL 0 esecuzione corretta < 0 situazione di errore 100 risultato vuoto sqlwarn: struttura di 8 campi (sqlwarn0... sqlwarn7) con le warning relative alle ultime istruzioni eseguite sqlerrd[6]: il terzo campo [2] indica il numero di tuple coinvolte durante l'ultima esecuzione. BASI DI DATI 14

Utilizzo di sqlca per Error Handling (1) exec sql whenever condition action; dove: condition assume uno tra i valori sqlwarning, sqlerror, not found action assume uno tra i valori continue, stop, goto label, call C procedure Condition possibili: sqlwarning: indica che l'ultima istruzione SQL Embedded eseguita ha prodotto una warning. La variabile sqlwarn0 di SQLCA vale W. E quindi possibile specicare azioni condizionate a warning del DBMS. sqlerror: indica che l'ultima istruzione SQL Embedded eseguita ha prodotto un errore. La variabile sqlcode di SQLCA ha valore negativo. not found: indica che l'istruzione di select, update, insert, delete,... non ha avuto eetto su alcuna riga. La variabile sqlcode di SQLCA e posta a 100. BASI DI DATI 15

Utilizzo di sqlca per Error Handling (2) Action possibili: continue: continua l'esecuzione a partire dalla prossima istruzione. Nel caso di fatal error viene visualizzato un messaggio di errore e il programma termina. stop: viene visualizzato un messaggio di errore e il programma termina. Nel caso in cui il database sia connesso quando la condizione e raggiunta la terminazione non esegue il commit delle operazioni compiute. L'azione di stop non puo essere eseguita per la condizione di not found. goto label: trasferisce il controllo del programma alla label specicata. call procedure: chiama la procedura specicata. Nessun argomento puo essere passato nella chiamata. Esiste una procedura di sistema sqlprint che visualizza un messaggio riguardante l'errore o la warning occorsa e ritorna, che quindi puo' essere utilizzata per informare l'utente dell'errore e continuare (call sqlprint). Ciascuna action ha eetto sulle istruzioni Embedded SQL no alla successiva whenever. BASI DI DATI 16

Compilare un programma Embedded C/SQL unix Passi necessari (INGRES): } Eseguire la precompilazione da embedded SQL a C: Il preprocessore e' chiamato esqlc esqlc <lename> Preprocessa <lename>.sc e genera <lename>.c } Compilare il codice C ottenuto cc -c <filename>.c } Linkare i codici oggetto con le librerie del DBMS cc -o <filename> <filename>.o $II SYSTEM/ingres/lib/libingres.a -lm -lc BASI DI DATI 17

#include <stdlib.h> #include <string.h> #include <stdio.h> Esempio Completo /* Inclusione dell'area di comunicazione */ exec sql include sqlca; main() /* Calcolo della media di laurea degli studenti di Ingegneria */ { int code_c_esami; int somma_voto, cont; /* La section e' l'area di definizione delle variabili utilizzate dal DB */ exec sql begin declare section; int n_esami; float media_laurea; long matricola_attuale; exec sql include 'esame.dcl'; exec sql include 'studente.dcl'; exec sql end declare section; BASI DI DATI 18

/* in caso di errore termina */ exec sql whenever sqlerror stop; /* Connessione al Database */ exec sql connect universita; /* Dichiarazione del cursore */ exec sql declare c_esami cursor for select COD_CORSO, MATRICOLA, VOTO from esame order by MATRICOLA, VOTO DESC; /* Apertura del cursore */ exec sql open c_esami; /* Caricamento del cursore nelle variabili */ exec sql fetch c_esami into :es_rec.cod_corso, :es_rec.matricola, :es_rec.voto; code_c_esami = sqlca.sqlcode; /* scansione sequenzialmente il cursore */ while (code_c_esami == 0) { somma_voto = 0; BASI DI DATI 19

/* conteggio esami superati da uno studente */ exec sql select count(*) into :n_esami from esame where MATRICOLA = :es_rec.matricola; matricola_attuale = es_rec.matricola; cont = 1; /* totale esami scartando i due peggiori */ while (es_rec.matricola == matricola_attuale && code_c_esami == 0 ) { /* sommatoria degli N-2 esami sostenuti */ if (cont <= (n_esami-2)) { cont++; somma_voto += es_rec.voto; } /* caricamento esame successivo */ exec sql fetch c_esami into :es_rec.cod_corso, :es_rec.matricola, :es_rec.voto; code_c_esami = sqlca.sqlcode; } /* calcolo punteggio laurea */ media_laurea = (float) somma_voto/ (n_esami-2) * 11 / 3; BASI DI DATI 20

/* aggiornamento della media dello studente */ exec sql update STUDENTE set MEDIA_LAUREA = :media_laurea where MATRICOLA = :matricola_attuale; } exec sql close c_esami; exec sql commit; /* Dichiarazione del cursore */ exec sql declare c_stud cursor for select * from STUDENTE order by MEDIA_LAUREA desc; /* Apertura del cursore */ exec sql open c_stud; /* Caricamento del cursore nelle variabili */ exec sql fetch c_stud into :st_rec; printf("punteggio DI PARTENZA IN SEDE DI \ LAUREA DEGLI STUDENTI DI INGEGNERIA\n MATRICOLA\tCOGNOME\t\tNOME\t\tPUNTEGGIO\n''); while (sqlca.sqlcode == 0) { BASI DI DATI 21

printf("%d\t\t%s\t%s\t%f\n", st_rec.matricola, st_rec.cognome, st_rec.nome, st_rec.media_laurea); exec sql fetch c_stud into :st_rec; } exec sql close c_stud; /* chiusura database */ exec sql disconnect; } Embedded SQL BASI DI DATI 22

SQL SERVER e la programmazione C E possibile eseguire istruzioni di SQL Server da un programma C utilizzando il linguaggio Embedded SQL. Congurazione: 1. Connessione a SQL Server; 2. Memorizzazione delle istruzioni SQL in un buer ed invio a SQL Server; 3. Utilizzo del risultato: e possibile processare una riga per volta (utilizzo di cursori), memorizzare i dati in variabili di programma; 4. Gestione gli errori utilizzando le opportune librerie; 5. Sconnessione dal Server. BASI DI DATI 23

Esempio con SQL Server #include <stddef.h> #include <stdio.h> #include "gcutil.h" // GLOBAL VARIABLES int main ( int argc, char** argv, char** envp) { int nret; // for return values EXEC SQL BEGIN DECLARE SECTION; // for CONNECT TO char szserverdatabase[(sqlid_max * 2)+2] = ""; char szloginpassword[(sqlid_max * 2)+2] = ""; char objtype[3] = "U"; char au_name[21]; char city_name[21]; char cmd[] = "select au_lname, city _ from pubs.authors where state = 'CA'"; BASI DI DATI 24

EXEC SQL END DECLARE SECTION; Embedded SQL // install Embedded SQL for C error handler EXEC SQL WHENEVER SQLERROR CALL ErrorHandler(); // set Embedded SQL for C options EXEC SQL SET OPTION LOGINTIME 10; EXEC SQL SET OPTION QUERYTIME 100; // get info for CONNECT TO statement nret = GetConnectToInfo(argc, argv, szserverdatabase, szloginpassword); if (!nret) { return (1); } // attempt connection to SQL Server EXEC SQL CONNECT TO :szserverdatabase USER :szloginpassword; if (SQLCODE == 0) { printf("connection established\n"); } else { // problem connecting to SQL Server printf("error: Connection failed\n"); return (1); } EXEC SQL SET CURSORTYPE CUR_STANDARD; BASI DI DATI 25

EXEC SQL DECLARE C1 CURSOR FOR stmt1; Embedded SQL EXEC SQL PREPARE stmt1 FROM :cmd; EXEC SQL OPEN C1; // perform until sqlcode not = zero. while (SQLCODE == 0) { EXEC SQL FETCH C1 INTO :au_name, :city_name; if (SQLCODE == 0) printf("%s %s\n", au_name, city_name); } // Close cursor EXEC SQL CLOSE C1; // disconnect from SQL Server EXEC SQL DISCONNECT ALL; return (0); } BASI DI DATI 26

Esempio di utilizzo di Cursori /* Il programma manipola i dati di un database relativo ad una libreria: viene applicato uno sconto del 20% ai negozi con vendite maggiori di 50 e del 10% a quelli comprese tra 10 e 50 */ DECLARE @tid char(6), -- Title ID. @dtype varchar(40), -- Discount Type. @sid char(4), -- Store ID. @totsold int -- Total Sold. SELECT @tid = 'PS2091' SELECT @dtype = (@tid + ' Book Discount') USE pubs DECLARE SalesDiscnt CURSOR FOR SELECT st.stor_id, SUM(qty) AS 'Total Units Sold' BASI DI DATI 27

FROM stores st INNER JOIN sales s ON st.stor_id = s.stor_id INNER JOIN titles t ON t.title_id = s.title_id WHERE ord_date BETWEEN '1/1/1998' AND '12/31/1998' AND t.title_id = @tid GROUP BY st.stor_id Embedded SQL OPEN SalesDiscnt FETCH NEXT FROM SalesDiscnt INTO @sid, @totsold WHILE (@@FETCH_STATUS <> -1) BEGIN IF @totsold > 50 BEGIN INSERT discounts (discounttype, stor_id, discount) VALUES (@dtype, @sid, 20) END ELSE IF @totsold >= 20 AND @totsold <= 50 BEGIN INSERT discounts (discounttype, stor_id, discount) VALUES (@dtype, @sid, 10) BASI DI DATI 28

END FETCH NEXT FROM SalesDiscnt INTO @sid, @totsold END Embedded SQL DEALLOCATE SalesDiscnt BASI DI DATI 29