{"id":1,"date":"2023-04-11T16:18:58","date_gmt":"2023-04-11T16:18:58","guid":{"rendered":"https:\/\/www.suffritti.it\/?p=1"},"modified":"2023-04-11T17:19:57","modified_gmt":"2023-04-11T17:19:57","slug":"hello-world","status":"publish","type":"post","link":"https:\/\/www.suffritti.it\/?p=1","title":{"rendered":"Appunti sui database relazionali e sul linguaggio SQL"},"content":{"rendered":"\n<BODY text=#000000 vLink=#800080 aLink=#0000ff link=#0000ff bgColor=#ffffff>\n<H1><FONT color=#0000ff>Appunti sui DataBase Relazionali e sul linguaggio \nSQL<\/FONT><\/H1><B><TT><FONT size=+1>Autore Pietro \nSuffritti&nbsp;<\/FONT><\/TT><\/B> \n<P><B><TT><FONT size=+1>Versione 1.1, pubblicata il 27\/01\/2004 sulla base della 1.0 del 15\/02\/2002<\/FONT><\/TT><\/B><\/P>\n<P><B><TT><FONT color=#ff0000>basato in origine sul documento &#8220;Introduction to \nStructured Query Language ver. 4.71&#8221; di James Hoffmann, poi pesantemente rielaborato e riscritto, reperibile all&#8217; URL <A \nhref=\"http:\/\/w3.one.net\/~jhoffman\/sqltut.htm\">HTTP:\/\/w3.one.net\/~jhoffman\/sqltut.htm<\/A>&nbsp;<\/FONT><\/TT><\/B><\/P>\n<P>Queste pagine nascono a causa della richiesta rivoltami dai membri dell&#8217; \nERLUG di Modena di tenere un corso introduttivo sull&#8217; SQL ANSI (un grazie \nparticolare a quel rompiscatole di Andrea &#8220;Andy&#8221; Papotti che con le sue battute \ne richieste mi ha spinto a fare questa robaccia).&nbsp;\n<P>Non avendo io la minima esperienza n\u00e9 di SQL ANSI (normalmente ammetto di \nlavorare con il transact-sql di SQLServer 7.0) n\u00e9 tantomeno di corsi ho \nricercato su internet una guida introduttiva all&#8217; SQL ANSI su cui basarmi ed ho \ntrovato l&#8217;ottima &#8220;Introduction to Structured Query Language&#8221; di James Hoffmann a \ncui ho attinto a piene mani per sviluppare questi appunti, ampliandoli con una \ndisgressione su cos&#8217;\u00e8 un database e traducendoli in italiano. Spero di non avere \nintrodotto troppi errori, ma tengo a precisare che il medesimo James Hoffmann mi \nha autorizzato via mail a fare tutto ci\u00f2. Presto vedr\u00f2 di tradurre anche \npedissequamente il suo documento e metterlo sempre qui, distaccando quindi in \nseguito questo documento sempre di pi\u00f9 dal suo originale, ed aggiungendovi nuove \nsezioni. In ogni caso riconosco al suddetto quanto di buono pu\u00f2 esserci in \nquesto documento mentre mi assumo la colpa di qualsiasi boiata io possa avervi \nintrodotto,e come nel documento originale vi segnalo l&#8217; esistenza di un SQL Club \nnell&#8217; area forum di Yahoo rintracciabile a questo link:&nbsp; <A \nhref=\"http:\/\/clubs.yahoo.com\/clubs\/structuredquerylanguage\">SQL Club on \nYahoo!<\/A> . \n<P>&nbsp;Voglio comunque chiarire che era mia intenzione creare un documento in \ncui la semplicit\u00e0 di comprensione fosse INCREDIBILMENTE pi\u00f9 importante della \nprecisione (di manuali di SQL e&#8217; pieno il mondo, se dovete usarlo davvero fate \nriferimento a quelli), per cui invoco la clemenza della corte per le incredibili \nsemplificazioni che ho qui utilizzato nel tentativo (orrore!) di uscire dal \nlinguaggio tecnico per avvicinarmi a qualcosa che anche mia madre, insegnante di \nscuola materna dotata di un ottimo cervello ma di preparazione informatica quasi \nnulla, potesse comprendere. Spero che i tecnici mi perdoneranno e che i non \ntecnici possano trarne un qualche vantaggio.<\/P>\n<P>Ringrazio Decio Biavati per avermi aiutato traducendo l&#8217; ultimo pezzettino \nresiduo del documento di Hoffmann ancora presente in inglese. Colgo l&#8217; occasione \nper dirgli per\u00f2 che se invece che in formato doc l&#8217; avesse fatto in html avrei \napprezzato ancora di pi\u00f9 \ud83d\ude42<\/P>\n<HR>\n<B><FONT color=#800080 size=+2>Indice<\/FONT><\/B> \n<BLOCKQUOTE>\n  <P><A \n  href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#INTRODUZIONE SUI DATABASE\">Introduzione \n  sui database<\/A>&nbsp;<BR><A \n  href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#cos'e' un database\">Cos&#8217;e&#8217; un \n  database?<BR><\/A><A \n  href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Piccola storia dei database assolutamente incompleta\">Piccola \n  storia dei database assolutamente incompleta<\/A><\/P>\n  <P><A href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#I Database Relazionali\">I \n  DataBase Relazionali<BR><\/A><A \n  href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#SQL questo sconosciuto\">SQL \n  questo sconosciuto<BR><\/A><A \n  href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Commit e Rollback, ovvero come limitare i danni\">Commit \n  e Rollback, ovvero come limitare i danni<BR><\/A><A \n  href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#I Semafori , ovvero la gestione della multiutenza\">I \n  Semafori , ovvero la gestione della multiutenza<\/A><\/P>\n  <P><A href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Il Linguaggio SQL\">Il \n  Linguaggio SQL<\/A><\/P><\/BLOCKQUOTE>\n<DIR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Basi del comando SELECT\">Basi del \ncomando SELECT<BR><\/A>&nbsp;&nbsp;&nbsp; <A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Selezione Condizionata\">Selezione \nCondizionata<\/A> <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Operatori Relazionali\">Operatori \nRelazionali<\/A> <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Condizioni piu' complesse: Condizioni multiple e Operatori Logici\">Condizioni \npi\u00f9 complesse: Condizioni multiple e Operatori Logici<\/A>&nbsp; \n<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#IN , BETWEEN e NOT\">IN, BETWEEN e \nNOT<BR><\/A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#IN , BETWEEN e NOT\"> <\/A><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Utilizzare la clausola LIKE ed il carattere jolly\">Utilizzare \nla clausola LIKE ed il carattere jolly %<\/A><BR>&nbsp;&nbsp;&nbsp;<A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Joins\"> I \nJoin<BR><\/A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Le Chiavi\">Le \nChiavi<BR><\/A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Creare un Join\">Creare un \nJoin<BR><\/A>&nbsp;&nbsp;&nbsp;<I><B> <\/B><\/I><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Clausola DISTINCT e l'Eliminazione dei Duplicati\">Clausola \nDISTINCT e l&#8217;Eliminazione dei Duplicati<\/A><BR>&nbsp;&nbsp;&nbsp; <A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Alias, In e l' utilizzo delle Subquery\">Alias, \nIn e l&#8217;utilizzo delle Subquery<\/A> \n<P><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Funzioni di Aggregazione\">Funzioni \ndi Aggregazione<BR><\/A><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Viste\">Viste<\/A><BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Creare Nuove Tabelle\">Creare Nuove \nTabelle<\/A><BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Modificare la struttura delle tabelle\">Modificare \nla struttura delle tabelle <BR><\/A><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Inserire dati in una tabella\">Inserire \ndati in una tabella<\/A><BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Cancellare dati da una tabella\">Cancellare \ndati da una tabella<\/A><BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Modifica dei dati\">Modifica dei \ndati<\/A> \n<P><A href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Gli Indici\">Gli \nIndici<\/A><BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#GROUP BY &amp; HAVING\">GROUP BY ed \nHAVING<\/A> <BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Altre Subquery\">Altre Subquery<\/A> \n<BR><A href=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#EXISTS ed ALL\">EXISTS ed \nALL<\/A> <BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#UNION ed Outer Joins\">UNION ed \nOuter Joins<\/A> <BR><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Sommario della Sintassi - Solo per veri masochisti\">Sommario \ndella Sintassi &#8211; Solo per veri masochisti<BR><\/A><A \nhref=\"http:\/\/www.suffritti.it\/SQLTutorial.htm#Sommario dei Link relativi all' SQL\">Sommario \ndei Link relativi all&#8217; SQL<\/A>&nbsp;<\/P><\/DIR>\n<HR>\n\n<P><B><FONT size=+2><A name=\"INTRODUZIONE SUI DATABASE\">INTRODUZIONE SUI \nDATABASE<\/A><\/FONT><\/B><\/P>\n<P><B><FONT size=+2><A name=\"cos'e' un database\">cos&#8217;\u00e8 un \ndatabase<\/A><\/FONT><\/B><\/P>\n<P>In tutti i corsi che io ho frequentato la definizione di cosa sia un database \n\u00e8 stata o allegramente saltata (dando per scontato che tutti sapessero di cosa \nsi stava parlando) o definita con un criptico linguaggio pseudomatematico per me \ndi difficile comprensione, pertanto tento di esporre qui quello che io ho capito \nessere un database (con buona pace di professori e puristi dell&#8217; \ninformatica)<\/P>\n<P>Al di l\u00e0 dei termini complessi e da iniziati un database (del tipo &#8220;un \ninsieme strutturato di dati che in un momento n fornisce una rappresentazione \nsemplificata di una realt\u00e0 in evoluzione&#8221;) un database non \u00e8 altro che una \nspecie di &#8220;contenitore&#8221; che ci permette di gestire grossi quantitativi di \ninformazioni simili in maniera ordinata e (si spera) pi\u00f9 semplice e veloce che \ncon grossi libroni cartacei o documenti di tipo foglio di calcolo o \ntesto.&nbsp;&nbsp;<\/P>\n<P><B><FONT size=+2><A \nname=\"Piccola storia dei database assolutamente incompleta\">Piccola storia dei \ndatabase assolutamente incompleta<\/A><\/FONT><\/B><\/P>\n<P>Probabilmente il pi\u00f9 glorioso (ed a tutt&#8217; oggi utilizzato) antenato dei \ndatabase relazionali odierni pu\u00f2 essere identificato con la sana e vecchia \nagenda&nbsp; telefonica. in effetti penso che se guardiamo come \u00e8 fatta la \nnostra agenda scopriremo una notevole affinit\u00e0 con i sui parenti pi\u00f9 tecnologici \nattuali. Infatti \u00e8 organizzata tramite un indice (la serie di linguette sul \nfianco che ci permette di accedere pi\u00f9 rapidamente a tutti i nominativi che \niniziano con una certa lettera) che gestisce una tabella composta da colonne che \nidentificano il tipo di dato sotto riportato (nome, numero di telefono, a volte \nindirizzo) all&#8217; interno delle registrazioni (vogliamo chiamarle con il termine \ninglese &#8220;record&#8221;?) che , pur differendo l&#8217; una dall&#8217; altra per i dati riportati \nal loro interno &#8220;hanno tutti la stessa struttura&#8221;, cio\u00e8 riportano le stesse \ninformazioni nella medesima maniera.<\/P>\n<P>Il primo tentativo di cui io sono a conoscenza compiuto dagli informatici per \nriversare questo tipo di oggetti in un &#8220;coso&#8221; trattabile dalle loro grosse \ncalcolatrici corrisponde al nome di CSV (Comma Separated Value), cio\u00e8 un \nbanalissimo file di testo dove ogni informazione (numero di telefono di pino, \nnome di gino, indirizzo di tino) \u00e8 separata dalle altre tramite un carattere \nparticolare (normalmente una virgola) ed ogni record (vedi definizione spora \nriportata, cio\u00e8 la riga della nostra agenda) \u00e8 separato dagli altri tramite un&#8217; \naltro carattere (normalmente il carattere di &#8220;a capo&#8221;). Ovviamente questo \nsistema era decisamente embrionale, in quanto comunque per trovare all&#8217; interno \ndi un file del genere una informazione specifica era spesso necessario \nscorrerselo quasi tutto ed in modo poco pratico per trovare quanto si \nricercava.<\/P>\n<P>la logica evoluzione del CSV fu l&#8217;ISAM (Indexed Sequential Access Method), \nche differiva dal CSV solo per il fatto che i record non erano &#8220;buttati dentro a \ncasaccio&#8221; (cio\u00e8 in ordine di inserimento), bens\u00ec veniva definito un ordinamento \n(tipicamente nel caso della nostra agenda l&#8217; ordine alfabetico sui cognomi) che \nveniva sfruttato sia in scrittura (&#8220;dove devo mettere il record del telefono di \nAnna?&#8221; &#8220;sotto la lettera A tra Anita ed Antonio&#8221;) sia in lettura (&#8220;dove hai \ninfilato il numero di telefono di Pietro?&#8221; &#8221; lettera P, tra Paolo e Pinocchio&#8221;) \npermettendo in questo modo di abbreviare incredibilmente i tempi di ricerca di \nuna data informazione. Per riuscire poi a gestire ancora meglio il tutto si \ncrearono&nbsp; anche delle specie di &#8220;archivi sussidiari&#8221;, detti indici, in cui \nveniva registrato solo l&#8217; ordine dei vari record senza tutte le altre \ninformazioni, il che permetteva di andare a svolgere le proprie ricerche in \nquesto &#8220;riassunto&#8221; in modo molto pi\u00f9 veloce (meno roba da leggere=ci metto di \nmeno a leggerla) e poi &#8220;puntare diritti&#8221; sul database completo per leggere tutto \nil record una volta che si sapeva dov&#8217;era<\/P>\n<P>A questo punto parecchi matematici di notevole ingegno si misero a cercare \nmetodi per rendere ancora pi\u00f9 veloce l&#8217; accesso alle informazioni che ci \nservivano sfornando sistemi di ricerca dai nomi fantasiosi come &#8220;ricerca \ndicotomica&#8221; o &#8221; a farfalla&#8221; (che non \u00e8 nostro interesse qui approfondire) , \nsviluppando cos\u00ec tutti quei sistemi oggi definiti &#8220;Database non relazionali&#8221; (in \ncontrapposizione ai database relazionali che vedremo dopo) di cui forse i pi\u00f9 \nfamosi sono stati i database B-Trieve e DBIII-like (clipper, DBIII, DBIV \necc)<\/P>\n<P>con l&#8217;evoluzione di questi ultimi i database ebbero una notevole diffusione e \nquindi iniziarono a nascere richieste di affidabilit\u00e0 e di prestazioni sempre \nmaggiori, con uno sviluppo teorico notevole dietro ad essi, che permetteva a \nquesto punto di affrontare diversi problemi, di cui di seguito elenco quelli pi\u00f9 \nconosciuti (forse da me: sicuramente un teorico dei database potr\u00e0 aggiungerne \naltri milioni). sia chiaro, alcuni di questi problemi venivano egregiamente \naffrontati dai database non relazionali, ma raramente tutti insieme ed in \nmaniera affidabile<\/P>\n<OL>\n  <LI>La ridondanza dei dati:<BR>ergo &#8220;ma non esiste proprio un modo per evitare \n  di rimettere nel mio database della contabilit\u00e0 duemila volte l&#8217; indirizzo del \n  mio cliente principale?&#8221; \n  <LI>L&#8217; uniformit\u00e0 dei dati<BR>&#8220;oddio, come ho chiamato la Johns Coopers and \n  Lybrand Incorporated l&#8217; ultima volta? JCL? J.C.L. ? J.C.L Inc.? J.C.&amp; L. \n  Inc?&#8221; \n  <LI>L&#8217;indipendenza dalla piattaforma<BR>&#8220;scusa Aristide, ti ricordi sul tuo \n  sistema come devo fare per vedere il contenuto di una tabella? perch\u00e9 su \n  quello di Asdrubale devo fare cos\u00ec, su quello di Antonio cos\u00e0 e sul mio in un \n  modo completamente diverso&#8221; \n  <LI>La sicurezza delle transazioni<BR>&#8220;ARGH! stavo mettendo dentro al database \n  tutte le fatture dell&#8217; ultimo semestre quando \u00e8 andata via la corrente ed \n  adesso non so se l&#8217; ultima me l&#8217; ha presa o no! cosa faccio, devo ricostruire \n  l&#8217; intera tabella delle fatture per essere certo che non ci siano valori doppi \n  o inseriti a met\u00e0??&#8221; \n  <LI>La possibilit\u00e0 di gestire correttamente un ambiente multiutente<BR>&#8220;Mi \n  spieghi perch\u00e9 io sono certo di avere inserito l&#8217; ordine per le ultime dieci \n  scatole di pirulazio a nome del mio miglior cliente e quelle sono finite \n  invece al peggior cliente di un&#8217; altro commerciale? eppure SO di averle \n  fermate al magazzino io per primo..&#8221; <\/LI><\/OL>\n<P>Per risolvere tutti questi problemi in maniera soddisfacente si \u00e8 dovuto \ncambiare il modo di &#8220;pensare&#8221; i database, portando cos\u00ec alla nascita dei \ndatabase relazionali<\/P>\n<P>&nbsp;<\/P>\n<P><B><FONT size=+2><A name=\"I Database Relazionali\">I Database \nRelazionali<\/A><\/FONT><\/B><\/P>\n<P>allora cosa sono questi famigerati Database relazionali? il concetto che sta \nalla base \u00e8 , come spesso succede nell&#8217; informatica, molto meno &#8220;strampalato&#8221; di \nquello che si pensa: invece di fare un&#8217; enorme tabella in cui \u00e8 contenuto TUTTO \nil database si divide lo stesso in tante tabelle che contengono dati logicamente \ncorrelati e per metterle insieme si usano delle relazioni tra l&#8217; una e l&#8217; altra \ntabella. vediamo di fare un qualche esempio per capirci meglio.<\/P>\n<P>Per il nostro esempio prenderemo in esame il database di una piccola gestione \ndi una videoteca di famiglia.Vogliamo tenere registrati tutti i film che abbiamo \nin modo da sapere su di essi le seguenti informazioni:<\/P>\n<OL>\n  <LI>il titolo \n  <LI>il regista \n  <LI>l&#8217; attore protagonista \n  <LI>l&#8217; attrice protagonista \n  <LI>l&#8217; anno di uscita nelle sale del film \n  <LI>il tipo di supporto \n  <LI>se l&#8217; ho in casa o se l&#8217; ho prestato a qualcuno \n  <LI>a chi l&#8217; ho eventualmente prestato: nome, cognome e numero di telefono \n  <LI>il genere del film \n  <LI>se nostra figlia di 5 anni pu\u00f2 vederlo o non \u00e8 proprio il caso&nbsp; \n  <LI>un breve riassunto della trama <\/LI><\/OL>\n<P>nel modo &#8220;classico&#8221; avremmo realizzato un&#8217; unica &#8220;tabellona&#8221; pi\u00f9 o meno di \nquesto tipo:<\/P>\n<TABLE width=\"98%\" border=1>\n  <TBODY>\n  <TR>\n    <TD width=\"115%\" colSpan=13>\n      <P align=center>Videoteca<\/P><\/TD><\/TR>\n  <TR>\n    <TD width=\"4%\">cod<\/TD>\n    <TD width=\"25%\">titolo<\/TD>\n    <TD width=\"7%\">regista<\/TD>\n    <TD width=\"7%\">attore<\/TD>\n    <TD width=\"6%\">attrice<\/TD>\n    <TD width=\"5%\">anno<\/TD>\n    <TD width=\"7%\">supporto<\/TD>\n    <TD width=\"9%\">PrestNome<\/TD>\n    <TD width=\"8%\">PrestCogn<\/TD>\n    <TD width=\"11%\">PrestTel<\/TD>\n    <TD width=\"11%\">Genere<\/TD>\n    <TD width=\"7%\">VM18<\/TD>\n    <TD width=\"8%\">trama<\/TD><\/TR>\n  <TR>\n    <TD width=\"4%\">1<\/TD>\n    <TD width=\"25%\">l\u00e0 dove scorre il fiume<\/TD>\n    <TD width=\"7%\">Redford<\/TD>\n    <TD width=\"7%\">DeNiro<\/TD>\n    <TD width=\"6%\">Stone<\/TD>\n    <TD width=\"5%\">85<\/TD>\n    <TD width=\"7%\">DVD<\/TD>\n    <TD width=\"9%\">&nbsp;<\/TD>\n    <TD width=\"8%\">&nbsp;<\/TD>\n    <TD width=\"11%\">&nbsp;<\/TD>\n    <TD width=\"11%\">Dramma<\/TD>\n    <TD width=\"7%\">no<\/TD>\n    <TD width=\"8%\">xxx<\/TD><\/TR>\n  <TR>\n    <TD width=\"4%\">2<\/TD>\n    <TD width=\"25%\">Proposta indecente<\/TD>\n    <TD width=\"7%\">Spielberg<\/TD>\n    <TD width=\"7%\">Redford<\/TD>\n    <TD width=\"6%\">Pfeiffer<\/TD>\n    <TD width=\"5%\">91<\/TD>\n    <TD width=\"7%\">VHS<\/TD>\n    <TD width=\"9%\">Gigi<\/TD>\n    <TD width=\"8%\">Salvioli<\/TD>\n    <TD width=\"11%\">05808086<\/TD>\n    <TD width=\"11%\">sexy<\/TD>\n    <TD width=\"7%\">si<\/TD>\n    <TD width=\"8%\">yyy<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>in questo modo abbiamo registrato poche informazioni e di difficile uso. \nproviamo allora a ragionarci sopra e vediamo che vogliamo in realt\u00e0 registrare 3 \ndiversi tipi di dati, nella fattispecie:<\/P>\n<UL>\n  <LI>i dati della cassetta vera e propria: codice, titolo, supporto, genere, \n  vietata si\/no , trama \n  <LI>i dati di persone che lavorano nei film: regista, attore, attrice \n  <LI>i dati dei nostri amici a cui potremmo voler prestare la cassetta <\/LI><\/UL>\n<P>a questo punto prendiamo in mano un database relazionale e creiamo non una ma \ntre tabelle:<\/P>\n<TABLE width=\"92%\" border=1>\n  <TBODY>\n  <TR>\n    <TD width=\"105%\" colSpan=11>\n      <P align=center>Cassette<\/P><\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">CodCass<\/TD>\n    <TD width=\"17%\">Titolo<\/TD>\n    <TD width=\"8%\">CodReg<\/TD>\n    <TD width=\"7%\">CodAtt1<\/TD>\n    <TD width=\"8%\">CodAtt2<\/TD>\n    <TD width=\"6%\">Anno<\/TD>\n    <TD width=\"8%\">Supporto<\/TD>\n    <TD width=\"10%\">CodPrest<\/TD>\n    <TD width=\"8%\">Genere<\/TD>\n    <TD width=\"8%\">VM18<\/TD>\n    <TD width=\"17%\">trama<\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">1<\/TD>\n    <TD width=\"24%\">l\u00e0 dove scorre il fiume<\/TD>\n    <TD width=\"8%\">1<\/TD>\n    <TD width=\"7%\">2<\/TD>\n    <TD width=\"8%\">3<\/TD>\n    <TD width=\"6%\">85<\/TD>\n    <TD width=\"8%\">DVD<\/TD>\n    <TD width=\"10%\">0<\/TD>\n    <TD width=\"8%\">dramma<\/TD>\n    <TD width=\"8%\">no<\/TD>\n    <TD width=\"17%\">xxx<\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">2<\/TD>\n    <TD width=\"24%\">Proposta indecente<\/TD>\n    <TD width=\"8%\">4<\/TD>\n    <TD width=\"7%\">1<\/TD>\n    <TD width=\"8%\">5<\/TD>\n    <TD width=\"6%\">85<\/TD>\n    <TD width=\"8%\">VHS<\/TD>\n    <TD width=\"10%\">1<\/TD>\n    <TD width=\"8%\">Sexy<\/TD>\n    <TD width=\"8%\">SI<\/TD>\n    <TD width=\"17%\">yyy<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>&nbsp;<\/P>\n<TABLE width=\"28%\" border=1>\n  <TBODY>\n  <TR>\n    <TD width=\"81%\" colSpan=4>\n      <P align=center>Personaggi del cinema<\/P><\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">CodPers<\/TD>\n    <TD width=\"12%\">Cognome<\/TD>\n    <TD width=\"1%\">Nome<\/TD>\n    <TD width=\"60%\">VintoOscar<\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">1<\/TD>\n    <TD width=\"12%\">Redford<\/TD>\n    <TD width=\"1%\">Robert<\/TD>\n    <TD width=\"60%\">si<\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">2<\/TD>\n    <TD width=\"12%\">DeNiro<\/TD>\n    <TD width=\"1%\">Robert<\/TD>\n    <TD width=\"60%\">si<\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">3<\/TD>\n    <TD width=\"12%\">Stone<\/TD>\n    <TD width=\"1%\">Sharon<\/TD>\n    <TD width=\"60%\">no<\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">4<\/TD>\n    <TD width=\"12%\">Spielberg<\/TD>\n    <TD width=\"1%\">Stephen<\/TD>\n    <TD width=\"60%\">si<\/TD><\/TR>\n  <TR>\n    <TD width=\"8%\">5<\/TD>\n    <TD width=\"12%\">Pfeiffer<\/TD>\n    <TD width=\"1%\">Michelle<\/TD>\n    <TD width=\"60%\">no<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>&nbsp;<\/P>\n<TABLE width=\"52%\" border=1>\n  <TBODY>\n  <TR>\n    <TD width=\"120%\" colSpan=5>\n      <P align=center>Amici<\/P><\/TD><\/TR>\n  <TR>\n    <TD width=\"9%\">CodAmico<\/TD>\n    <TD width=\"28%\">Cognome<\/TD>\n    <TD width=\"10%\">Nome<\/TD>\n    <TD width=\"16%\">Telefono<\/TD>\n    <TD width=\"57%\">Indirizzo<\/TD><\/TR>\n  <TR>\n    <TD width=\"9%\">0<\/TD>\n    <TD width=\"28%\">non prestata<\/TD>\n    <TD width=\"10%\">&nbsp;<\/TD>\n    <TD width=\"16%\">&nbsp;<\/TD>\n    <TD width=\"57%\">&nbsp;<\/TD><\/TR>\n  <TR>\n    <TD width=\"9%\">1<\/TD>\n    <TD width=\"28%\">Salvioli<\/TD>\n    <TD width=\"10%\">Gigi<\/TD>\n    <TD width=\"16%\">0547778899<\/TD>\n    <TD width=\"57%\">via Garibaldi 5<\/TD><\/TR>\n  <TR>\n    <TD width=\"9%\">2<\/TD>\n    <TD width=\"28%\">Persiceto<\/TD>\n    <TD width=\"10%\">Gennaro<\/TD>\n    <TD width=\"16%\">0547558877<\/TD>\n    <TD width=\"57%\">via Mazzini 6<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>in questo modo, oltre ad inserire molti pi\u00f9 dati abbiamo gi\u00e0 risolto due dei \nproblemi citati sopra: inseriremo una sola volta Robert de Niro per tutte le \nvolte che vorremo usarlo in punti differenti del nostro database ed avremo \nsempre la certezza di chiamarlo Redford, Robert e non r.redford,robertredford, \nRobert Redford ecc&#8230;<\/P>\n<P>in compenso abbiamo un problema : come faccio a capire che la cassetta di \nproposta indecente l&#8217; ho prestata a Gigi Salvioli e non ad un fantomatico signor \n1 ? risposta: tramite delle relazioni<\/P>\n<P>una delle cose che dovrebbe saltare immediatamente all&#8217; occhio guardando le \ntabelle dell&#8217; esempio \u00e8 il fatto che ogni record ha un suo codice univoco \n(spesso chiamato &#8220;chiave primaria&#8221; ) che identifica lui e solo lui (non ci sono \nn\u00e9 possono essere due personaggi del cinema con CodPers=1) e che tali codici \nvengono richiamati all&#8217; interno della tabella delle cassette: si pu\u00f2 quindi dire \nche ho stabilito una relazione tra i campi della tabella cassette CodReg, \nCodAtt1 e CodAtt2 e il campo CodPers della tabella personaggi del cinema, cos\u00ec \ncome ho stabilito una relazione tra CodAmico della tabella Amici e CodPrest \n(risolvendo peraltro il fastidio di avere caselle vuote per indicare che la \ncassetta \u00e8 in mio possesso). in questo modo tramite un apposito sistema di \ndefinizione delle relazioni si possono creare database estremamente complessi ma \ndi consultazione abbastanza semplice. con una appropriata gestione degli indici \nsulle tabelle inoltre si pu\u00f2 ottenere un tempo di accesso ai dati decisamente \nsoddisfacente<\/P>\n<P><B><FONT size=+2><A name=\"SQL questo sconosciuto\">SQL questo \nsconosciuto<\/A><\/FONT><\/B><\/P>\n<P>Abbiamo appena finito di dire che uno dei requisiti fondamentali per poter \nutilizzare un database relazionale e&#8217; avere un &#8220;linguaggio&#8221; che ci permetta di \ninterrogarlo in maniera opportuna, cosa che gli informatici (che complottano tra \ndi loro usando sigle strane per non farsi capire dai non iniziati) chiamano \nRDBMS, cio\u00e8 Relational DataBase Management System. come spesso succede nel mondo \ndell&#8217; informatica anche in questo caso e&#8217; nato uno &#8220;standard&#8221; che avrebbe \npermesso a tutti di parlare la stessa lingua, ed appena e&#8217; nato sono nati cos\u00ec \ntanti dialetti che non parlano l&#8217; uno con l&#8217;altro da potercisi affogare. Questo \nstandard si chiama ANSI SQL (Structured Query Language della American National \nStandard Institute), e ovviamente sebbene TUTTI dicano che il loro linguaggio e&#8217; \nANSI Compliant (compatibile con l&#8217; ansi SQL) in realt\u00e0 tutti hanno differenze \nsostanziali l&#8217; uno con l&#8217;altra. i pi\u00f9 diffusi linguaggi SQL oggi sono \n(ovviamente) quelle dei pi\u00f9 diffusi database, cio\u00e8<\/P>\n<UL>\n  <LI>Oracle SQL \n  <LI>Transact &#8211; SQL \n  <LI>PostgreSQL \n  <LI>MySQL \n  <LI>SQLInformix \n  <LI>DBII SQL \n  <LI>ecc&#8230; <\/LI><\/UL>\n<P>non potendo fare un corso su ognuno di essi (in primis perch\u00e9 molti non li \nconosco) noi faremo invece riferimento all&#8217; ANSI SQL. ma prima di partire con il \nlinguaggio soffermiamoci un&#8217; attimo sugli altri punti mancanti delle richieste \nche abbiamo fatto ai nostri database relazionali: la possibilit\u00e0 di riuscire a \nrecuperare la situazione in caso di guasto e di lavorare in un sistema \nmultiutente<\/P>\n<P><B><FONT size=+2><A \nname=\"Commit e Rollback, ovvero come limitare i danni\">Commit e Rollback, ovvero \ncome limitare i danni<\/A><\/FONT><\/B><\/P>\n<P>In tutti i database relazionali minimamente decenti esistono due comandi \nfondamentali che rispondono per l&#8217; appunto al nome di commit e rollback. questi \ndue comandi provvedono a fare in modo che una determinata operazione venga \neffettuata come un tutto unico o che non venga effettuata per niente. vediamo di \ncapire cosa significa.<\/P>\n<P>Mettiamo che voi stiate gestendo il database di una banca e che dobbiate \neffettuare un bonifico bancario; questa operazione in realt\u00e0 si divide in almeno \ndue distinte operazioni:<\/P>\n<OL>\n  <LI>aumentare il saldo del conto corrente del destinatario della cifra in \n  esame \n  <LI>diminuire il saldo del conto corrente del mittente della stessa cifra pi\u00f9 \n  quella dovuta per le commissioni <\/LI><\/OL>\n<P>ora, cosa succederebbe se a met\u00e0 dell&#8217; operazione il sistema avesse dei \nproblemi (stile corrente che salta, un errore logico come la mancanza del record \ndel destinatario, un processore fuso per il troppo calore,un impiegato impazzito \ncon grosso martellone che picchia sul server)? a seconda dell&#8217; ordine in cui le \neffettuate potete avere i seguenti risultati:<\/P>\n<OL>\n  <LI>i soldi vengono tolti dal cc del mittente e non arrivano in quello del \n  destinatario: risultato il destinatario del bonifico vuole il vostro sangue \n  <LI>i soldi NON vengono tolti dal cc del mittente, arrivano in quelli del \n  destinatario e la banca ce li rimette: risultato dovete cercarvi in fretta \n  un&#8217;altro lavoro DOPO averli sborsati voi <\/LI><\/OL>\n<P>entrambi i risultati non brillano per piacevolezza, ma per fortuna vi vengono \nincontro i due comandi suddetti. come funzionano?<\/P>\n<P>Quando si fa qualcosa che deve venire gestito come un tutt&#8217; uno si inizia la \nprocedura con una istruzione BEGIN TRANSACTION, che indica il punto di inizio \ndel nostro codice &#8220;a rischio&#8221; . a questo punto il nostro database non esegue pi\u00f9 \nle variazioni direttamente sul disco ma in una particolare area temporanea \n(normalmente in memoria) e se la tiene parcheggiata l\u00ec finch\u00e9&nbsp; non sente un \ncomando COMMIT. a quel punto in un&#8217; unica soluzione fa TUTTE le variazioni che \nha precalcolato in contemporanea. nel caso qualcosa andasse storto l&#8217; intera \ntransazione andrebbe persa e quindi il bonifico non verrebbe fatto, sicuramente \nuna situazione meno spiacevole di quella citata prima (anche perch\u00e9 pu\u00f2 venire \nrifatto). E&#8217; inoltre possibile forzare questo avvenimento tramite l&#8217; istruzione \nROLLBACK nel caso che il problema sia di tipo software (esempio ho gli estremi \ndel mittente ma in tabella non esiste il destinatario, quindi sebbene sia gi\u00e0 \npartito a togliere i soldi dal primo non posso metterli sul secondo) . un tipico \nesempio di gestione commit-rollback pu\u00f2 essere la seguente:<\/P>\n<P class=ex><CODE>BEGIN \nTRANSACTION;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ inizio della transazione&nbsp;&nbsp;&nbsp;&nbsp;<\/CODE><\/P>\n<P class=ex><CODE>USE \nbanca1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ utilizza il database di nome BANCA1<\/CODE><\/P>\n<P class=ex><CODE>UPDATE \nconticorrenti&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ aggiorna la tabella dei conti correnti<\/CODE><\/P>\n<P class=ex><CODE>SET saldo = saldo + 1000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \naggiungendo un milione al saldo<\/CODE><\/P>\n<P class=ex><CODE>WHERE ccn =&nbsp; \n181818&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ del conto corrente numero 181818<\/CODE><\/P>\n<P class=ex><CODE>ON ERROR \nROLLBACK;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ in caso di un qualunque errore effettua un rollback ed annulla \ntutto<\/CODE><\/P>\n<P class=ex><CODE>USE \nbanca2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ utilizza il database di nome BANCA2<\/CODE><\/P>\n<P class=ex><CODE>UPDATE \nconticorrenti&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ aggiorna la tabella dei conti correnti<\/CODE><\/P>\n<P class=ex><CODE>SET saldo = saldo &#8211; 1000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ \nsottraendo un milione al saldo<\/CODE><\/P>\n<P class=ex><CODE>WHERE ccn =&nbsp; \n161616;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ del conto corrente numero 161616<\/CODE><\/P>\n<P class=ex><CODE>ON ERROR \nROLLBACK;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ in caso di un qualunque errore effettua un rollback ed annulla \ntutto<\/CODE><\/P>\n<P \nclass=ex><CODE>COMMIT;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \n\/\/ effettua tutta la transizione in una volta<\/CODE><\/P>\n<P>attenzione, l&#8217; esempio fatto sopra e&#8217; un classico esempio di pi\u00f9 ISTRUZIONI \ninserite in un&#8217; unica transazione , ma in genere se non specifichiamo nulla ogni \nsingola istruzione viene gestita come una transazione a se stante, pertanto se \ndurante l&#8217; esecuzione della nostra update su due milioni di campi crolla il \nsistema, le procedure di ripristino provvederanno a fare si che NESSUNA modifica \ndella due milioni che stavamo facendo compaia, il che e&#8217; incredibilmente \npreferibile al non sapere su quali record la modifica e&#8217; gi\u00e0 stata apportata e \nsu quali no<\/P>\n<P><B><FONT size=+2><A \nname=\"I Semafori , ovvero la gestione della multiutenza\">I Semafori , ovvero la \ngestione della multiutenza<\/A><\/FONT><\/B><\/P>\n<P>Chiariamo subito una cosa: gi\u00e0 linguaggi come Clipper avevano strumenti per \ngestire la multiutenza sui database, ma in quel caso ancora era&nbsp; \ncompletamente demandato al programmatore il fatto di inserire apposite \nistruzioni per gestire tale eventualit\u00e0, mentre nei moderni motori database chi \ngestisce la multiutenza e&#8217; il motore stesso (a meno che il programmatore o il \nDataBase Administrator non vogliano fare giochini strani ed in quel caso se ne \nprendono la responsabilit\u00e0). ma come viene gestita questa multiutenza? nella \nmaniera pi\u00f9 semplice del mondo: chi primo arriva meglio alloggia. per spiegarsi \nun po&#8217; meglio la cosa funziona in questo modo:<\/P>\n<P>Tutte le volte che noi accediamo ad un determinato record possiamo accedervi \nin tre diverse modalit\u00e0: in lettura, in scrittura o in lettura E scrittura. la \nprocedura di accesso ai record SA in che modo noi vogliamo accedere (o perch\u00e9 ha \nuna impostazione di default o perch\u00e9 noi stessi glielo abbiamo detto) e provvede \nquindi ad imporre un &#8220;limite&#8221; sul set di record su cui stiamo lavorando che po&#8217; \nessere normalmente uno dei seguenti:<\/P>\n<UL>\n  <LI>record libero in lettura e scrittura \n  <LI>record in sola lettura (divieto di modifica) \n  <LI>record bloccato sia in lettura che in scrittura <\/LI><\/UL>\n<P>questo tipo di gestione (normalmente definito &#8220;a semafori&#8221; ) permette di \nevitare che due persone tentino contemporaneamente di modificare lo stesso \nrecord, permettendo cos\u00ec di evitare i problemi che nascono con la \nmultiutenza<\/P>\n<HR>\n\n<P><B><FONT size=+2><A name=\"Il Linguaggio SQL\">Il Linguaggio \nSQL<\/A><\/FONT><\/B><\/P>\n<P>Ora che abbiamo visto rapidamente cosa sta alla base di un database \nrelazionale entriamo nel dettaglio del linguaggio SQL, analizzandone i \ncomandi<\/P>\n<P><B><FONT size=+2><A name=\"Basi del comando SELECT\">Basi del comando \nSELECT<\/A><\/FONT><\/B> <\/P>\n<P>Come abbiamo detto prima nell&#8217; introduzione, nei database relazionali le \ninformazioni sono contenute in tabelle. Un esempio di tabella puo&#8217; essere \nrappresentato dalla tabella dei dati degli impiegati riportata qui sotto \n<TABLE border=1>\n  <TBODY>\n  <TR>\n    <TD vAlign=center colSpan=6>\n      <P align=center><B>TabellaImpiegati<\/B><\/P><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center><B>CFisc<\/B><\/TD>\n    <TD vAlign=center><B>Nome<\/B><\/TD>\n    <TD vAlign=center><B>Cognome<\/B><\/TD>\n    <TD vAlign=center><B>Indirizzo<\/B><\/TD>\n    <TD vAlign=center><B>Citta<\/B><\/TD>\n    <TD vAlign=center><B>Provincia<\/B><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>ALSNTN60R18F115Z<\/TD>\n    <TD vAlign=center>Alessandro<\/TD>\n    <TD vAlign=center>Antoni<\/TD>\n    <TD vAlign=center>Vicolo Fastidio 23<\/TD>\n    <TD vAlign=center>Sesso<\/TD>\n    <TD vAlign=center>Bologna<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>FRCBNC58A55F254W<\/TD>\n    <TD vAlign=center>Franca<\/TD>\n    <TD vAlign=center>Bianchi<\/TD>\n    <TD vAlign=center>Via Rua Pioppa 15<\/TD>\n    <TD vAlign=center>Modena<\/TD>\n    <TD vAlign=center>Modena<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>OSCGRG75F23K242Z<\/TD>\n    <TD vAlign=center>Oscar<\/TD>\n    <TD vAlign=center>Gorgo<\/TD>\n    <TD vAlign=center>Piazza Ugo Bassi 23<\/TD>\n    <TD vAlign=center>Forl\u00ec<\/TD>\n    <TD vAlign=center>Forl\u00ec Cesena<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>SMNZNT71D12F251K<\/TD>\n    <TD vAlign=center>Simone<\/TD>\n    <TD vAlign=center>Zanti&nbsp;<\/TD>\n    <TD vAlign=center>Via Radici in piano 115<\/TD>\n    <TD vAlign=center>Sassuolo<\/TD>\n    <TD vAlign=center>Modena<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>adesso tentiamo di leggere gli indirizzi dei nostri impiegati.Utilizziamo l&#8217; \nistruzione SELECT cos\u00ec: \n<P><TT>SELECT Nome, Cognome, Indirizzo, Citta, Provincia<\/TT> <BR><TT>FROM \nTabellaImpiegati;<\/TT> \n<P>Il risultato della vostra prima QUERY (interrogazione) del database sar\u00e0 \nquesto: \n<TABLE border=1>\n  <TBODY>\n  <TR>\n    <TD vAlign=center><B>Nome<\/B><\/TD>\n    <TD vAlign=center><B>Cognome<\/B><\/TD>\n    <TD vAlign=center><B>Indirizzo<\/B><\/TD>\n    <TD vAlign=center><B>Citta<\/B><\/TD>\n    <TD vAlign=center><B>Provincia<\/B><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>Alessandro<\/TD>\n    <TD vAlign=center>Antoni<\/TD>\n    <TD vAlign=center>Vicolo Fastidio 23<\/TD>\n    <TD vAlign=center>Sesso<\/TD>\n    <TD vAlign=center>Bologna<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>Franca<\/TD>\n    <TD vAlign=center>Bianchi<\/TD>\n    <TD vAlign=center>Via Rua Pioppa 15<\/TD>\n    <TD vAlign=center>Modena<\/TD>\n    <TD vAlign=center>Modena<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>Oscar<\/TD>\n    <TD vAlign=center>Gorgo<\/TD>\n    <TD vAlign=center>Piazza Ugo Bassi 23<\/TD>\n    <TD vAlign=center>Forl\u00ec<\/TD>\n    <TD vAlign=center>Forl\u00ec Cesena<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>Simone<\/TD>\n    <TD vAlign=center>Zanti&nbsp;<\/TD>\n    <TD vAlign=center>Via Radici in piano 115<\/TD>\n    <TD vAlign=center>Sassuolo<\/TD>\n    <TD vAlign=center>Modena<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>Spieghiamo cosa avete appena fatto. Avete appena chiesto al vostro database \ndi farvi vedere tutti i dati contenuti nella tabella TabellaImpiegati, ed in \nparticolare di mostrarvi solo il contenuto delle colonne Nome, Cognome, \nindirizzo, citt\u00e0 e provincia. E&#8217; il caso di notare che nei nomi delle colonne e \nnel nome della tabella non sono presenti spazi, che sono un tipo di carattere \nnon ammesso per specificare i nomi di tali elementi. La sintassi generalizzata \ndi questo comando, per ricevere sulle colonne specificate tutte le righe di una \ntabella,&nbsp; e&#8217; la seguente:\n<P><TT>SELECT NomeColonna, NomeColonna, &#8230;<\/TT> <BR><TT>FROM \n<\/TT><TT>NomeTabella<\/TT><TT>;<\/TT> \n<P>Per ricevere invece tutte le colonne, senza specificarle una ad una, potete \nusare: \n<P><TT>SELECT * FROM NomeTabella;<\/TT>\n<P>Notiamo due cose in particolare da questa prima istruzione:\n<P>Ogni comando SQL viene concluso (terminato) da un carattere particolare che \ne&#8217; normalmente il carattere &#8220;;&#8221;. finch\u00e9 SQL non incontra tale carattere continua \nad interpretare i caratteri che legge come facenti parti della stesa istruzione. \ncorollario fondamentale di questo fatto e&#8217; che possiamo spezzare il comando \nstesso su pi\u00f9 righe allo scopo di ottenere una migliore leggibilit\u00e0 senza \nparticolari problemi (ATTENZIONE: questo carattere VARIA da DBMS a DBMS, \nCONTROLLATE QUAL&#8217;E&#8217; il carattere di separazione nel particolare DBMS che state \nusando).&nbsp;&nbsp; \n<HR>\n<B><FONT size=+2><A name=\"Selezione Condizionata\">Selezione \nCondizionata<\/A><\/FONT><\/B> \n<P>Per continuare la discussione sulla selezione, facciamo riferimento a questa \nnuova tabella di esempio<\/P>\n<TABLE width=544 border=1>\n  <TBODY>\n  <TR>\n    <TD vAlign=center colSpan=4>\n      <P align=center><B>TabellaStatisticheImpiegati<\/B><\/P><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\"><B>CodiceImpiegato<\/B><\/TD>\n    <TD vAlign=center width=\"25%\"><B>StipendioAnnuo<\/B><\/TD>\n    <TD vAlign=center width=\"25%\"><B>Benefici<\/B><\/TD>\n    <TD vAlign=center width=\"25%\"><B>Posizione<\/B><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">010<\/TD>\n    <TD vAlign=center width=\"25%\">75000000<\/TD>\n    <TD vAlign=center width=\"25%\">15000000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Dirigente<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">105<\/TD>\n    <TD vAlign=center width=\"25%\">65000000<\/TD>\n    <TD vAlign=center width=\"25%\">15000000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Dirigente<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">152<\/TD>\n    <TD vAlign=center width=\"25%\">60000000<\/TD>\n    <TD vAlign=center width=\"25%\">15000000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Dirigente<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">215<\/TD>\n    <TD vAlign=center width=\"25%\">60000000<\/TD>\n    <TD vAlign=center width=\"25%\">12500000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Dirigente<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">244<\/TD>\n    <TD vAlign=center width=\"25%\">50000000<\/TD>\n    <TD vAlign=center width=\"25%\">12000000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Impiegato<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">300<\/TD>\n    <TD vAlign=center width=\"25%\">45000000<\/TD>\n    <TD vAlign=center width=\"25%\">10000000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Impiegato<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">335<\/TD>\n    <TD vAlign=center width=\"25%\">40000000<\/TD>\n    <TD vAlign=center width=\"25%\">10000000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Impiegato<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">400<\/TD>\n    <TD vAlign=center width=\"25%\">32000000<\/TD>\n    <TD vAlign=center width=\"25%\">7500000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Apprendista<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"26%\">441<\/TD>\n    <TD vAlign=center width=\"25%\">28000000<\/TD>\n    <TD vAlign=center width=\"25%\">7500000&nbsp;<\/TD>\n    <TD vAlign=center width=\"25%\">Apprendista<\/TD><\/TR><\/TBODY><\/TABLE>\n<H4><A name=\"Operatori Relazionali\">Operatori Relazionali<\/A><\/H4>Ci sono sei \noperatori relazionali in SQL, e dopo averli specificati vedremo come si usano. \ngli operatori sono: \n<TABLE width=283 border=1>\n  <TBODY>\n  <TR>\n    <TD vAlign=center width=\"36%\">=<\/TD>\n    <TD vAlign=center width=\"64%\">Uguale<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"36%\">&lt;&gt; oppure != (vedere manuali)<\/TD>\n    <TD vAlign=center width=\"64%\">Non Uguale&nbsp;<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"36%\">&lt;<\/TD>\n    <TD vAlign=center width=\"64%\">Minore di<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"36%\">&gt;<\/TD>\n    <TD vAlign=center width=\"64%\">Maggiore di<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"36%\">&lt;=<\/TD>\n    <TD vAlign=center width=\"64%\">Minore o uguale di<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center width=\"36%\">&gt;=<\/TD>\n    <TD vAlign=center width=\"64%\">Maggiore o uguale di<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>La clausola <I>WHERE <\/I>viene utilizzata per specificare che si desidera \nvedere solo certe righe della tabella, basandosi per la scelta sul criterio \nstabilito nella clausola stessa. Penso che un paio di esempi possano rendere pi\u00f9 \nchiaro il funzionamento della stessa.\n<P>Se si vuole vedere il Codice Impiegato di quegli impiegati che hanno uno \nstipendio annuo maggiore di 50 milioni possiamo farlo cos\u00ec: \n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticeImpiegati<\/TT> \n<BR><TT>WHERE StipendioAnnuo &gt;= 50000000;<\/TT> \n<P>Notate che abbiamo utilizzato il simbolo &gt;= (Maggiore o uguale di), in \nquanto vogliamo vedere sia coloro che hanno uno stipendio di 50 milioni che \nquelli che hanno uno stipendio maggiore di 50 milioni. il risultato sar\u00e0 il \nseguente: \n<P><TT>CodiceImpiegato<\/TT> <BR><TT>&#8212;&#8212;&#8212;&#8212;<\/TT> <BR><TT>010<\/TT> \n<BR><TT>105<\/TT> <BR><TT>152<\/TT> <BR><TT>215<\/TT> <BR><TT>244<\/TT> \n<P>la parte del comando&nbsp; <I>WHERE<\/I> che contiene la regola discriminante, \nin questo caso StipendioAnnuo &gt;= 50000000, e&#8217; conosciuta come una&nbsp; \n<I>condizione<\/I> (un&#8217; operazione il cui risultato pu\u00f2 essere Vero o \nFalso)<I>.<\/I> La stessa cosa pu\u00f2 essere fatta anche con colonne che contengono \ntesto invece che numeri: \n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE POSIZIONE = &#8216;Dirigente&#8217;;<\/TT> \n<P>Questo comando mostrer\u00e0 come risultato il codice impiegato di tutti i \ndirigenti. Generalmente quando si utilizzano colonne di testo ci si limita agli \noperatori = e != , e bisogna assicurarsi che tutti i testi utilizzati compaiano \nnel comando racchiusi tra singoli apici (&#8216;). N.B. il singolo apice e&#8217; l&#8217; \nidentificatore di testo nell&#8217; SQL ANSI, ma alcuni DBMS usano altri qualificatori \ncome i doppi apici.&nbsp; \n<P><A \nname=\"Condizioni piu' complesse: Condizioni multiple e Operatori Logici\"><FONT \nsize=+1>Condizioni pi\u00f9 complesse: Condizioni multiple e Operatori \nLogici&nbsp;<\/FONT><\/A>\n<P>L&#8217; operatore <I>AND<\/I> congiunge due o pi\u00f9 condizioni, e ritorna tutte e \nsolo le righe che soddisfano TUTTE le condizioni. Per esempio, per mostrare i \ncodici di tutti gli impiegati con uno stipendio superiore ai 40 milioni si \nutilizza il comando seguente: \n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE StipendioAnnuo&nbsp; &gt; 40000000 AND Posizione = \n&#8216;Impiegato&#8217;;<\/TT> \n<P>L&#8217; operatore <I>OR<\/I> collega anch&#8217;esso due o pi\u00f9 condizioni, ma ritorna una \nriga se UNA QUALSIASI delle condizioni inserite risulta vera. ad esempio per \nvedere tutti coloro che&nbsp; hanno uno stipendio annuo inferiore a 40 milioni o \nricevono meno di 10 milioni in benefici accessori si utilizza la seguente query: \n\n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE StipendioAnnuo&nbsp; &lt; 40000000 OR Benefici &lt; 10000000;<\/TT> \n\n<P>AND ed OR possono venire combinati, come nell&#8217; esempio seguente: \n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE Posizione = &#8216;Dirigente&#8217; AND StipendioAnnuo &gt; 60000000 OR \nBenefici &gt; 12000000;<\/TT> \n<P>Per prima cosa, SQL trova le righe in cui lo stipendio annuo e&#8217; maggiore di \n60 milioni e che contengono nella colonna Posizione la parola &#8216;Dirigente&#8217;, \nquindi si tiene in memoria questa lista e controlla che soddisfino la condizione \nOR relativa ad avere benefici per pi\u00f9 di 12 milioni. Notate che la condizione \nAND viene risolta per prima, cosa che modifica nettamente i risultati. spendiamo \nun paio di parole in pi\u00f9 su questo fatto, in quanto se non ben compreso pu\u00f2 \nportare a differenze sostanziali nei risultati delle query ed alla difficile \ncomprensione del perch\u00e9 ci\u00f2 \u00e8 avvenuto.\n<P>Per generalizzare quello che avviene, SQL calcola i risultati delle \noperazioni AND per determinare quali sono le righe che soddisfano la condizione \n(ricordate: TUTTE le condizioni devono essere vere), quindi questi risultati \nvengono utilizzati per essere confrontati con la condizione OR, e vengono \nmostrate solo le righe rimanenti dove una qualsiasi delle operazioni collegate \ndall&#8217; operatore OR risulta vera (True). Matematicamente , SQL valuta tutte le \ncondizioni realizzate tramite operatori relazionali, quindi valuta le &#8220;coppie&#8221; \ndi AND e quindi gli OR (dove entrambi gli operatori sono valutati da sinistra a \ndestra).\n<P>Per fare un esempio, guardiamo cosa succede quando il nostro DBMS valuta una \ndeterminata condizione, ricordando che i valori booleani &#8220;vero&#8221; e &#8220;falso&#8221; in SQL \nvengono espressi come True e False . il primo passo che il DBMS fa e&#8217; di \nvalutare i risultati delle operazioni svolte tramite gli operatori relazionali, \nquindi si prepara a valutare gli operatori logici sui risultati. mettiamo che \ndalla valutazione di una condizione complessa al nostro DBMS sia risultato \nquanto segue: \n<P><TT>True AND False OR True AND True OR False AND False<\/TT> \n<P>La prima cosa che fa sar\u00e0 valutare le coppie di AND, ottenendo quanto segue: \n<P><TT><U>True AND False<\/U> OR <U>True AND True<\/U> OR <U>False AND False<\/U> = \nFalse OR True OR False<BR>1\u00b0 \ncoppia&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2\u00b0 \nCoppia&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3\u00b0Coppia<\/TT> \n<P>Quindi parte a valutare gli OR, da sinistra a destra, ottenendo al primo \npassaggio quanto segue: \n<P><TT><U>False OR True<\/U> OR False = True OR False<BR>1\u00b0 coppia<\/TT> \n<P>ed alla fine, valutando l&#8217; ultima espressione , arriva al risultato \ndefinitivo \n<P><TT><U>True OR False<\/U> = True<\/TT>\n<P>Il risultato finale e&#8217; True (vero) e quindi la riga che ha generato questa \nsequenza di valori verr\u00e0 inserita all&#8217; interno di quelle passate dalla query. \nAssicuratevi di leggere attentamente anche la prossima sezione sull&#8217; operatore \nNOT e di avere ben compreso l&#8217; ordine di valutazione degli operatori, in quanto \ne&#8217; un argomento difficile da spiegare in poche righe, pertanto posso solo \nsperare di essere stato sufficientemente chiaro.\n<P>Per variare l&#8217; ordine di esecuzione , ad esempio se volete una lista di \ndipendenti che percepiscono uno stipendio maggiore di 50 milioni o con benefici \nmaggiori di 10 milioni e che siano dei dirigenti, si usano le parentesi, come in \nquesto esempio: \n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE Posizione = &#8216;Dirigente&#8217; AND (StipendioAnnuo &gt; 50000000 OR \nBenefici &gt; 10000000); \n<HR>\n<\/TT><B><I><A name=\"IN , BETWEEN e NOT\">IN , BETWEEN e NOT<\/A><\/I><\/B> \n<P>Un metodo semplice per usare delle condizioni multiple e&#8217; quello di impiegare \nle due clausole&nbsp; <I>IN<\/I> e <I>BETWEEN.<\/I> Per esempio, se volete vedere \ntutti i dipendenti che siano dirigenti o impiegati potete fare cos\u00ec:\n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE Posizione IN (&#8216;Dirigente&#8217;, &#8216;Impiegato&#8217;);<\/TT> \n<P>Oppure per avere la lista di coloro che hanno uno stipendio maggiore o uguale \ndi&nbsp; 30 milioni e minore o uguale a 50 milioni potete impiegare il seguente \ncomando\n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE StipendioAnnuo BETWEEN 30000000 AND 50000000;<\/TT> \n<P>Invece, per mostrare tutti quelli che non sono compresi nell&#8217; intervallo, \npotete usare:\n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE StipendioAnnuo NOT BETWEEN 30000000 AND 50000000;<\/TT> \n<P>Similarmente, la clausola&nbsp; NOT IN restituisce tutte le righe escluse \ndalla lista generata dalla relativa <I>IN<\/I>, quindi se voleste vedere tutti \ncoloro che non sono ne&#8217; dirigenti ne&#8217; impiegati potete farlo con il comando\n<P><TT>SELECT CodiceImpiegato<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE Posizione NOT IN (&#8216;Dirigente&#8217;, &#8216;Impiegato&#8217;);<\/TT> \n<P>Inoltre, l&#8217; operatore NOT&nbsp; pu\u00f2 venire utilizzato in congiunzione con AND \ned OR per invertirne il risultato, ma va tenuto conto che mentre i due operatori \nAND ed OR sono binari (usano 2 condizioni) il NOT e&#8217; unario, cio\u00e8 si riferisce \nad una sola condizione; inoltre il NOT viene calcolato PRIMA dell&#8217; AND e dell&#8217; \nOR . \n<P><B><I>Ordine in SQL degli operatori logici&nbsp; (tutti funzionano da \nsinistra a destra)<\/I><\/B> \n<OL>\n  <LI><TT><FONT size=+1>NOT<\/FONT><\/TT> \n  <LI><TT><FONT size=+1>AND<\/FONT><\/TT> \n  <LI><TT><FONT size=+1>OR<\/FONT><\/TT> <\/LI><\/OL><B><A \nname=\"Utilizzare la clausola LIKE ed il carattere jolly\">Utilizzare la clausola \n<I>LIKE ed il carattere jolly %<\/I><\/A><\/B> \n<P>Mettiamo di voler estrarre dalla nostra tabella TabellaImpiegati i codici \nfiscali di tutti gli impiegati il cui nome inizia per&nbsp; &#8220;S&#8221;; possiamo \nprocedere cos\u00ec:\n<P><TT>SELECT CFisc<\/TT> <BR><TT>FROM TabellaImpiegati<\/TT> <BR><TT>WHERE NOME \nLIKE &#8216;A%&#8217;;<\/TT> \n<P>Il carattere percento (%) viene utilizzato pre rappresentare ogni possibile \ncarattere (numeri, lettere o segni di interpunzione) o blocchi di caratteri che \npossono venire trovati dopo il carattere &#8220;A&#8221;. similmente, se volessimo trovare \ncoloro il cui nome termina in &#8220;A&#8221; potremmo farlo con &#8220;%A&#8221;, o se volessimo \ntrovare quelli il cui nome contiene una A potremmo farlo con &#8220;%A%&#8221;. Visto che il \nfunzionamento dell&#8217; operatore Like varia tantissimo da DBMS a DBMS consiglio di \nverificare la sintassi esatta nel vostro sistema prima di impiegarlo e per \nvedere quali altre possibilit\u00e0 vi pu\u00f2&nbsp; offrire \n<HR>\n<B><FONT size=+2>I <A name=Joins>Join<\/A><\/FONT><\/B> \n<P>In questa sezione discuteremo solo degli <I>inner<\/I> <I>joins<\/I>, e \ndegli&nbsp; <I>equijoin<\/I><I>s<\/I>, che , in genere, sono estremamente utili. \nPer informazioni pi\u00f9 dettagliate in merito vi rimando ai link che ho inserito in \nfondo a questa pagina e che credo possano esservi di un qualche aiuto\n<P>Le norme generali sulla buona progettazione dei database suggeriscono che \nogni tabella contenga dati relativi solo ad una singola &#8220;entit\u00e0&#8221; e che i dati \naggiuntivi rispetto ad essa possano venire recuperati tramite relazioni con \naltre tabelle create tramite i Join. per prima cosa partiamo da un esempio, \nrappresentato dalle tabelle seguenti: \n<P>&nbsp; \n<TABLE border=1>\n  <TBODY>\n  <TR>\n    <TD vAlign=center colSpan=3>\n      <P align=center>Antiquari<\/P><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center><B>IDAntiquario<\/B><\/TD>\n    <TD vAlign=center><B>CognomeAntiquario<\/B><\/TD>\n    <TD vAlign=center><B>NomeAntiquario<\/B><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>01<\/TD>\n    <TD vAlign=center>Jones<\/TD>\n    <TD vAlign=center>Bill<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>Smith<\/TD>\n    <TD vAlign=center>Bob<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>15<\/TD>\n    <TD vAlign=center>Lawson<\/TD>\n    <TD vAlign=center>Patricia<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>21<\/TD>\n    <TD vAlign=center>Akins<\/TD>\n    <TD vAlign=center>Jane<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>50<\/TD>\n    <TD vAlign=center>Fowler<\/TD>\n    <TD vAlign=center>Sam<\/TD><\/TR><\/TBODY><\/TABLE>&nbsp; \n<TABLE border=1>\n  <TBODY>\n  <TR>\n    <TD vAlign=center colSpan=2>\n      <P align=center><B>Ordini<\/B> <\/P><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center><B>IDAntiquario<\/B><\/TD>\n    <TD vAlign=center><B>OggettoRicercato<\/B><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>Tavolo<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>Scrivania<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>21<\/TD>\n    <TD vAlign=center>Sedia<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>15<\/TD>\n    <TD vAlign=center>Specchio<\/TD><\/TR><\/TBODY><\/TABLE>&nbsp; \n<TABLE border=1>\n  <TBODY>\n  <TR>\n    <TD vAlign=center colSpan=3>\n      <P align=center><B>Antichita<\/B><\/P><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center><B>IDVenditore<\/B><\/TD>\n    <TD vAlign=center><B>IDAcquirente<\/B><\/TD>\n    <TD vAlign=center><B>Oggetto<\/B><\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>01<\/TD>\n    <TD vAlign=center>50<\/TD>\n    <TD vAlign=center>Letto<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>15<\/TD>\n    <TD vAlign=center>Tavolo<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>15<\/TD>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>Sedia<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>21<\/TD>\n    <TD vAlign=center>50<\/TD>\n    <TD vAlign=center>Specchio<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>50<\/TD>\n    <TD vAlign=center>01<\/TD>\n    <TD vAlign=center>Scrivania<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>01<\/TD>\n    <TD vAlign=center>21<\/TD>\n    <TD vAlign=center>Cassettiera<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>21<\/TD>\n    <TD vAlign=center>Tavolinetto da Caff\u00e8<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>15<\/TD>\n    <TD vAlign=center>50<\/TD>\n    <TD vAlign=center>Sedia<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>01<\/TD>\n    <TD vAlign=center>15<\/TD>\n    <TD vAlign=center>Portagioielli<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>21<\/TD>\n    <TD vAlign=center>Terracotta<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>21<\/TD>\n    <TD vAlign=center>02<\/TD>\n    <TD vAlign=center>Libreria<\/TD><\/TR>\n  <TR>\n    <TD vAlign=center>50<\/TD>\n    <TD vAlign=center>01<\/TD>\n    <TD vAlign=center>Piantana<\/TD><\/TR><\/TBODY><\/TABLE>\n<P>\n<P><B><A name=\"Le Chiavi\">Le Chiavi<\/A><\/B>\n<P>Per prima cosa vediamo il concetto di <I>Chiave<\/I>. Una <I>Chiave \nPrimaria<\/I> ( o <I>primary key) <\/I>e&#8217; una colonna o un gruppo di colonne che \nidentificano in maniera univoca (singola) ogni data riga rispetto alle altre. \nTradotto in un linguaggio un po&#8217; pi\u00f9 semplice, e&#8217; quell&#8217; insieme di informazioni \nche mi permettere di distinguere ogni singolo record da ogni altro record. Per \nesempio, nella tabella Antiquari il campo IDAntiquario distingue in maniera \nprecisa ogni singolo record (non ci sono due record con lo stesso numero nel \ncampo IDAntiquario ne&#8217; ci possono logicamente essere). questo significa che non \npossono esistere due righe della tabella con lo stesso codice in IDAntiquario e \nche se anche due antiquari avessero lo stesso nome e lo stesso cognome sarebbero \ncomunque differenziato da un codice diverso, permettendoci cos\u00ec di non \nconfonderli tra di loro, e che quindi ci verr\u00e0 molto pi\u00f9 comodo usare il codice \nrispetto al nome + cognome per&nbsp; collegarci alle altre tabelle del database.\n<P>Una <I>Chiave Esterna<\/I> (o<I> foreign key<\/I> ) e&#8217; invece una colonna \npresente in una tabella nella quale si registrano dati che sono la chiave \nprimaria di un&#8217; altra tabella. per fare un&#8217; esempio con il nostro database le \ncolonne IDVenditore e IDAcquirente della tabella antichit\u00e0 sono chiavi esterne \nin quanto fanno riferimento ai valori contenuti nella chiave primaria della \ntabella Antiquari, cio\u00e8 IDAntiquario. In &#8220;Informatichese&#8221; questa corrispondenza \nviene chiamata <I>Integrit\u00e0 Referenziale<\/I> (o <I>referential integrity <\/I>per \ngli inglesofoni), ed impongono il limite che all&#8217; interno dei campi della \ncolonna della chiave esterna non possono comparire valori che non siano stati \nprecedentemente inseriti nella colonna della chiave primaria relativa, \naltrimenti ci si troverebbe di fronte ad un errore chiamato &#8220;<I>Violazione dell&#8217; \nintegrit\u00e0 referenziale<\/I>&#8221; che renderebbe il database <I>inconsistente<\/I>, \ncio\u00e8 in pratica inutilizzabile. In pratica, come risulta chiaro dall&#8217; esempio, \nviene utilizzata la chiave primaria di una certa tabella per fare riferimento ai \ndati contenuti nel record relativo senza dovere riportarli nella seconda \ntabella. nel nostro esempio infatti viene utilizzato il campo &#8220;IDAntiquario&#8221; per \nsapere chi ha comprato e chi ha venduto un determinato oggetto nella tabella \nAntichita, senza dovere riportare il nome ed il cognome sia dell&#8217; acquirente che \ndel venditore. \n<P><B><A name=\"Creare un Join\">Creare un Join<\/A><\/B> \n<P>Lo scopo delle Chiavi appena discusse e&#8217; quella di correlare i dati \nattraverso le tabelle, senza dover in questo modo ripetere su tutte le tabelle i \ndati pi\u00f9 frequenti, il che e&#8217; il vero scopo e la sostanziale differenza tra i \ndatabase relazionali ed altri tipi di database. per esempio possiamo trovare i \nnomi di coloro che hanno comprato una sedia senza dover mettere il nome ed il \ncognome dell&#8217; acquirente nella tabella antichit\u00e0. possiamo infatti ottenerne il \nnome mettendo in relazione coloro che hanno comprato una sedia con la lista di \ntutti i nomi degli antiquari della tabella Antiquari attraverso l&#8217; utilizzo \ndell&#8217; IDAcquirente, che mette in relazione i dati nelle due tabelle. per trovare \ni nomi di chi ha comprato una sedia possiamo , in pratica, utilizzare la \nseguente query: \n<P><TT>SELECT CognomeAntiquario, NomeAntiquario<\/TT> <BR><TT>FROM Antiquari, \nAntichita<\/TT> <BR><TT>WHERE IdAcquirente = IDAntiquario AND Oggetto = \n&#8216;Sedia&#8217;;<\/TT> \n<P>Iniziamo ad analizzare le particolarit\u00e0 di questa query. la prima che balza \nall&#8217; occhio subito e&#8217; che ENTRAMBE le tabelle sono coinvolte nella query e \ncitate di fianco alla clausola FROM. la seconda cosa e&#8217; che nella clausola WHERE \nle due chiavi delle due tabelle sono messe in relazione tramite l&#8217; uso della \ncondizione <TT>IdAcquirente = IDAntiquario <\/TT>e quindi ristretto tramite la \ncondizione <TT>Oggetto = &#8216;Sedia&#8217; <\/TT>a coloro che hanno acquistato una sedia. \nLa condizione che mette in collegamento le due tabelle \n(IDAcquirente=IDAntiquario) e&#8217; il nostro <I>Join<\/I> (in italiano connessione). \nVisto che la condizione che crea il join e&#8217; un uguale, questo tipo di join e&#8217; \nchiamato un&nbsp; <I>equijoin<\/I>. Il risultato di questa query saranno due \nnomi: Smith, Bob e Fowler, Sam.\n<P>La<I> notazione a punti <\/I>(<I>Dot notation<\/I>) permette di specificare il \nnome della tabella a cui si riferisce il campo , evitando cos\u00ec possibili \nambiguit\u00e0. pur essendo pi\u00f9 &#8220;faticosa&#8221; e&#8217; nettamente preferibile visto che \nmigliora notevolmente la leggibilit\u00e0 della query e riduce la possibilit\u00e0 di \nerrori. la nostra query precedente in dot notation sarebbe cos\u00ec: \n<P><TT>SELECT Antiquari.CognomeAntiquario, Antiquari.NomeAntiquario<\/TT> \n<BR><TT>FROM Antiquari, Antichita<\/TT> <BR><TT>WHERE Antichita.IdAcquirente = \nAntiquari.IDAntiquario AND Antichita.Oggetto = &#8216;Sedia&#8217;;<\/TT> \n<P>Questa notazione non sarebbe (e non e&#8217;) necessaria se i nomi di tutti i campi \ndi ogni tabella differissero l&#8217; uno dall&#8217; altro, ma e&#8217; comunque un&#8217; ottima \nabitudine da prendere e diventa fondamentale appena la struttura del database \ncresce a sufficienza da non essere pi\u00f9 verificabile a colpo d&#8217;occhio<\/P><B><I><A \nname=\"Clausola DISTINCT e l'Eliminazione dei Duplicati\">Clausola \nDISTINCT<\/A><\/I> <A name=\"Clausola DISTINCT e l'Eliminazione dei Duplicati\">e \nl&#8217;Eliminazione dei Duplicati<\/A><\/B> \n<P>Prendiamo in esame la necessit\u00e0, nel nostro database di esempio, di avere una \nlista dei codici e dei nomi esclusivamente degli antiquari che hanno venduto un \noggetto. Ovviamente si vorr\u00e0 che nella lista risultante ogni venditore sia \nelencato una sola volta, indipendentemente dal numero di oggetti che ha venduto \n&#8211; non vogliamo sapere quanti oggetti ha venduto un antiquario, ma solo che abbia \nvenduto qualcosa (per poterli conteggiare invece fare riferimento alla \nsuccessiva sezione sulle funzioni di aggregazione). Questo significa che \ndobbiamo dire ad SQL di eliminare le righe duplicate delle vendite dello stesso \nantiquario, e quindi elencare ognuno di questi una volta sola. Per ottenere \nquesto scopo utilizzeremo la clausola <I>DISTINCT<\/I>.\n<P>Per prima cosa ci serve un equijoin (come e&#8217; stato spiegato subito sopra) \nalla tabella degli Antiquari per potere ottenere i dati particolareggiati di \nogni antiquario, cio\u00e8 cognome e nome. Ovviamente in merito va mantenuta ben in \nmente quella che prima e&#8217; stata definita l&#8217; Integrit\u00e0 referenziale, cio\u00e8 nel \ncaso in cui non esistesse un record relativo al codice presente nel campo \nIDVenditore all&#8217; interno del campo IDAntiquario nella tabella Antiquari il \nminimo che pu\u00f2 accadere \u00e8 che il record non venga mostrato, mentre addirittura \nsu alcuni DBMS si verificherebbe un errore di integrit\u00e0 referenziale violata \nbloccando l&#8217; esecuzione della query. come abbiamo detto inoltre vogliamo \neliminare le occorrenze multiple dei record nella nostra lista, quindi \nimpieghiamo la clausola Distinct sulle colonne in cui potrebbe verificarsi l&#8217; \noccorrenza multipla stessa\n<P>Per aggiungere un&#8217; ulteriore livello di complessit\u00e0 della query , vogliamo i \nrisultati in ordine alfabetico prima per cognome e poi per nome. per fare questo \npossiamo utilizzare la clausola <I>ORDER BY<\/I> . La nostra query finale sar\u00e0 la \nseguente: \n<P><TT>SELECT DISTINCT IDVenditore, CognomeAntiquario, NomeAntiquario<\/TT> \n<BR><TT>FROM Antichita, Antiquari<\/TT> <BR><TT>WHERE IDVenditore = \nIDAntiquario<\/TT> <BR><TT>ORDER BY CognomeAntiquario, NomeAntiquario;<\/TT> \n<P>In questo esempio particolare, visto che tutti hanno venduto almeno un \noggetto, avremo una lista completa di tutti gli antiquari, in ordine alfabetico \nper cognome e nome. Per uso futuro (cio\u00e8 se un qualche sadico ve lo viene a \nchiedere) tenete presente che questo tipo di Join \u00e8 da considerarsi nella \ncategoria degli <I>inner joins. \n<HR>\n<\/I><B><FONT size=+2><A name=\"Alias, In e l' utilizzo delle Subquery\">Alias, In \ne l&#8217; utilizzo delle Subquery<\/A><\/FONT><\/B> \n<P>In questa sezione parleremo dell&#8217; utilizzo degli&nbsp; <I>Alias<\/I>, dell&#8217; \n<I>In<\/I> , dell&#8217; utilizzo delle&nbsp; subquery, e come queste possono venire \nutilizzate nel nostro esempio di 3 tabelle. Per prima cosa diamo un&#8217; occhiata \nalla query riportata qui sotto, che ritorna i cognomi di quegli antiquari che \nhanno fatto un&#8217; ordine e che tipo di oggetto hanno ordinato, mostrando solo gli \nordini in essere (se notate infatti esiste un&#8217; antiquario che ha ordinato un&#8217; \noggetto di cui e&#8217; gi\u00e0 in possesso):\n<P><TT>SELECT PERS.CognomeAntiquario Cognome, ORD.OggettoRicercato Oggetto \nOrdinato<BR>FROM Ordini ORD, Antiquari PERS<\/TT> <BR><TT>WHERE ORD.IDAntiquario \n= PERS.IDAntiquario<\/TT> <BR><TT>AND ORD.OggettoRicercato IN<\/TT> \n<DIR><TT>(SELECT Oggetto<\/TT> <BR><TT>FROM Antichita);<\/TT><\/DIR>Questa query \nritorna questo risultato:\n<P><TT>Cognome Oggetto Ordinato<\/TT> <BR><TT>&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;-<\/TT> \n<BR><TT>Smith&nbsp;&nbsp; Tavolo<\/TT> <BR><TT>Smith&nbsp;&nbsp; Scrivania<\/TT> \n<BR><TT>Akins&nbsp;&nbsp; Sedia<\/TT> <BR><TT>Lawson&nbsp; Specchio<\/TT> \n<P>C&#8217;e&#8217; veramente un mucchio di cose da vedere in questa query. analizziamola \nnello specifico : \n<OL>\n  <LI>Per prima cosa, nella linea della clausola SELECT compaiono le parole \n  &#8220;Cognome&#8221; e &#8220;Oggetto Ordinato&#8221; che forniscono l&#8217; intestazione delle colonne \n  del report ritornato dalla query \n  <LI>Le parole PERS ed ORD sono <I>alias<\/I>; gli alias sono dei nomi \n  alternativi per le due tabelle che compaiono nella clausola FROM e che vengono \n  utilizzati come prefissi in tutta la dot notation delle colonne utilizzate \n  nella query, in modo da eliminare le ambiguit\u00e0 , in particolar modo nella \n  clausola WHERE dell&#8217; equijoin , dove entrambi le colonne si chiamano \n  IDAntiquario e quindi la dot notation si renda indispensabile per evitare \n  confusione tra i due&nbsp; \n  <LI>Notate che la tabella Ordini e&#8217; quella che compare per prima nella \n  clausola FROM; questo ci permette di essere sicuri che il report verr\u00e0 tratto \n  dai dati presenti in questa tabella e che la tabella Antiquari viene \n  utilizzata solo per recuperare le informazioni dettagliate (i cognomi) \n  <LI>La cosa pi\u00f9 importante; l&#8217; AND nella clausola WHERE forza a richiamare la \n  subquery contenuta nella clausola IN (&#8220;= ANY&#8221; o &#8220;= SOME&#8221; sono due utilizzi \n  equivalenti ad IN). Questo e&#8217; quello che fa: la subquery contenuta tra le \n  parentesi viene eseguita, ritornando l&#8217; elenco di tutti gli oggetti contenuti \n  nella tabella Antichita non essendoci nessuna clausola WHERE nella subquery; \n  dopodich\u00e9, perch\u00e9 una riga nella&nbsp;&nbsp; tabella degli ordini possa venire \n  inserita nel report finale, il valore del campo OggettoRicercato deve essere \n  all&#8217; interno della lista&nbsp; degli oggetti restituita dalla subquery. Per \n  chiarire meglio la cosa si pu\u00f2 vederla in questo modo: la subquery ritorna un \n  set di oggetti con i quali vengono confrontati gli oggetti presenti nella \n  colonna OggettoRicercato e la condizione di inclusione diventa vera solo se il \n  valore del campo OggettoRicercato \u00e8 presente nella lista ritornata dalla \n  subquery \n  <LI>Inoltre tenete ben presente che quando usate le clausole IN, &#8220;= ANY&#8221;, o &#8220;= \n  SOME&#8221; NON potete fare riferimento a pi\u00f9 colonne diverse. sono i valori che \n  vengono restituiti a potere essere differenti , e il confronto pu\u00f2 venire \n  fatto tra valori differenti contenuti in ogni RIGA ma NON in colonne \n  differenti. il viceversa non e&#8217; possibile. <\/LI><\/OL>Ok, penso che abbiamo \ndiscusso in maniera ampia e dettagliata del comando SELECT e penso che dovreste \nessere a questo punto in grado di arrivare a fare query di selezione decisamente \ncomplesse, per cui passiamo agli altri comandi di SQL \n<HR>\n<B><FONT size=+2>Comandi SQL Vari<\/FONT><\/B>\n<P><B><A name=\"Funzioni di Aggregazione\">Funzioni di Aggregazione<\/A><\/B>\n<P>In questa sezione introdurr\u00f2 le cinque pi\u00f9 importanti&nbsp; <I>Funzioni di \nAggregazione<\/I>: SUM, AVG, MAX, MIN, e COUNT. Queste funzioni vengono chiamate \nDi Aggregazione perch\u00e9 servono a calcolare valori dai risultati delle query \ninvece che a ottenerne un listato di tutte le righe. Vediamo il significato di \nogni funzione: \n<UL>\n  <LI>SUM () restituisce il totale di tutte le righe, che soddisfano ogni \n  condizione, della colonna data, quando tale colonna contiene valori numerici \n  <LI>AVG () restituisce la media della colonna data \n  <LI>MAX () restituisce il valore pi\u00f9 elevato della colonna data \n  <LI>MIN () restituisce il valore pi\u00f9 piccolo della colonna data \n  <LI>COUNT(*) restituisce il numero di righe che soddisfano le condizioni \n<\/LI><\/UL>proviamo a fare un po&#8217; di esempi con le tabelle degli impiegati \nutilizzate all&#8217; inizio di questo documento. guardiamo questi tre esempi: \n<P><TT>SELECT SUM(StipendioAnnuo), AVG(StipendioAnnuo)<\/TT> <BR><TT>FROM \nTabellaStatisticheImpiegati;<\/TT> \n<P>Questa query ritorna la somma totale di tutti gli stipendi annui presenti \nnella tabella e la media degli stessi \n<P><TT>SELECT MIN(Benefici)<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE Posizione = &#8216;Dirigente&#8217;;<\/TT> \n<P>Questa query ritorna il valore del piu&#8217; basso importo annuo preso da un \ndirigente come beneficio accessorio (12 milioni). \n<P><TT>SELECT COUNT(*)<\/TT> <BR><TT>FROM TabellaStatisticheImpiegati<\/TT> \n<BR><TT>WHERE POSITION = &#8216;Impiegato&#8217;;<\/TT> \n<P>Questa query risponde dandoci il numero di persone con la qualifica di \nimpiegato (3). \n<HR>\n<B><A name=Viste>Viste<\/A><\/B> \n<P>In SQL si pu\u00f2 normalmente avere la possibilit\u00e0 di crearsi delle proprie \nviste, cio\u00e8 creare delle query &#8220;perenni&#8221; che possono venire utilizzate come \ndelle vere e proprie tabelle. normalmente questa funzione pu\u00f2 venire usata da \nogni singolo utente, che sar\u00e0 colui che vedr\u00e0 la vista se non specificato \ndiversamente dal DBA (controllate il vostro DBMS e sentite dal vostro DB \nAdministrator se gli utenti hanno questo diritto). per essere pi\u00f9 precisi quello \nche fa una vista e&#8217; permettervi di assegnare i risultati di una query ad una \nnuova tabella &#8220;personale&#8221; (cio\u00e8 legata al vostro utente), che potete usare all&#8217; \ninterno di altre query , ed il cui nome potete tranquillamente specificare nella \nclausola FROM come se fosse una qualunque tabella. Generalmente le viste sono \ndinamiche, cio\u00e8 i valori nella tabella vengono rigenerati tutte le volte che \naccedete alla vista stessa. un esempio di creazione di una vista pu\u00f2 essere il \nseguente: \n<P><TT>CREATE VIEW VistaAnt AS SELECT OggettoRichiesto FROM Ordini;<\/TT> \n<P>A questo punto possiamo scrivere una query che usa questa vista come una \ntabella; tabella che in realt\u00e0 sar\u00e0 solo un&#8217; elenco di tutti gli oggetti \nrichiesti proveniente dalla tabella Ordini: \n<P><TT>SELECT IDVenditore<\/TT> <BR><TT>FROM Antichita, VistaAnt<\/TT> \n<BR><TT>WHERE OggettoRichiesto = Oggetto;<\/TT> \n<P>Questa query mostra il codice del venditore estratto dalla tabella antichit\u00e0 \nquando il campo OggettoRichiesto in quella tabella compare nella vista VistaAnt, \nche e&#8217; semplicemente la lista di tutti gli oggetti richiesti nella tabella degli \nordini, eseguita al momento del lancio della query.Le viste possono essere \nutilizzate sia allo scopo di restringere la visibilit\u00e0 dei dati a determinati \nutenti che per semplificare delle query complesse. \n<HR>\n<B><A name=\"Creare Nuove Tabelle\">Creare Nuove Tabelle<\/A><\/B>\n<P>Tutte le tabelle all&#8217; interno di un database devono venire create prima o \npoi. vediamo come possiamo fare. a titolo di esempio prendiamo in esame la \ncreazione della tabella Ordini: \n<P><TT>CREATE TABLE Ordini<\/TT> <BR><TT>(IDAntiquario&nbsp;&nbsp;&nbsp; \nINTEGER&nbsp; NOT NULL,<\/TT> <BR><TT>OggettoRicercato CHAR(40) NOT NULL);<\/TT>\n<P>Questo comando dice al DBMS di creare una tabella, gli assegna un nome e \ndefinisce ogni colonna nella stessa. ATTENZIONE: notate che questo comando \nutilizza dei tipi di dato generici, e che i tipi di dato possono variare da DBMS \na DBMS, quindi verificate i tipi di dato disponibili sul vostro. Alcuni tipi di \ndato generalmente disponibili su quasi tutti i DBMS sono: \n<UL>\n  <LI>Char(x) &#8211; una serie di caratteri alfanumerici (generalmente la tabella \n  ASCII o EBCDIC) , in cui x specifica il numero massimo di caratteri permessi \n  nella colonna (spesso conosciuta anche come stringa di caratteri di lunghezza \n  x). \n  <LI>Integer &#8211; una colonna di numeri interi, positivi o negativi, i cui massimi \n  dipendono da DBMS a DBMS. \n  <LI>Decimal(x, y) &#8211; Una colonna di numeri decimali, in cui x esprime il numero \n  massimo di cifre permesso e y il numero di cifre dopo la virgola. per esempio \n  il numero pi\u00f9 alto esprimibile in un campo definito Decimal(4,2) e&#8217; 99,99. \n  <LI>Date &#8211; Una colonna contenente delle date nel formato tipico specifico del \n  proprio DBMS. \n  <LI>Logical &#8211; Una colonna che pu\u00f2 contenere solo uno dei due seguenti valori: \n  TRUE (vero) o FALSE (falso). <\/LI><\/UL>Altra cosa da notare e&#8217; l&#8217; impiego della \nclausola NOT NULL. Questa clausola impone che il relativo campo non possa mai \nvenire lasciato vuoto (deve sempre essere presente un valore per questo campo). \nNel caso si voglia invece permettere l&#8217; inserimento di record con quel \ndeterminato campo vuoto si usa la clausola NULL o, in molti DBMS, se non viene \nspecificato nulla viene associata per default la clausola NULL. \n<HR>\n<B><A name=\"Modificare la struttura delle tabelle\">Modificare la struttura delle \ntabelle<\/A><\/B>\n<P>Sempre con la logica di vedere i comandi all&#8217; interno di esempi pratici, \nvediamo come si puo&#8217; aggiungere una nuova colonna &#8220;Prezzo&#8221; alla tabella \nantichita per permettere l&#8217; inserimento del prezzo di ogni articolo. vista la \nprossima introduzione dell&#8217; euro inseriamo invece che un valore Integer un \nvalore Decimal di dimensioni tali da poterci permettere di esprimere il prezzo \nsia in lire che in euro: \n<P><TT>ALTER TABLE Antichita ADD (Prezzo DECIMAL(12,2) NULL);<\/TT> \n<P>l&#8217; ovvio complemento della clausola ADD qui utilizzata per aggiungere una \ncolonna e&#8217; la clausola REMOVE che permette di eliminare una colonna specificata. \ni dati in questa nuova colonna possono essere modificati o inseriti come \nspecificato poco oltre. \n<HR>\n\n<P><B><A name=\"Inserire dati in una tabella\">Inserire dati in una \ntabella<\/A><\/B><\/P>\n<P>Per inserire record (righe) in una tabella si usa il seguente comando \n(esempio riferito alla tabella Antichita a cui e&#8217; appena stato aggiunto il \nprezzo) : \n<P><TT>INSERT INTO Antichita VALUES (21, 01, &#8216;Ottomana&#8217;, 2000000.00);<\/TT> \n<P>Questo comando inserisce una nuova riga nella tabella, nell&#8217; ordine dei campi \npredefinito e riempiendo tutti i campi. per poter variare l&#8217; ordine di \ninserimento dei campi e lasciare in bianco il campo Prezzo (che abbiamo \nprecedentemente definito NULL e che quindi accetta valori nulli) si pu\u00f2 fare \ncos\u00ec: \n<P><TT>INSERT INTO Antichita (IDAcquirente, IDVenditore, Oggetto)<\/TT> \n<BR><TT>VALUES (01, 21, &#8216;Ottomana&#8217;); \n<HR>\n<\/TT><B><A name=\"Cancellare dati da una tabella\">Cancellare dati da una \ntabella<\/A><\/B>\n<P>Adesso proviamo a cancellare la riga di dati che abbiamo appena inserito \ndalla tabella: \n<P><TT>DELETE FROM Antichita<\/TT> <BR><TT>WHERE Oggetto = &#8216;Ottomana&#8217;;<\/TT> \n<P>Ma, in questo caso, se c&#8217;e&#8217; un&#8217; altra riga che contiene nel campo Oggetto la \nparla &#8220;Ottomana&#8221; verr\u00e0 cancellata anch&#8217;essa. per cui siamo un po&#8217; pi\u00f9 specifici \ne cancelliamo la riga specificando tutti i dati che abbiamo appena inserito: \n<P><TT>DELETE FROM Antichita<\/TT> <BR><TT>WHERE Oggetto = &#8216;Ottomana&#8217; AND \nIDAcquirente = 01 AND IDVenditore = 21;<\/TT><TT> \n<HR>\n<\/TT><B><A name=\"Modifica dei dati\">Modifica dei dati<\/A>&nbsp;<\/B>\n<P>Proviamo ad aggiornare il valore di un prezzo in un record dove questo non e&#8217; \nstato inserito. ricordiamoci che in questo caso non si tratta di un inserimento \nma di una modifica del valore NULL precedentemente impostato in quel campo, in \nquanto il record e&#8217; gi\u00e0 presente nella tabella: \n<P><TT>UPDATE Antichita SET Prezzo = 500000.00 WHERE Oggetto = &#8216;Sedia&#8217;;<\/TT> \n<P>Questo comando imposta il prezzo di tutte le sedie a 500.000\u00a3 . anche in \nquesto caso possiamo fare riferimento alla sintassi della clausola WHERE del \ncomando SELECT per essere pi\u00f9 o meno specifici nella scelta dei record da \nmodificare. inoltre, esattamente come nel comando SELECT, si possono modificare \npi\u00f9 colonne con la stessa sintassi usata in questo comando per indicare pi\u00f9 \ncolonne (elenco diviso da virgole dopo la clausola SET) . \n<HR>\n\n<P><B><I><FONT size=+1><A name=\"Gli Indici\">Gli Indici<\/A><\/FONT><\/I><\/B> \n<P class=MsoNormal>Gli indici permettono ad un DBMS di accedere ai dati pi\u00f9 \nrapidamente (nota bene: questa funzionalit\u00e0 \u00e8 non-standard\/non disponibile su \ntutti i sistemi).Il sistema crea della strutture dati interne (gli indici) per \nla selezione pi\u00f9 veloce di determinate righe quando la selezione \u00e8 basata su \ncolonne indicizzate. La struttura indica al DBMS dove si trova una certa riga su \nuna tabella con colonne indicizzate, pi\u00f9 o meno come il glossario di un libro \nindica la pagina in cui appare una determinata parola. Creiamo un indice per \nIDAntiquario nella tabella ANTIQUARI<\/P>\n<P><TT>CREATE INDEX OID_IDX ON ANTIQUARI (IDAntiquari);<\/TT> \n<P>Ora un indice sui nomi:<\/P>\n<P><TT>CREATE INDEX NAME_IDX ON ANTIQUARI (CognomeAntiquario, \nNomeAntiquario);<\/TT> \n<P>Per eliminare un indice si usa l\u2019istruzione DROP:<\/P>\n<P><TT>DROP INDEX OID_IDX;<\/TT> \n<P class=MsoNormal>In pi\u00f9, si pu\u00f2 usare l\u2019istruzione DROP TABLE per eliminare \nuna tabella (attenzione! Questo significa che la tua tabella viene cancellata). \nNel secondo esempio, l\u2019indice \u00e8 relativo a due colonne, aggregate insieme; in \nquesto caso, possono accadere strani comportamenti\u2026 consultare il manuale prima \ndi eseguire questa operazione.<\/P>Alcuni DBMS non richiedono l\u2019unicit\u00e0 della \nchiave primaria. In altre parole, se cercassi di inserire un\u2019altra riga nella \ntabella ANTIQUARI con un IDAntiquario = 2, alcuni sistemi mi lascerebbero fare \nquest\u2019operazione, anche se non \u00e8 consigliabile, in quanto si suppone che il \nvalore di questa colonna sia unico per ciascuna riga. Un modo per ovviare a \npossibili inconvenienti di questo genere \u00e8 di creare un indice unico sulla \ncolonna che noi vogliamo sia una chiave primaria, per forzare il sistema ad \nimpedire la duplicazione di valori in quella colonna: \n<P><TT>CREATE UNIQUE INDEX OID_IDX ON ANTIQUARI (IDAntiquario); \n<HR>\n<\/TT><B><I><FONT size=+1><A name=\"GROUP BY &amp; HAVING\">GROUP BY ed \nHAVING<\/A><\/FONT><\/I><\/B> \n<P>Un uso speciale dell\u2019istruzione GROUP BY \u00e8 di associare una funzione di \naggregazione (nella fattispecie COUNT; conta il numero di righe in ciascun \ngruppo) con dei gruppi di righe. Si assuma che la tabella ANTICHITA abbia la \ncolonna PREZZO e che ciascuna riga abbia un valore inserito in questa colonna. \nQuello che ci interessa \u00e8 di vedere il prezzo dell\u2019oggetto pi\u00f9 costoso comprato \nda ciascun acquirente. Si deve impartire via SQL l\u2019ordine di <I \nstyle=\"mso-bidi-font-style: normal\">raggruppare<\/I> gli acquisti di ciascun \nacquirente, e di stampare il prezzo dell\u2019acquisto pi\u00f9 costoso:\n<P><TT>SELECT IDAcquirente, MAX(Prezzo)<\/TT> <BR><TT>FROM ANTICHITA<\/TT> \n<BR><TT>GROUP BY IDAcquirente;<\/TT> \n<P>Ora, aggiungiamo l\u2019istruzione di stampare il prezzo massimo di acquisto se \nsupera i 100 dollari; in questo caso si usa l\u2019istruzione HAVING:<\/P>\n<P><TT>SELECT IDAcquirente, MAX(Prezzo)<\/TT> <BR><TT>FROM ANTICHITA<\/TT> \n<BR><TT>GROUP BY IDAcquirente<\/TT> <BR><TT>HAVING Prezzo &gt; 100; \n<HR>\n<\/TT><B><I><FONT size=+1><A name=\"Altre Subquery\">Altre \nSubquery<\/A><\/FONT><\/I><\/B> \n<P>Un altro uso comune delle Queries coinvolge l\u2019uso di operatori per permettere \nad una condizione di WHERE di includere l\u2019output di una SELECT di una Query \nannidata. Dapprima, si mostri la lista degli acquirenti che hanno comprato un \noggetto dispendioso (ovvero con il prezzo dell\u2019articolo che superi di 100 \ndollari il prezzo medio di tutti gli oggetti comprati): \n<P class=MsoNormal><TT>SELECT IDAcquirente<BR>FROM ANTICHITA<BR>WHERE Prezzo \n&gt;<\/TT><\/P>\n<P class=MsoNormal><TT>&nbsp;&nbsp;&nbsp; (SELECT AVG(Prezzo) + \n100<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM ANTICHITA);<\/TT><\/P>\n<P class=MsoNormal>La query annidata fra parentesi calcola il prezzo medio, \nsomma 100, ed usando il risultato, si stampa un IDAcquirente per ciascun oggetto \nvenduto di prezzo superiore. Si pu\u00f2 usare DISTINCT IDAcquirente per visualizzare \nuna sola riga per ciascun IDAcquirente selezionato.<O:P> <\/O:P><\/P>\n<P class=MsoNormal>Stampa i Cognomi della tabella ANTIQUARI, solo se hanno \ncomprato un oggetto:<\/P>\n<P class=MsoNormal><TT>SELECT COGNOMEANTIQUARIO<BR>FROM ANTIQUARI<BR>WHERE \nIDAntiquario IN<\/TT><\/P>\n<P class=MsoNormal style=\"MARGIN-LEFT: 0.25in\"><TT>&nbsp;&nbsp;&nbsp; (SELECT \nDISTINCT IDAcquirente<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM \nANTICHITA);<\/TT><\/P>\n<P class=MsoNormal>La query annidata (o sottoquery) seleziona una lista di \nacquirenti, e stampa il cognome di un Antiquario se e solo se il suo \nIDAntiquario appare nella lista selezionata dalla sottoquery (talvolta chiamata \n<I style=\"mso-bidi-font-style: normal\">lista dei candidati<\/I>). <I \nstyle=\"mso-bidi-font-style: normal\">Nota:<\/I> alcuni DBMS permettono di usare il \nsegno uguale (\u2018=\u2019) al posto di IN; per chiarezza, per\u00f2, si preferisce l\u2019uso di \nIN, in quanto la sottoquery non ritorna un valore singolo, bens\u00ec una lista.<\/P>\n<P class=MsoNormal>Per un esempio relativo all&#8217; UPDATE, sappiamo che il \ngentiluomo che ha acquistato la libreria ha il Nome sbagliato nel database, e \nche il nome corretto \u00e8 Giovanni:<\/P>\n<P class=MsoNormal><TT>UPDATE ANTIQUARI<BR>SET NOMEANTIQUARIO = \n&#8216;Giovanni&#8217;<BR>WHERE IDAntiquario =<\/TT><\/P>\n<P class=MsoNormal><TT>&nbsp;&nbsp;&nbsp; (SELECT \nIDAcquirente<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM \nANTICHITA<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE OGGETTO = \n&#8216;Libreria&#8217;);<\/TT><\/P>\n<P class=MsoNormal>&nbsp;<I style=\"mso-bidi-font-style: normal\">In primis<\/I>, \nla sottoquery cerca l\u2019IDAcquirente per la persona o le persone che hanno \nacquistato la libreria, <I style=\"mso-bidi-font-style: normal\">in secundis<\/I> \nla query esterna aggiorna il Nome.<\/P>\n<P class=MsoNormal><B style=\"mso-bidi-font-weight: normal\">Regola delle \nsottoquery: <\/B>quando si ha una sottoquery come parte di una condizione di \nWHERE, l\u2019istruzione di SELECT deve avere un numero di colonne pari in numero e \ntipo a quelle contenute nella condizione di WHERE della query esterna. In altre \nparole, se si ha <SPAN style=\"FONT-FAMILY: 'Courier New'\">\u201cWHERE NomeColonna = \n(SELECT\u2026.);\u201d <\/SPAN>l\u2019istruzione di Select deve avere solo una colonna, per \ntrovare una corrispondenza con il NomeColonna della condizione di Where esterna; \nin pi\u00f9, il <I style=\"mso-bidi-font-style: normal\">tipo<\/I> deve essere il \nmedesimo (due interi, due stringhe di caratteri, etc..).<\/P>\n<HR>\n<B><I><FONT size=+1><A name=\"EXISTS ed ALL\">EXISTS ed ALL<\/A><\/FONT><\/I><\/B> \n<P class=MsoNormal>EXISTS usa una sottoquery come condizione: la condizione \u00e8 \nVera se la sottoquery ritorna almeno una riga, ed \u00e8 Falsa se la sottoquery non \nritorna nessuna riga. Questa \u00e8 una funzionalit\u00e0 non intuitiva con quest\u2019uso \nspecifico. Comunque, se si vuole stampare un riassuntivo clienti solo se il \nnegozio ha venduto Sedie, si pu\u00f2 scrivere:<SPAN class=Macchinadascrivere \nstyle=\"FONT-FAMILY: 'Courier New'\">&nbsp;<O:P> <\/O:P><\/SPAN><\/P>\n<P><TT>SELECT NomeAcquirente, CognomeAcquirente<BR>FROM ANTIQUARI<BR>WHERE \nEXISTS<\/TT><\/P>\n<P><TT>&nbsp;&nbsp;&nbsp; (SELECT \n*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM \nANTICHITA<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE Oggetto = \n&#8216;Sedia&#8217;);<\/TT><\/P>\n<P class=MsoNormal>Se nella colonna della tabella ANTICHITA c\u2019\u00e8 almeno una riga \ncontenente l\u2019articolo sedia, la sottoquery ritorna una o pi\u00f9 righe, rendendo \nVera la condizione EXISTS; di conseguenza la query stampa gli Antiquari. Se non \nci sono righe con l\u2019oggetto Sedia, la query esterna non<SPAN \nstyle=\"mso-spacerun: yes\">&nbsp; <\/SPAN>stamper\u00e0 alcuna riga.<\/P>\n<P class=MsoNormal>&nbsp;ALL \u00e8 un\u2019altra funzionalit\u00e0 inusuale, in quanto la \nquery che contengono l\u2019istruzione ALL possono essere eseguite in altri modi, a \nvolte anche pi\u00f9 semplici; diamo un\u2019occhiata alla query di esempio:<\/P>\n<P><TT>SELECT IDAcquirente, Oggetto<BR>FROM ANTICHITA<BR>WHERE Prezzo &gt;= \nALL<\/TT><\/P>\n<P><TT>&nbsp;&nbsp;&nbsp; (SELECT \nPrezzo<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM ANTICHITA);<\/TT><\/P>\n<P><TT>&nbsp;<\/TT>Questa query ritorna l\u2019oggetto con il prezzo pi\u00f9 alto (o pi\u00f9 \ndi un oggetto se hanno un prezzo uguale e massimo), e l\u2019Acquirente. La \nsottoquery ritorna una lista di tutti i prezzi nella tabella ANTICHITA, mentre \nla query esterna passa tutte le righe della tabella ANTICHITA, e se il prezzo \u00e8 \nmaggiore o uguale di qualunque altro oggetto (ALL = tutti), viene stampato, \nrisultando cos\u00ec l\u2019oggetto con il prezzo pi\u00f9 alto. La ragione per cui viene usato \nil segno di \u201cmaggiore o uguale\u201d \u00e8 che il prezzo dell\u2019oggetto pi\u00f9 costoso sar\u00e0 \nuguale al prezzo pi\u00f9 alto della tabella.<\/P>\n<HR>\n<B><I><FONT size=+1><A name=\"UNION ed Outer Joins\">UNION ed Outer Joins<\/A> \n(rapida spiegazione non esaustiva)<\/FONT><\/I><\/B> \n<P class=MsoNormal>Si possono presentare casi in cui si voglia vedere il \nrisultato di diverse query insieme, combinando il loro output; in questi casi si \nusa l\u2019espressione UNION. Per unire l\u2019output delle due query seguenti, stampando \ntutti gli IDAcquirente, insieme con tutti quelli che hanno mandato un ordine, si \nesegua:<\/P>\n<P class=MsoNormal><TT>SELECT IDAcquirente<BR>FROM ANTICHITA<BR>UNION<BR>SELECT \nIDAntiquario<BR>FROM ORDINI; <\/TT><SPAN lang=EN-US \nstyle=\"mso-ansi-language: EN-US\"><O:P><\/O:P><\/SPAN><\/P>\n<P class=MsoNormal><SPAN lang=EN-US \nstyle=\"mso-ansi-language: EN-US\">&nbsp;<\/SPAN>Si noti che SQL richiede che la \nlista di colonne di entrambe le Select siano uguali per tipo, colonna per \ncolonna. In questo caso IDAcquirente ed IDAntiquario sono dello stesso tipo \n(Interi [integer]). Si noti inoltre che SQL elimina automaticamente le righe \nduplicate usando UNION (come fossero due set di dati); per le query singole si \ndeve usare DISTINCT.<\/P>\n<P class=MsoNormal>L\u2019<I style=\"mso-bidi-font-style: normal\">outer join<\/I>, \n(join esterno) si usa quando una join fra tabelle viene \u201cunita\u201d con le righe non \nincluse nella condizione di join; questo risulta particolarmente utile se nella \nquery sono contenute delle costanti di tipo testo. Per esempio:<\/P>\n<P class=MsoNormal><TT>SELECT IDAntiquario, &#8216;presente in Ordini ed \nAntichita&#8217;<BR>FROM ORDINI, ANTICHITA<BR>WHERE IDAntiquario = \nIDAcquirente<BR>UNION<BR>SELECT IDAcquirente, &#8216;presente solo in \nAntichita&#8217;<BR>FROM ANTICHITA<BR>WHERE IDAcquirente NOT \nIN<BR>&nbsp;&nbsp;&nbsp;<\/TT> <TT>(SELECT \nIDAntiquario<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM ORDINI); \n<\/TT><SPAN lang=EN-US style=\"mso-ansi-language: EN-US\"><O:P><\/O:P><\/SPAN><\/P>\n<P class=MsoNormal style=\"MARGIN-LEFT: 0.25in\"><SPAN lang=EN-US \nstyle=\"mso-ansi-language: EN-US\">&nbsp;<\/SPAN>La prima query fa una join per \nstampare tutti gli Antiquari in entrambe le tabelle, e per aggiungere un breve \ncommento dopo ciascun ID. La UNION combina questa lista con la successiva, che \nviene generata anzi tutto richiamando gli ID non presenti nella tabella ORDINI, \ninfine stampando gli ID esclusi dalla condizione di join. Quindi, ciascuna riga \nnella tabella ANTICHITA viene esaminata, e se l\u2019IDAcquirente non \u00e8 nella lista \ndi esclusione, viene stampato con il commento fra apici. Ci possono essere modi \npi\u00f9 semplici per generare la stessa lista di ID, ma attaccare a ciascuna riga un \ncommento fisso appropriato \u00e8 ben pi\u00f9 complesso se fatto in altri modi.<\/P>\n<P class=MsoNormal>Questo concetto \u00e8 utile in situazioni in cui una chiave \nprimaria viene messa in condizione di join con una chiave secondaria, ma la \nchiave secondaria pu\u00f2 essere NULL per alcune chiavi primarie. Ad esempio, in una \ntabella la chiave primaria \u00e8 il venditore e in un\u2019altra \u00e8 il cliente, con il \nvenditore riportato nella stessa riga. Se un venditore non ha clienti, il suo \nnome non appare nella tabella dei clienti. L\u2019<B \nstyle=\"mso-bidi-font-weight: normal\">outer join<\/B> si usa allora per ottenere \nla lista di <B style=\"mso-bidi-font-weight: normal\">tutti<\/B> i venditori, \ninsieme con i loro clienti, sia nel caso in cui il venditore abbia clienti sia \nnel caso in cui non ne abbia, cio\u00e8 non venga stampato il nome del cliente (un \nvalore di NULL logico) se il venditore non ha clienti, ma \u00e8 nella tabella dei \nvenditori. In caso contrario, il venditore sar\u00e0 stampato insieme con ognuno dei \nsuoi clienti.<\/P>\n<P class=MsoNormal>Un altro punto importante riguardo ai NULL nelle condizioni \ndi join: l\u2019ordine delle tabelle nella lista successiva all\u2019istruzione FROM \u00e8 \nmolto importante. La regola \u00e8 che SQL aggiunge la seconda tabella alla prima; se \nla prima tabella presenta solo righe contenenti NULL nella colonna di join, e la \nseconda tabella ha una riga con NULL nella colonna di join, tale riga non \nrisulta nella condizione di join, e pertanto deve venire inclusa con i dati di \nriga della prima tabella. Questa \u00e8 un altro esempio in cui comunemente viene \nimpiegato un outer join. Il concetto di NULL \u00e8 importante, e pu\u00f2 essere proficuo \ninvestigarlo in maniera pi\u00f9 approfondita.<\/P>BASTA QUERY!!! O non ne avete \nancora avuto abbastanza? \u2026 adesso si passa a qualcosa del tutto differente\u2026 \n<HR>\n<B><FONT size=+2><A \nname=\"Sommario della Sintassi - Solo per veri masochisti\">Sommario della \nSintassi &#8211; Solo per veri masochisti<\/A><\/FONT><\/B>\n<P>Qui potete trovare le forme generalizzate dei comandi discussi in questi \nappunti, pi\u00f9 alcuni aggiuntivi che possono risultare comodi e la cui spiegazione \ne&#8217; data a latere. <B><U>ATTENZIONE!!!<\/U><\/B> non e&#8217; detto che tutti questi \ncomandi siano esattamente in questa forma, controllate sul vostro sistema per \navere la certezza del loro funzionamento e della loro disponibilit\u00e0:\n<P><TT><B>ALTER TABLE<\/B> &lt;Nome Tabella&gt; ADD|DROP|MODIFY (Specifiche \nColonna[e]&#8230;vedere Create Table);<\/TT><B> <\/B>&#8211;vi permette di aggiungere o \ncancellare una o pi\u00f9 colonne da una tabella, o di cambiare i parametri di una \ncolonna esistente (tipi di dato ecc..); questo comando e&#8217; utilizzato spesso \nanche per cambiare le specifiche fisiche di una tabella (dove e come viene \nsalvata ecc.), ma in questo caso dipende direttamente dal DBMS che state usando, \nquindi vi rimando ai manuali del vostro database. Oltre che con questo comando \nle specifiche fisiche della tabella possono venire generalmente date all&#8217; \ninterno del comando Create Table quando una tabella viene creata per la prima \nvolta.\n<P><B><TT>Begin Transaction; <\/TT><\/B>inizia a considerare i comandi seguenti \ncome facenti parte di un&#8217; unico blocco (transazione) che vanno eseguiti in un \nblocco unico al raggiungimento di una istruzione di commit o scartati tutti \ninsieme al raggiungimento di una istruzione rollback\n<P><B><TT>COMMIT<\/TT>;<\/B> effettua i cambiamenti fatti sul database dall&#8217; \nultima istruzione Begin Transaction (in alcuni DBMS dall&#8217; ultima commit) e li \nrende permanenti &#8212; questo blocco di istruzioni viene definito una Transazione \n<P><B><TT>CREATE [UNIQUE] INDEX<\/TT> <\/B><TT>&lt;Nome Indice&gt;<\/TT><BR><TT>ON \n&lt;Nome Tabella&gt; (&lt;Lista Colonne&gt;); <\/TT>&#8212; UNIQUE e&#8217; opzionale e va \nusato senza parentesi quadre.\n<P><B><TT>CREATE TABLE<\/TT> <\/B><TT>&lt;Nome Tabella&gt;<\/TT><BR><TT>(&lt;Nome \nColonna&gt; &lt;Tipo di Dato&gt; [(&lt;Dimensione&gt;)] &lt;Limitazioni sulle \ncolonne&gt;,<\/TT><BR><TT>&#8230;altre colonne[PRIMARY KEY (colonna, colonna,&#8230;)]); \n(<\/TT>sintassi valida anche per ALTER TABLE)<BR>&#8211;dove Dimensione viene usato \nsolo su alcuni tipi di dato, e le limitazioni includono quelle qui sotto \nriportate (controllate automaticamente dal dbms. una tentata violazione causa la \ngenerazione di un errore): \n<OL>\n  <LI>NULL o NOT NULL (vedi sotto) \n  <LI>UNIQUE obbliga a non avere due valori uguali all&#8217; interno della colonna \n  <LI>PRIMARY KEY dice al database che questa colonna e&#8217; la chiave primaria \n  della tabella (utilizzato solo se la chiave primaria e&#8217; composta da una sola \n  colonna, altrimenti una clausola&nbsp; PRIMARY KEY (colonna, colonna, &#8230;) \n  comparir\u00e0 dopo l&#8217;ultima definizione di colonna. \n  <LI>CHECK permette ad una condizione di essere testata quando i dati vengono \n  inseriti o aggiornati in una determinata colonna; per esempio, CHECK (Prezzo \n  &gt;= 0) impone al sistema di controllare che il prezzo sia maggiore o uguale \n  a zero prima di accettare il valore; a volte viene implementato con \n  l\u2019istruzione CONSTRAINT. \n  <LI>DEFAULT inserisce il valore nel database per una determinata colonna se \n  una riga viene inserita senza un valore per la colonna stessa; per \n  esempio,<SPAN \n  style=\"FONT-SIZE: 10pt; FONT-FAMILY: 'Times New Roman'; mso-ansi-language: IT; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: IT; mso-bidi-language: AR-SA\"> \n  <\/SPAN><SPAN class=Macchinadascrivere \n  style=\"FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: IT; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: IT; mso-bidi-language: AR-SA\">BENEFITS \n  INTEGER DEFAULT = 10000<\/SPAN> \n  <LI>FOREIGN KEY funziona esattamente come l\u2019istruzione Primary Key, ma \u00e8 \n  seguita da: <TT>REFERENCES &lt;Nome Tabella&gt; (&lt;Nome Colonna&gt;)<\/TT>, \n  che riferisce la chiave riferita ad una chiave primaria. <\/LI><\/OL><B><TT>CREATE \nVIEW<\/TT> <\/B><TT>&lt;Nome Tabella&gt; AS &lt;Query&gt;;<\/TT> \n<P><B><TT>DELETE<\/TT> <\/B><TT>FROM &lt;Nome Tabella&gt; WHERE \n&lt;Condizione&gt;;<\/TT> \n<P><B><TT>INSERT<\/TT> <\/B><TT>INTO &lt;Nome Tabella&gt; [(&lt;Lista \nColonne&gt;)]<\/TT><BR><TT>VALUES (&lt;Lista Valori&gt;);<\/TT> \n<P><B><TT>ROLLBACK<\/TT>; <\/B>&#8212; Annulla le modifiche effettuare al database che \nsono state effettuate dopo l&#8217; ultimo comando COMMIT. ATTENZIONE! vedere il \nfunzionamento delle istruzioni COMMIT, ROLLBACK e BEGIN TRANSACTION sui propri \nRDBMS particolari in quanto il funzionamento di tali comandi varia moltissimo da \nun sistema all&#8217; altro\n<P><TT><B>SELECT<\/B> [DISTINCT|ALL] &lt;Lista Colonne, Funzioni, Costanti, \necc.&gt;<\/TT><BR><TT>FROM &lt;Lista di tabelle o di viste&gt;<\/TT><BR><TT>[WHERE \n&lt;Condizione\/i&gt;]<\/TT><BR><TT>[GROUP BY &lt;raggruppamento \ncolonna\/e&gt;]<\/TT><BR><TT>[HAVING &lt;condizione&gt;]<\/TT><BR><TT>[ORDER BY \n&lt;colonna\/e di ordinamento&gt; [ASC|DESC]]; <\/TT>&#8211;dove ASC|DESC permettono di \nfare in modo che l&#8217; ordinamento venga effettuato in ordine ascendente (ASC) o \ndiscendente (DESC)\n<P><B><TT>UPDATE<\/TT> <\/B><TT>&lt;Nome Tabella&gt;<\/TT><BR><TT>SET &lt;Nome \nColonna&gt; = &lt;Valore&gt;<\/TT><BR><TT>[WHERE &lt;Condizione&gt;]; <\/TT>&#8212; se \nla clausola Where non e&#8217; specificata vengono aggiornate tutte le righe come \nspecificate nella clausola SET \n<HR>\n\n<H1><B><FONT size=+2><A name=\"Sommario dei Link relativi all' SQL\">Sommario dei \nLink relativi all&#8217; SQL&nbsp;<\/A><\/FONT><\/B><\/H1>\n<P><A href=\"http:\/\/www.contrib.andrew.cmu.edu\/~shadow\/sql.html\">SQL Reference \nPage<\/A><BR><A href=\"http:\/\/www.progsource.com\/index.html\">Programmer&#8217;s \nSource<\/A><BR><A href=\"http:\/\/www.devx.com\/\">DevX<\/A><BR><A \nhref=\"http:\/\/www.compapp.dcu.ie\/databases\/f017.html\">DB Ingredients<\/A><BR><A \nhref=\"http:\/\/www.lizardfoot.com\/SQLTrainer\">SQL Trainer S\/W<\/A><BR><A \nhref=\"http:\/\/www.stars.com\/Tutorial\/CGI\/\">Web Authoring<\/A><BR><A \nhref=\"http:\/\/www-ccs.cs.umass.edu\/db.html\">DBMS Lab\/Links<\/A><BR><A \nhref=\"http:\/\/epoch.cs.berkeley.edu:8000\/sequoia\/dba\/montage\/FAQ\/SQL_TOC.html\">SQL \nFAQ<\/A><BR><A href=\"http:\/\/ashok.pair.com\/sql.htm\">Query List<\/A><BR><A \nhref=\"http:\/\/sqlcourse.com\/\">SQL Practice Site<\/A><BR><A \nhref=\"http:\/\/sqlcourse2.com\/\">SQL Course II<\/A><BR><A \nhref=\"http:\/\/www.pcslink.com\/~ej\/dbweb.html\">Database Jump Site<\/A><BR><A \nhref=\"http:\/\/www.eng.uc.edu\/~jtilley\/tutorial.html\">Programming Tutorials on the \nWeb<\/A><BR><A href=\"http:\/\/www.postgresql.org\/\">PostgreSQL<\/A><BR><A \nhref=\"http:\/\/www.adobe.com\/prodindex\/acrobat\/readstep.html\">Adobe \nAcrobat<\/A><BR><A href=\"http:\/\/www.shelby.net\/abotts\/database.htm\">A Good DB \nCourse<\/A><BR><A \nhref=\"http:\/\/www.muppetlabs.com\/library\/tech\/tutorials.html\">Tutorial \nPage<\/A><BR><A href=\"http:\/\/www.intelligententerprise.com\/\">Intelligent \nEnterprise Magazine<\/A><BR><A \nhref=\"http:\/\/www.let.rug.nl\/~s0367672\/pm_int_e.htm\">miniSQL<\/A><BR><A \nhref=\"http:\/\/hometown.aol.com\/rexxauthor\/sqlbk.htm\">SQL for DB2 Book<\/A><BR><A \nhref=\"http:\/\/msdn.microsoft.com\/library\/psdk\/sql\/8_gs_00.htm\">SQL Server \n7<\/A><BR><A href=\"http:\/\/users.neca.com\/ltruett\/sql.html\">SQL \nReference\/Examples<\/A><BR><A href=\"http:\/\/www.sqlschool.org\/\">SQL \nTopics<\/A><BR><A href=\"http:\/\/sql.terrashare.com\/\">Lee&#8217;s SQL Tutorial<\/A><BR><A \nhref=\"http:\/\/www.datawarehousing.com\/\">Data Warehousing Homepage<\/A><BR><A \nhref=\"http:\/\/www.jamesthornton.com\/nexuswatch\/20001018.html\">MIT SQL for Web \nNerds<\/A><BR><A \nhref=\"http:\/\/s2k-ftp.cs.berkeley.edu:8000\/personal\/aoki\/misc-db-info\/feature-matrix\">RDBMS \nServer Feature Comparison Matrix<\/A><BR><A \nhref=\"http:\/\/www.orafaq.org\/faq2.htm\">Oracle FAQ<\/A><BR><A \nhref=\"http:\/\/cisnet.baruch.cuny.edu\/holowczak\/oracle\/sqlplus\/\">Oracle Developer \n(2000)<\/A><BR><A href=\"http:\/\/www.edm2.com\/0612\/msql7.html\">Intro to Relational \nDatabase Design<\/A><BR><A \nhref=\"http:\/\/www.swynk.com\/friends\/hontz\/caselist.asp\">SQL Sam, the SQL Server \nDetective<\/A><BR><A \nhref=\"http:\/\/www.zdnet.com\/devhead\/stories\/articles\/0,4413,355971,00.html\">ZDNet&#8217;s \nSQL Introduction<\/A><BR><A href=\"http:\/\/baycongroup.com\/tocsql.htm\">Baycon \nGroup&#8217;s SQL Tutorial<\/A><BR><A \nhref=\"http:\/\/www.dragonlee.co.uk\/frame.html\">Dragonlee&#8217;s SQL Tutorial<\/A><BR><A \nhref=\"http:\/\/www.cs.pdx.edu\/~len\/SQLtut.html\">A good, but anonymous SQL \nTutorial<\/A><BR><A href=\"http:\/\/www.db.cs.ucdavis.edu\/teaching\/sqltutorial\/\">UC \nDavis&#8217; Oracle PDF&#8217;s<\/A><BR><A \nhref=\"http:\/\/databases.about.com\/compute\/databases\/?once=true&amp;\">About.com&#8217;s \nDatabase Advisor<\/A><BR><A \nhref=\"http:\/\/www.findtutorials.com\/new\/tutorial\/ViewTutorial.asp?article_id=82\">Manas \nTungare&#8217;s SQL Tutorial at FindTutorials.com<\/A><BR><A \nhref=\"http:\/\/www.dcs.napier.ac.uk\/~andrew\/sql\/\">A Gentle Introduction to \nSQL<\/A><BR><A href=\"http:\/\/sqlwire.com\/\">SQL (News) Wire<\/A> \n<P>vi consiglio vivamente di andare a visitare i link qui sopra riportati , \nspecialmente se volete approfondire gli argomenti qui trattati ed in particolare \ncose come lo standard SQL-92. ricordatevi comunque che se state utilizzando un \ndatabase commerciale ben conosciuto (come Oracle, SQLServer ecc) normalmente il \nposto migliore dove trovare informazioni e&#8217; normalmente il sito web del \nproduttore del vostro DBMS \n<HR>\n<\/BODY>\n","protected":false},"excerpt":{"rendered":"<p>una serie di note da me utilizzate per tenere un corso all&#8217; ERLUG su SQL e sui database relazionali, con un focus sull&#8217;ANSI SQL<\/p>\n","protected":false},"author":1,"featured_media":44,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[12,9,11],"class_list":["post-1","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-informatica","tag-ansi-sql","tag-database","tag-database-relazionali"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Appunti sui database relazionali e sul linguaggio SQL - Suffritti.it<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.suffritti.it\/?p=1\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Appunti sui database relazionali e sul linguaggio SQL - Suffritti.it\" \/>\n<meta property=\"og:description\" content=\"una serie di note da me utilizzate per tenere un corso all&#039; ERLUG su SQL e sui database relazionali, con un focus sull&#039;ANSI SQL\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.suffritti.it\/?p=1\" \/>\n<meta property=\"og:site_name\" content=\"Suffritti.it\" \/>\n<meta property=\"article:published_time\" content=\"2023-04-11T16:18:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-04-11T17:19:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/database-schema-1895779_960_720.png\" \/>\n\t<meta property=\"og:image:width\" content=\"824\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Pietro Suffritti\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Pietro Suffritti\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"56 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1\"},\"author\":{\"name\":\"Pietro Suffritti\",\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/#\\\/schema\\\/person\\\/7d2b80cf72d9701c47de6ad671953fce\"},\"headline\":\"Appunti sui database relazionali e sul linguaggio SQL\",\"datePublished\":\"2023-04-11T16:18:58+00:00\",\"dateModified\":\"2023-04-11T17:19:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1\"},\"wordCount\":10419,\"publisher\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/#\\\/schema\\\/person\\\/7d2b80cf72d9701c47de6ad671953fce\"},\"image\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/database-schema-1895779_960_720.png\",\"keywords\":[\"ansi sql\",\"database\",\"database relazionali\"],\"articleSection\":[\"Informatica\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1\",\"url\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1\",\"name\":\"Appunti sui database relazionali e sul linguaggio SQL - Suffritti.it\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/database-schema-1895779_960_720.png\",\"datePublished\":\"2023-04-11T16:18:58+00:00\",\"dateModified\":\"2023-04-11T17:19:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.suffritti.it\\\/?p=1\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1#primaryimage\",\"url\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/database-schema-1895779_960_720.png\",\"contentUrl\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/database-schema-1895779_960_720.png\",\"width\":824,\"height\":720},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/?p=1#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.suffritti.it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Appunti sui database relazionali e sul linguaggio SQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/#website\",\"url\":\"https:\\\/\\\/www.suffritti.it\\\/\",\"name\":\"Suffritti.it\",\"description\":\"la nostra web-casa\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/#\\\/schema\\\/person\\\/7d2b80cf72d9701c47de6ad671953fce\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.suffritti.it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/#\\\/schema\\\/person\\\/7d2b80cf72d9701c47de6ad671953fce\",\"name\":\"Pietro Suffritti\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/PietroSamuraiSmall.png\",\"url\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/PietroSamuraiSmall.png\",\"contentUrl\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/PietroSamuraiSmall.png\",\"width\":500,\"height\":500,\"caption\":\"Pietro Suffritti\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.suffritti.it\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/PietroSamuraiSmall.png\"},\"sameAs\":[\"https:\\\/\\\/www.suffritti.it\"],\"url\":\"https:\\\/\\\/www.suffritti.it\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Appunti sui database relazionali e sul linguaggio SQL - Suffritti.it","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.suffritti.it\/?p=1","og_locale":"it_IT","og_type":"article","og_title":"Appunti sui database relazionali e sul linguaggio SQL - Suffritti.it","og_description":"una serie di note da me utilizzate per tenere un corso all' ERLUG su SQL e sui database relazionali, con un focus sull'ANSI SQL","og_url":"https:\/\/www.suffritti.it\/?p=1","og_site_name":"Suffritti.it","article_published_time":"2023-04-11T16:18:58+00:00","article_modified_time":"2023-04-11T17:19:57+00:00","og_image":[{"width":824,"height":720,"url":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/database-schema-1895779_960_720.png","type":"image\/png"}],"author":"Pietro Suffritti","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Pietro Suffritti","Tempo di lettura stimato":"56 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.suffritti.it\/?p=1#article","isPartOf":{"@id":"https:\/\/www.suffritti.it\/?p=1"},"author":{"name":"Pietro Suffritti","@id":"https:\/\/www.suffritti.it\/#\/schema\/person\/7d2b80cf72d9701c47de6ad671953fce"},"headline":"Appunti sui database relazionali e sul linguaggio SQL","datePublished":"2023-04-11T16:18:58+00:00","dateModified":"2023-04-11T17:19:57+00:00","mainEntityOfPage":{"@id":"https:\/\/www.suffritti.it\/?p=1"},"wordCount":10419,"publisher":{"@id":"https:\/\/www.suffritti.it\/#\/schema\/person\/7d2b80cf72d9701c47de6ad671953fce"},"image":{"@id":"https:\/\/www.suffritti.it\/?p=1#primaryimage"},"thumbnailUrl":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/database-schema-1895779_960_720.png","keywords":["ansi sql","database","database relazionali"],"articleSection":["Informatica"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/www.suffritti.it\/?p=1","url":"https:\/\/www.suffritti.it\/?p=1","name":"Appunti sui database relazionali e sul linguaggio SQL - Suffritti.it","isPartOf":{"@id":"https:\/\/www.suffritti.it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.suffritti.it\/?p=1#primaryimage"},"image":{"@id":"https:\/\/www.suffritti.it\/?p=1#primaryimage"},"thumbnailUrl":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/database-schema-1895779_960_720.png","datePublished":"2023-04-11T16:18:58+00:00","dateModified":"2023-04-11T17:19:57+00:00","breadcrumb":{"@id":"https:\/\/www.suffritti.it\/?p=1#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.suffritti.it\/?p=1"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/www.suffritti.it\/?p=1#primaryimage","url":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/database-schema-1895779_960_720.png","contentUrl":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/database-schema-1895779_960_720.png","width":824,"height":720},{"@type":"BreadcrumbList","@id":"https:\/\/www.suffritti.it\/?p=1#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.suffritti.it\/"},{"@type":"ListItem","position":2,"name":"Appunti sui database relazionali e sul linguaggio SQL"}]},{"@type":"WebSite","@id":"https:\/\/www.suffritti.it\/#website","url":"https:\/\/www.suffritti.it\/","name":"Suffritti.it","description":"la nostra web-casa","publisher":{"@id":"https:\/\/www.suffritti.it\/#\/schema\/person\/7d2b80cf72d9701c47de6ad671953fce"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.suffritti.it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":["Person","Organization"],"@id":"https:\/\/www.suffritti.it\/#\/schema\/person\/7d2b80cf72d9701c47de6ad671953fce","name":"Pietro Suffritti","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/PietroSamuraiSmall.png","url":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/PietroSamuraiSmall.png","contentUrl":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/PietroSamuraiSmall.png","width":500,"height":500,"caption":"Pietro Suffritti"},"logo":{"@id":"https:\/\/www.suffritti.it\/wp-content\/uploads\/2023\/04\/PietroSamuraiSmall.png"},"sameAs":["https:\/\/www.suffritti.it"],"url":"https:\/\/www.suffritti.it\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/www.suffritti.it\/index.php?rest_route=\/wp\/v2\/posts\/1","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.suffritti.it\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.suffritti.it\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.suffritti.it\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.suffritti.it\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1"}],"version-history":[{"count":2,"href":"https:\/\/www.suffritti.it\/index.php?rest_route=\/wp\/v2\/posts\/1\/revisions"}],"predecessor-version":[{"id":16,"href":"https:\/\/www.suffritti.it\/index.php?rest_route=\/wp\/v2\/posts\/1\/revisions\/16"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.suffritti.it\/index.php?rest_route=\/wp\/v2\/media\/44"}],"wp:attachment":[{"href":"https:\/\/www.suffritti.it\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.suffritti.it\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.suffritti.it\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}