| |
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!
La gestione delle FK
(Foreign Keys) e della RI
(Referential Integrity, Integrità Referenziale) di SQL server contiene gravi manchevolezze e
ancor più gravi limitazioni.
|
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; |
|
è 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; |
|
è 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); |
|
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; |
|
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); |
|
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? |
| 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. |
|
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; |
|
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:
|
sono più rapide da scrivere e
più facili da leggere; |
|
sono *molto* meno 'pericolose' poiché possono contenere *molti*
meno errori; |
|
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; |
| 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. |
|
(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.
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:
| 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 ... |
|
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.
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:
|
per quale motivo sussistono le proibizioni di cui sopra, e quali sono i vantaggi che derivano dalla loro imposizione; |
|
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? |
|
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). |
| 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). |
|
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. |
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).
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.
| 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 ... |
|
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). |
| 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; |
|
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. |
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).
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*.
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!!!!!!!!)
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 |
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, 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!!!! |