{"id":18,"date":"2012-05-15T11:23:00","date_gmt":"2012-05-15T11:23:00","guid":{"rendered":"http:\/\/e-ware.org\/blog\/?p=18"},"modified":"2012-05-15T11:23:00","modified_gmt":"2012-05-15T11:23:00","slug":"sql-aggiornamento-o-inserimento-in-una-sola-query","status":"publish","type":"post","link":"http:\/\/e-ware.org\/blog\/sql-aggiornamento-o-inserimento-in-una-sola-query\/","title":{"rendered":"Sql: Aggiornamento o inserimento in una sola query"},"content":{"rendered":"<div>\u00a0\u00a0 <\/div>\n<div>Quando si scrivono applicazioni che utilizzano un database per il salvataggio dei dati, \u00e8 sempre importante tenere presente che la velocit\u00e0 \u00e8 uno dei fattori pi\u00f9 influenti per la buona riuscita del nostro lavoro. Bisogna infatti pensare che in ogni banca dati possono essere memorizzati milioni di record che, se analizzati e trattati, possono richiedere tempo e risorse che vengono sottratti ad altre attivit\u00e0 che nello stesso momento girano sulla macchina in uso. Proprio per questo motivo quando si lavora su db sql \u00e8 sempre preferibile demandare ogni tipo di attivit\u00e0 al database stesso poich\u00e9 la sua struttura ed i suoi strumenti sono programmati affinch\u00e9 le operazioni siano il meno dispendiose possibile.<\/div>\n<div><\/div>\n<div>Una delle attivit\u00e0 pi\u00f9 ricorrenti da effettuare su una serie di dati \u00e8 il loro aggiornamento (se i dati sono presenti) o il loro inserimento (qualora essi non esistano ancora) all&#8217;interno del database in base ad una serie di variabili campione (ad esempio l&#8217;imput di un utente in una form). Questo lavoro richiede sicuramente un&#8217;estrazione di dati per effettuare un confronto ed un&#8217;analisi al fine di capire se eseguire un aggiornamento o un inserimento. Se volessimo analizzare le operazioni da eseguire con una serie di step, rappresentanti un algoritmo, essi si presenterebbero cos\u00ec:<\/div>\n<div><\/div>\n<div><i>APRO LA CONNESSIONE AL DB<\/i><\/div>\n<div><i>CERCO I DATI NEL DB<\/i><\/div>\n<div><i>SE I DATI SONO PRESENTI:<\/i><\/div>\n<div><i>\u00a0\u00a0\u00a0 AGGIORNA I DATI CON I NUOVI VALORI<\/i><\/div>\n<div><i>ALTRIMENTI:<\/i><\/div>\n<div><i>\u00a0\u00a0\u00a0 INSERISCI I DATI NEL DB<\/i><\/div>\n<div><i>CHIUDO LA CONNESSIONE AL DB<\/i><\/div>\n<div><\/div>\n<div>Come si pu\u00f2 vedere, nonostante il codice sia il pi\u00f9 minimale possibile, esso richiede una serie di passaggi che portano via una notevole quantit\u00e0 di tempo. Basti pensare che se il database in questione contiene 1 milione di record esso verr\u00e0 (nella migliore delle ipotesi) &#8220;percorso&#8221; 2 volte (non necessariamente nella sua interezza) e ci\u00f2 significa analizzare una grande mole di dati. Se a ci\u00f2 aggiungiamo la complessit\u00e0 dei vari moduli dei diversi linguaggi di programmazione che dovrebbero aiutarci in questo lavoro allora capiamo quanto risparmiare secondi preziosi diventi fondamentale.\u00a0<\/div>\n<div><\/div>\n<div>A giungerci in aiuto in questo contesto arriva uno strumento sql davvero molto potente: <b>ON DUPLICATE KEY<\/b>. Esso ci permette di eseguire le operazioni appena viste sopra (aggiornamento o inserimento) in una sola query senza preoccuparci di estrazioni e confronti. Il suo funzionamento \u00e8 molto semplice. Esso si prende in carico il compito di analizzare la presenza di una determinata chiave e nel caso essa sia presente aggiornarla altrimenti inserirla. La sintassi si presenta come segue (l&#8217;esempio \u00e8 riferito ad un db MySql):<\/div>\n<div><\/div>\n<div><i><b>INSERT INTO<\/b> tabella (chiave, campo1, campo2, &#8230;, campoN) <b>VALUES<\/b> (valchiave, val1, val2, &#8230;, valN) <b>ON DUPLICATE KEY UPDATE<\/b> campo1=val1, campo2=val2, &#8230;, campoN = valN<\/i><\/div>\n<div><\/div>\n<div>In pratica la query si occupa di cercare all&#8217;interno del db il record in base al valore della chiave primaria (nel nostro caso <i>chiave<\/i>) qualora esso sia presente verr\u00e0 aggiornato con i valori della tupla che segue VALUES altrimenti verr\u00e0 creata una nuova voce con i valori definiti dopo UPDATE. Si noti che nell&#8217;esempio che il valore di chiave nel caso di inserimento non \u00e8 definito poich\u00e9 il database conterr\u00e0 una chiave con autoincremento ma qualora (per nostre scelte strutturali) la chiave deve essere definita manualmente la si potr\u00e0 passare come un qualsiasi altro parametro. La query diventerebbe cos\u00ec:<\/div>\n<div><\/div>\n<div><i><b>INSERT INTO<\/b> tabella (chiave, campo1, campo2, &#8230;<\/i><i>, campoN<\/i><i>) <b>VALUES<\/b> (valchiave, val1, val2, &#8230;<\/i><i>, valN<\/i><i>) <b>ON DUPLICATE KEY UPDATE<\/b> chiave=valchiave, campo1=val1, campo2=val2, &#8230;<\/i><i>, campoN = valN<\/i><\/div>\n<div><\/div>\n<div>Grazie all&#8217;uso di ON DUPLICATE KEY i vecchi step dell&#8217;algoritmo diventano:<\/div>\n<div><\/div>\n<div><i>APRO LA CONNESSIONE AL DB<\/i><\/div>\n<p><i>ESEGUO QUERY<\/i><\/p>\n<div><i>CHIUDO LA CONNESSIONE AL DB<\/i><\/div>\n<div><\/div>\n<div>La scelta di questo strumento si \u00e8 dimostrata appropriata in un test eseguito di persona. Si \u00e8 visto, infatti, che confrontando i tempi di esecuzione di uno script python non ottimizzato con db mysql in locale popolato da 96000 record di prova, i due diversi algoritmi (con e senza ON DUPLICATE KEY) hanno portato una differenza di tempo di circa il 15%.<br \/><i>\u00a0\u00a0 <\/i><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u00a0\u00a0 Quando si scrivono applicazioni che utilizzano un database per il salvataggio dei dati, \u00e8 sempre importante tenere presente che la velocit\u00e0 \u00e8 uno dei fattori pi\u00f9 influenti per la buona riuscita del nostro lavoro. Bisogna infatti pensare che in ogni banca dati possono essere memorizzati milioni di record che, se analizzati e trattati, possono [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,17],"tags":[],"class_list":["post-18","post","type-post","status-publish","format-standard","hentry","category-opencode","category-sql-database"],"views":1612,"_links":{"self":[{"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/posts\/18","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/comments?post=18"}],"version-history":[{"count":0,"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/posts\/18\/revisions"}],"wp:attachment":[{"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/media?parent=18"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/categories?post=18"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/e-ware.org\/blog\/wp-json\/wp\/v2\/tags?post=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}