SQL server? No grazie!

SQL server? No, grazie!

Obbligato dalle circostanze ad affrontare un pesante lavoro di conversione di una serie di applicazioni da un database serio - ancorché di livello medio - al suddetto SQL server, non ho trovato di meglio - per sublimare le quantità industriali di stress che tale lavoro ha prodotto in me - che raccogliere qui per iscritto quelle che per me sono le principali critiche a SQL server.

Tutti i lettori sono ovviamente *benvenuti*, ma temo che buona parte del testo risulterà assai poco digeribile a chi non abbia un minimo di dimestichezza con i databases SQL. In altre parole: se sei un SQL-profano la tua ultima possibilità di sopravvivenza è cliccare QUI.

A tutti, comunque, auguro una buona lettura!

bullet

FOREIGN KEYS e INTEGRITA’ REFERENZIALE

bullet

I TRIGGERS INSTEAD OF

bullet

ALIAS

bullet

Funzioni definite dall’utente

bullet

TABELLE TEMPORANEE [temporary tables]

bullet

COMMENTI

bullet

ALTRE FUNZIONI MANCANTI

bullet

PARAMETRI STORED PROCEDURES

bullet

CONCATENAZIONE DI STRINGHE

bullet

AMBIGUITA’ NON RISOLTE

bullet

AMBIGUITA' NEL TRATTAMENTO DELLE DATE?

bullet

MANUALE E DOCUMENTAZIONE

bullet

ALLA FINE

FOREIGN KEYS e INTEGRITA’ REFERENZIALE

La gestione delle FK (Foreign Keys) e della RI (Referential Integrity, Integrità Referenziale) di SQL server contiene gravi manchevolezze e ancor più gravi limitazioni.

bullet

manca la possibilità di creare FKs con la clausola ‘ON DELETE SET NULL’, che è *estremamente* utile in *moltissime* situazioni; al loro posto bisogna sempre scrivere *scomodi* triggers (e dire scomodi significa essere dei professionisti dell'understatement) per effettuare l’azione di assegnazione dei valori NULL in occasione dell’eliminazione di records dalle tabelle master;

bullet

è impossibile creare FKs con la clausola ‘CASCADE’ ove queste diano luogo a possibili percorsi circolari o a catena multipla. Benché l’intenzione che sta alla base di tale proibizione, e che ritengo sia quella di evitare la possibilità di generare loops infiniti, sia teoricamente condivisibile, la soluzione adottata è di gran lunga peggiore del male che vorrebbe evitare, dato che in pratica si obbliga il programmatore ad eseguire manualmente (via trigger o – peggio - via codice) le *stesse* operazioni che sarebbero eseguite più comodamente attraverso le FKs, correndo inevitabilmente gli stessi rischi di generazione di loops infiniti;

bullet

è proibita la creazione di FKs ‘cascade’ (on update e on delete) in combinazione con triggers ‘instead of‘ (probabilmente per la risibile motivazione che SQL server implementa il vincolo ‘cascade’ utilizzando a sua volta un trigger ‘instead of’, e che non è possibile creare più ‘instead of’ per la stessa azione sulla stessa tabella);

bullet

per una stessa tabella è impossibile scrivere più triggers in risposta allo stesso tipo di azione, fatto che impedisce la creazione di triggers separati per la gestione di diversi aspetti del comportamento di una tabella;

bullet

in assenza di una FK ON UPDATE CASCADE (che è spesso impossibile creare per i motivi già visti), diventa letteralmente impossibile modificare il valore della primary key di una tabella master referenziata dalla FK di una tabella detail. L'unico modo - paradossale, ridicolo, scandaloso, inaccettabile - di effettuare tale operazione sarebbe quello di creare un record fittizio sulla tabella master, spostare 'manualmente' i record dal record modificando al nuovo record, e infine cancellare il vecchio record. (Se mi sbaglio, e se esiste un modo pulito per eseguire l’operazione descritta, sarei *veramente* interessato a conoscerlo);

bullet

le precauzioni che SQL server dice di voler prendere per garantire la sicurezza dei dati mi costringono ad effettuare operazioni così luridamente sporche, faticose e pericolose, da ottenere un effetto opposto a quello che dichiarano di voler perseguire; ma allora: a che pro?

bullet

en passant, come se non fosse importante: SQL server non implementa il KEY JOIN – che benché non sia ansi consente in modo semplice, sintetico e sicuro di stabilire un JOIN tra tabelle in funzione delle FKs esistenti; e chi ha provato ad usarlo sa quanto sia comodo ed efficace :-)
Dico ciò senza nascondere che le KEY JOIN non sono esattamente una best practice: poiché la sintassi KEY JOIN può essere usata solo quando tra due tabelle esiste una ed una sola relazione FK (perché altrimenti il database non sa quale FK usare), è evidente che l'aggiunta di ulteriori FKs tra le stesse tabelle produce l'effetto collaterale nascosto di invalidare l'uso della KEY JOIN tra le due tabelle, e quindi quello di mandare in vacca senza saperlo codice già scritto altrove; il che evidentemente non è bello.

bullet

per quale motivo, date le seguenti tabelle, non è possibile creare i due vincoli specificati? Quali sono le reali controindicazioni?

create TABLE A(A_key integer not null IDENTITY PRIMARY KEY);

create TABLE B(B_KEY integer not null IDENTITY PRIMARY KEY,
B_KEY_A1 integer NOT NULL,
B_KEY_A2 integer NOT NULL);

ALTER TABLE B add constraint [fk_b1] FOREIGN KEY ([B_lo_key_A1])
                    REFERENCES A ON UPDATE CASCADE ON DELETE CASCADE;

ALTER TABLE B add constraint [fk_b2] FOREIGN KEY ([B_lo_key_A2])
                    REFERENCES A ON UPDATE CASCADE ON DELETE CASCADE;
bullet

benché (come vedremo più sotto) anche la gestione dei triggers di SQL server sia sostanzialmente incompleta e ben lontana dall'essere soddisfacente, la ancor più grave ed estesa inadeguatezza della gestione delle FKs spesso obbliga il programmatore a fare uso dei triggers invece che delle FKs, e questo fatto ha gravi ripercussioni sia sui tempi di sviluppo di un database (e quindi sui costi) sia soprattutto sulla sua manutenibilità e sulla sua intrinseca stabilità; infatti - fatta salva l'insostituibile comodità dei triggers nelle occasioni in cui servono davvero - ritengo che, per tutto ciò che riguarda l’espletamento delle funzioni legate all’integrità referenziale, l’uso delle FKs sia di gran lunga preferibile all’utilizzo dei triggers perché, essendo le FKs puramente dichiarative, presentano i seguenti indiscutibili vantaggi rispetto ai triggers:
bullet

sono più rapide da scrivere e più facili da leggere;

bullet

sono *molto* meno 'pericolose' poiché possono contenere *molti* meno errori;

bullet

sono più facili da manutenere, perché sostanzialmente le FKs richiedono una manutenzione pari a zero, mentre i triggers spesso devono essere manutenuti non solo per modifiche legate ai campi oggetto dell’integrità referenziale ma anche per modifiche riferite ad altri campi della tabella;

bullet

sono più sicure da manutenere, perché (anche per i motivi sopra detti) i triggers di una stessa tabella spesso rischiano di dover essere scritti a più mani e/o in momenti diversi a causa delle differenti funzioni e relazioni della tabella, con la possibilità di generare errori a causa della sovrapposizione di competenze; viceversa ciascuna FK viene tipicamente creata da una sola persona perché riguarda uno specifico aspetto costitutivo della tabella stessa.

I TRIGGERS INSTEAD OF

(ovvero: della mancanza dei TRIGGERS BEFORE)

I triggers instead of svolgono una funzione utile ed interessante (soprattutto in relazione al trattamento delle views), ma non sono in grado di supplire efficacemente, come di fatto si trovano a dover fare, alla *clamorosa* mancanza dei triggers ‘before’.

L’uso dei triggers instead of per governare l’insert e l’update di una tabella con molte colonne è estremamente faticoso perché dopo aver effettuato i controlli e le modifiche del caso si è costretti di fatto a riscrivere completamente l’istruzione INSERT o UPDATE, con greve onere di scrittura e, soprattutto, difficoltà di manutenzione e possibilità di errore.

La presenza di un trigger BEFORE -- che tipicamente consente di intervenire esclusivamente sui valori dei campi che si desidera modificare nel trigger lasciando invariati tutti gli altri -- sarebbe *assolutamente* gradita, soprattutto perché solleverebbe il programmatore dallo svolgimento di lavoro lungo, inutile ed inutilmente pericoloso.

Tanto più che, come dicevo prima, i triggers ‘instead of’ sono incompatibili con la presenza sulla stessa tabella di una FK ‘cascade’, e la necessità di effettuare un trattamento sul trigger ‘instead of’ obbliga di fatto il programmatore a trasferire tutte le FKs ‘cascade’ all’interno del trigger.

ALIAS

Ma (lo so che non si comincia un periodo con una avversativa; MA qui ci vuole!!!) la cosa più incredibilmente assurda che ho trovato in SQL server, quella che più di ogni altra mi ha fatto disperare di poter mai davvero usare SQL server per qualche lavoro decente, è la sua incapacità di riutilizzare gli alias assegnati alle colonne:

bullet

sia nella definizione di altre campi in una istruzione SELECT; se ad esempio in una select io determino un VALORE e poi devo determinare un secondo valore attraverso un'espressione che coinvolge il VALORE trovato, mi piacerebbe tanto poter scrivere qualcosa come:
    select sqrt((a+b*c)/x + z*a + b - 173) AS valore, valore * 2 FROM ...
ma ovviamente SQL server mi impedisce di usare la sintassi indicata con il barrato, e mi obbliga a scrivere:
    select sqrt((a+b*c)/x + z*a + b - 173) AS valore,
     sqrt((a+b*c)/x + z*a + b - 173)
* 2 FROM ...

bullet

sia nelle clausole WHERE (!!!!), JOIN (!!!!!), GROUP BY, HAVING.

Si è deliberatamente obbligati a scrivere codice stupidamente ripetitivo e soprattutto assai pericoloso da manutenere.

Se poi l’alias è definito su un calcolo pesante o addirittura su una funzione (che può essere computazionalmente molto pesante) intervengono anche possibili problemi di performance, dato che il calcolo o la funzione devono essere eseguiti più volte.

Bontà Sua e incommensurabile miracolo: è possibile riutilizzare gli alias nella clausola ORDER BY. Ma allora, anche solo perché gli è venuto in mente, a chi ha scritto SQL server, che possa in una qualunque misura essere utile dare ai poveri forzati di SQL server la possibilità di riutilizzare gli alias, forse che non era il caso di ipotizzare di estendere la funzionalità anche alle altre clausole? (si capisce sufficientemente bene, che la domanda è una domanda retorica?)
Perché se è utile, è utile. E se non è utile, non è utile. E benignamente concedere l' immaginifica possibilità del riutilizzo degli alias sull'ORDER BY non sposta il problema né avanti né indietro, dato che il problema è fermo alla clausola WHERE (che è presente su *TUTTE* le queries vere di questo mondo, ad eccezione di quelle false) e sulla clausola GROUP BY (che è presente su una buonissima percentuale delle più complesse). Ma forse se ne sono dimenticati.

Funzioni definite dall’utente

Solo nella fantasia malata di chi pensa che la perfezione sia di questo mondo (no, adesso non sto parlando né degli hegeliani né dei comunisti) è possibile pensare di escludere dalle funzioni definite dall’utente l’accesso a valori non deterministici e l’accesso e la modifica di tabelle; con il risultato che, ad esempio, in SQL server non è possibile creare la banale funzione TODAY() che restituisce la data corrente (magari formattata secondo una certa modalità di mio gradimento), ma bisogna per forza chiamare qualcosa come convert(varchar, getdate(), 112) che oltre ad essere espressione inutilmente oscura e faticosa è soprattutto molto più difficile da manutenere; né è possibile creare la funzione MY_RANDOM() che restituisce un numero casuale di un certo tipo (ad esempio: in un certo range).
In specifico non capisco:

bullet

per quale motivo sussistono le proibizioni di cui sopra, e quali sono i vantaggi che derivano dalla loro imposizione;

bullet

assumendo che le operazioni proibite (ad esempio: quelle che coinvolgono valori non deterministici) siano davvero intrinsecamente ‘pericolose’, perché SQL server concede comunque la possibilità di eseguirle (ancorché obbligando il povero programmatore ad ingarbugliarsi in inutili giri di codice e complicatissimi stratagemmi)? Ovvero: il presunto vantaggio in termini di sicurezza e stabilità non viene comunque perso? Ovvero: perché non abolire completamente la funzione RAND(), pericolosa portatrice di sospette forme di (pseudo)indeterminazione? E perché ostinarsi a supportare la GETDATE(), così sgradevolmente legata al mondo reale da introdurre elementi di incertezza nei cieli perfetti di SQL server?

bullet

la necessità di indicare l’owner della funzione quando la si richiama: ad esempio per chiamare la funzione xyz() devo scrivere owner.xyz(); si tratta di un comportamento fastidioso (bisogna ricordarsi di premettere l’orpello ” owner.” - che comunque allunga il codice, e tutto ciò che allunga il codice inutilmente non solo è inutile e fastidioso, ma in generale è anche dannoso] - davanti ai nomi di funzione), inconsistente (con gli altri oggetti database non funziona così, nel senso che è bensì possibile indicare l’owner ma non è obbligatorio), inutile (perché non ha alcuna effettiva utilità – in quanto obbligatorio) e potenzialmente limitativo, perché impedisce l’uso di versioni diverse della stessa funzione in funzione dell’utente collegato al database (mentre è possibile farlo, ad esempio, per le tabelle).

bullet

l’obbligo di usare la clausola ‘default’ per indicare il default di un parametro; non è propriamente un fatto grave, è solo stupido, ma proprio stupido, ma proprio stupido stupido: default significa propriamente ‘in mancanza’, e obbligare alla positiva specificazione del termine ‘default’ nei casi in cui non si vuole indicare uno specifico valore è comportamento degno dell’insegnante che imperiosamente ingiunge alla sua classe: “chi è assente alzi la mano!” Tanto più che *spesso* il parametro default viene utilizzato proprio in casi in cui, dovendo estendere la funzionalità di una funzione preesistente e dovendone mantenere rigorosamente inalterato il comportamento in tutte le circostanze già trattate, si desidera propriamente evitare di dover aggiornare tutti i punti del codice in cui la funzione viene richiamata (e che possono essere anche difficili da raggiungere o da ricordare, ad esempio su un report installato presso il cliente, che magari non è neppure a conoscenza della modifica intercorsa, e che non se ne accorgerà sino a che la sua stampa smetterà di funzionare, tipicamente con un messaggio di errore poco pertinente e ancor meno comprensibile).

bullet

per quale motivo in una query del tipo: select RAND(), * FROM table il valore di RAND() sia lo stesso per tutte le righe restituite. Secondo me la funzione dovrebbe restituire invece un valore differente per ogni riga.
Sospetto che questo comportamento sia  legato alla stessa logica neo-hegeliana che vive con ostentato ribrezzo il contatto con valori non deterministici.

TABELLE TEMPORANEE [temporary tables]

Nei database serî le temporary tables sono tabelle persistenti (create una sola volta) dotate della caratteristica peculiare di non condividere i dati tra le connessioni: ciascuna connessione vede solo i dati che ha inserito. Al termine di ciascuna connessione i suoi dati caricati sulle temporary tables vengono automaticamente eliminati.
Le local tables sono delle temporary tables non persistenti: vengono create all'interno di una connessione (tipicamente all'interno di una stored procedures) e al termine della connessione vengono eliminate insieme ai dati (non vengono eliminati solo i dati, ma anche la stessa tabella, che cessa di esistere).

SQL server non gestisce le temporary tables. O meglio: lui dice di gestirle, ma quelle che spaccia per tali in effetti sono propriamente le local tables, dato che devono essere create ogni volta che vengono utilizzate. Le local tables sono comodissime per uso strettamente locale: ad esempio per particolari elaborazioni all'interno di stored procedure risulta spesso comodissimo poter usare particolari tabelle di supporto, che possono essere utilmente create sotto la forma di local tables. Le temporary tables trovano invece la loro specifica utilità in contesti tipicamente diffusi (non locali), e servono ad esempio per contenere e trasmettere dati in differenti parti di una applicazione.
In SQL server l'obbligo di verificare ogni volta, in ogni punto del programma in cui serve, di aver già creato la cosiddetta temporary table (e, peggio, di non averla ancora creata pena l'errore di esecuzione) è così pesante da consigliare di fare addirittura a meno delle temporary tables e di usare, come ho scelto di fare io, tabelle normali con un identificatore univoco per ciascuna connessione. Tale pratica, di per sé scomoda anche solo per l'obbligo di garantire l'univocità degli identificatori utilizzati e per il fatto di doversi ricordare, al termine, di cancellare i dati inseriti, tende ad influire negativamente sia sulla concorrenza tra connessioni (come sempre avviene quando si lavora sulla stessa tabella) sia sulle prestazioni del database (poiché le operazioni di inserimento e ricerca non vengono eseguite su piccole tabelle fisicamente separate per ogni connessione come capita con le true temporary tables, ma su una stessa grande tabella dove confluiscono i dati di tutte le connessioni; e - come ricordava Virgilio: divide et impera - lavorare su tabelle grandi è molto più costoso che su tabelle piccole).

COMMENTI

Manca la possibilità di inserire commenti sui vari oggetti che costituiscono il database: tabelle, views, colonne, indici, foreign keys, stored procedures, eccetera. La possibilità di inserire commenti, ancorché poco utilizzata da moltissimi (leggi: troppi) programmatori, è *fondamentale* per una buona manutenzione di databases complessi.

ALTRE FUNZIONI MANCANTI

bullet

NUMBER(): manca la funzione NUMBER() che per ogni record di una query restituisce un numero progressivo. Questa funzione, che è presente in databases di minor ‘caratura’ (e costo) di SQL server è tanto *preziosa* nella generazione di primary keys o di numeri di indice quanto *difficile* e/o *pesante* da emulare, soprattutto per queries con molti records. Che sia un'ulteriore incarnazione della perversa logica neo-hegeliana? In fondo si tratterebbe pur sempre di una funzione che restituisce un valore diverso per ogni riga della query, e quindi classificabile come impura ...

bullet

LIST(): manca l’utilissima funzione LIST() da usarsi in istruzioni GROUP BY (a dire il vero tale funzione manca in molti databases, anche di buon livello).

bullet

DATE: manca - ripeto: manca! - il tipo di dato DATE: il tipo DATETIME, che comprende l’ora oltre che la data, non è sempre un valido sostituto dato che in molte situazioni è non solo inutile, ma *decisamente* scomodo. Manca anche, forse coerentemente, la funzione TODAY() che restituisca semplicemente la data odierna priva di ora;

bullet

READ: manca la possibilità di eseguire rapidamente e semplicemente le istruzioni contenute in un file (o in cento diversi files senza trattarli singolarmente). Per intenderci: qualcosa di simile a “read xxx.SQL;”. Si tratta certo di una mancanza banale, ma notevolmente fastidiosa.

PARAMETRI STORED PROCEDURES

L’impossibilità di passare una espressione o una funzione come parametro ad una stored procedure ha dell’ *incredibile*. Io semplicemente non ci volevo credere. (Se sapete che non è vero e mi spiegate come funziona, vi offro minimo una pizza.) Ogni volta che bisogna passare ad una stored procedure la più semplice delle espressioni bisogna creare una variabile, assegnarle il valore dell’espressione e passare la variabile alla stored procedure. Se serviva un modo altamente efficace per rendere più oscuro, più lungo e più faticoso sia da scrivere che da leggere il codice delle stored procedures, bè, l’hanno trovato.

Sembra di essere ritornati alle asperità sintattiche dei linguaggi di quarant’anni fa, con la piccola differenza che mentre il Fortran e i suoi fratellini vivevano spartanamente in pochi k-bytes di memoria centrale, SQL server si ciba indecorosamente di MIPS e di Giga bytes di ram. (Salvo non sapere come dividere una query troppo complessa tra più processori, obbligando il sistemista a farlo lavorare con un processore per volta) (si, è incredibile, ma mi è capitato anche questo).

CONCATENAZIONE DI STRINGHE

La mancanza di uno specifico operatore di concatenazione di stringhe impedisce una semplice ed efficace distinzione tra somma aritmetica e concatenazione di stringhe. Ad esempio, la seguente banale istruzione 

select 'VALORE = ' + 123

viene rifiutata da SQL server perché SQL server cerca di effettuare la somma aritmetica e trova che la stringa 'VALORE = ' non è un valore numerico.
Se esistesse (come in altri databases) uno specifico operatore per l'operazione 'concatenazione di stringhe' (mettiamo l'operatore || ), l'operazione potrebbe essere eseguita, semplicemente e senza fraintendimenti di sorta, come:

select 'VALORE = ' || 123

SQL server invece obbliga ad effettuare una conversione esplicita

select 'VALORE = ' + cast(123 as varchar(10))

MA SIAMO PAZZI????? Ogni volta che concateno un numero ed una stringa devo stare a fare tutta 'sta manfrina? Non ho mica tempo da perdere, io!

NB: sì, lo so che esiste anche anche la possibilità di usare STR(123), ma la formattazione del numero è *insoddisfacente*.

AMBIGUITA’ NON RISOLTE

Consideriamo due semplicissime tabelle così definite e popolate:

CREATE TABLE a (
            A_lo_key int NOT NULL PRIMARY KEY,

           
A_i_qta int);

CREATE TABLE b (
            B_lo_key int NOT NULL IDENTITY PRIMARY KEY,
            B_lo_key_A int,
            B_i_qta int);

INSERT INTO a (A_lo_key, A_i_qta) VALUES (1000, 0);

INSERT INTO b (B_lo_key_A, B_i_qta) VALUES (1000, 1);
INSERT INTO b (B_lo_key_A, B_i_qta) VALUES (1000, 2);
INSERT INTO b (B_lo_key_A, B_i_qta) VALUES (1000, 3);
INSERT INTO b (B_lo_key_A, B_i_qta) VALUES (1000, 4);

Consideriamo inoltre la seguente istruzione:

UPDATE a SET A_i_qta = A_i_qta + B_i_qta    FROM a JOIN b ON (A_lo_key = B_lo_key_A);

L’istruzione è evidentemente ambigua e per questo non troverei poi così strano se il database si rifiutasse di eseguirla. Tuttavia, una volta che il database abbia accettato la sintassi dell’istruzione e l’abbia eseguita, io non ho alcun dubbio su quello che mi aspetto sia il valore del campo A_i_qta al termine dell'esecuzione: deve essere pitagoricamente pari a 10 (ovvero: 1+2+3+4).
SQL server considera legittima l’istruzione, ma la esegue in modo parziale e assurdo: al termine dell’esecuzione il campo A_i_qta della riga inserita nella tabella A vale 1 perché di fatto SQL server esegue l’operazione solo con la prima riga (apparentemente la prima in ordine di inserimento) che incontra sulla tabella B, trascurando tutte le altre.
Dato che in SQL la buona teoria prescrive che l’ordine di inserimento (ma in generale qualunque ordine e ordinamento, a meno che non sia dichiarato esplicitamente) sia da considerarsi totalmente trascurabile, lo stato del database al termine dell’esecuzione di questa banale istruzione è sostanzialmente *impredicibile*: un altro bel successo di SQL server!!!
(E poi si rifiuta di includere getdate() in una funzione perché rende un valore indeterminato!!!!!!!!)

DATE AMBIGUE

Atteso che uso un database su cui è impostata la lingua italiana e che DATEFORMAT vale 'ymd' non sono riuscito a capire perché '2005-12-01' interpretato come data rende il 12 di gennaio (creando fra l'altro una gravissima confusione con la notazione più generale '20051201' che invece indica correttamente il primo di dicembre). Il comportamento mi sembra poco documentato e complessivamente assurdo.

Inoltre mi sembra incomprensibile e insensato il risultato della seguente query, le cui due colonne dovrebbero essere assolutamente identiche:

declare @s varchar(20);
set @s =   convert(datetime, getdate(), 121);
select @s, convert(datetime, getdate(), 121);

@s convert(datetime, getdate(), 121)
giu 4 2008 11:57AM  2008-06-04 11:57:50.833

MANUALE E DOCUMENTAZIONE

Insieme a SQL server non viene fornita alcuna forma di documentazione cartacea. O almeno io non l'ho ricevuta. A parziale compensazione esiste un vastissimo HELP-ON-LINE che è possibile consultare per attingere tutte le informazioni necessarie.
Fatta salva la comodità di trovare con facilità un aiuto immediato su specifici argomenti (a patto di sapere con una certa precisione ciò che si sta cercando, il che a dire il vero è tutt'altro che scontato soprattutto quando ciò che si sta cercando è un errore o una anomalia), tale help-on-line a mio avviso è prolisso, poco organizzato e poco 'navigabile'.
A titolo di esempio: io ho fatto *veramente* fatica a trovare conferma nell'help-on-line di quanto da me contestato nel paragrafo PARAMETRI STORED PROCEDURES (e fors'anche non l'ho mai trovato). Nè ho mai trovato documentazione sulla data ambigua di cui sopra.

Manca completamente un manuale di riferimento (magari cartaceo) organizzato per argomento in cui si possa trovare un inquadramento complessivo dei vari argomenti. Chissà, forse organizzare [costosissimi] corsi di formazione rende meglio che scrivere manuali ben fatti ...

ALLA FINE

Alla fine, per fortuna, non uso né molto né spesso SQL server, e conseguentemente non lo conosco neppure granché bene. E per fortuna, perché altrimenti invece che un paio di paginette di commenti e critiche, avrei scritto i Promessi Sposi!

L’impressione complessiva che ho derivato dall’approccio con SQL server è che si tratti di un prodotto di fascia medio bassa che per motivi banalmente commerciali è stato in tutta fretta (versioni 6 e 7, fine anni '90) rattoppato e rappatchato e improvvidamente gettato nell’arena dei databases SQL veri. Né le pezze tardive e parziali (versione 8/2000) che sono state messe per cercare faticosamente di coprirne le carenze più significative hanno potuto cambiare la sostanza dei fatti.

Tutte le critiche da me portate al funzionamento di SQL server potrebbero banalmente tradursi in una sola contestazione e constatazione: il prodotto è semplicemente e strutturalmente inadeguato all'uso per il quale viene proposto; non è una piattaforma in grado di sostenere lo sviluppo di applicazioni vaste, solide e ben strutturate; non può essere messo a confronto con prodotti del calibro di Oracle e Sybase, non può gareggiare nella categoria dei 'pesi massimi' del mondo dei database, tutt'al più in quella dei pesi welter.

Non posso peraltro non rilevare che, in un contesto in cui una considerevolissima parte di aziende pervicacemente persiste ad utilizzare Visual Basic come linguaggio di sviluppo per ogni genere di applicazione, forse non è poi così illogico che il database di riferimento sia SQL server, perché il livello di inadeguatezza al proprio compito di entrambi i prodotti è perfettamente compatibile e allineato.
E poi, diciamoci la verità: chi usa Visual Basic come ambiente di sviluppo, come fa a notare la differenza tra SQL server e un database serio?

Quello che invece, ahimè, non si può contestare a SQL server, e che rappresenta certamente il suo punto di forza, è la sua clamorosa potenza commerciale, dinanzi alla quale troppo spesso i tecnici sono costretti a soccombere. Anche se a volte, la sera, si ritirano nel segreto della loro cameretta, e confidano al fido web-diario ciò che sentono nel profondo del cuore: SQL server? No, grazie!

NB: tutto quanto scritto in questa pagina vuole essere la manifestazione della mia personale opinione (prevalentemente tecnica) nei confronti di un prodotto commerciale pubblicamente disponibile e valutabile. Chiunque legga questa pagina è ovviamente libero di effettuare una diretta valutazione del prodotto e di formarsi una propria idea indipendentemente dalle mie opinabili opinioni, tanto più che stasera forse ho mangiato un po' pesante e il mio umore non è dei migliori. O forse è che ho passato gli ultimi mesi su SQL server e che ......

Mi scuso in anticipo per ogni eventuale scorrettezza in cui sia incorso, che sono pienamente disponibile ad emendare.

Sono molto interessato a pareri di altri utilizzatori di SQL server, sia che si trovino nel campo degli entusiasti che in quello dei detrattori. Per ogni comunicazione sarò lieto di ricevere messaggi su SQLserver.nograzie@feaci.it

PS: la versione di SQL server da me utilizzata per questa allegra recensione è la “Microsoft SQL Server 2000 - 8.00.818 (Intel X86) May 31 2003 16:08:15 Copyright (c) 1988-2003 Microsoft Corporation Standard Edition on Windows NT 5.2 (Build 3790: )”.

PS/2 (ma niente a che vedere con l'IBM): se mi scrivete che ho sbagliato e mi spiegate come fare (in modo ragionevole!) ad eseguire le operazioni che io credo essere ineseguibili, la pizza (minimo, a crescere) ve la offro davvero!!!! E volentieri!!!!

aggiornato il 23/01/2010

home

scrivimi, se ti va