Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Query parametriche e testo SQL completo

330 views
Skip to first unread message

Roberto Casarini

unread,
May 10, 2010, 11:43:37 AM5/10/10
to
All'interno di un'applicazione faccio uso di query parametriche, per
intenderci: "INSERT INTO TABLE_1 (IDPK, Nome, Cognome) VALUES (:IDPK,
:Nome, :Cognome)".
Vorrei implementare la funzionalitᅵ di loggare eventuali errori generati
dal database (tipo il tentativo di duplicare una chiave primaria o un
indice unique) su un apposito file di log, ma quello che mi manca ᅵ come
tirare fuori il testo SQL completato con i valori che sostituiscono i
parametri, cioᅵ nel caso precedente qualcosa del tipo "INSERT INTO
TABLE_1 (IDPK, Nome, Cognome) VALUES ('5', 'Pippo', 'PierPippo')".
C'ᅵ un'automazione nei componenti che ereditano da TQuery o TDataset che
faccia questo? Ho guardato sul manuale e ho googlato in giro ma non ho
trovato nulla.

Chiaramente potrei farlo a "manazza", cioᅵ prelevando tutti i parametri
dalla proprietᅵ Params e sostituendoli sulla stringa SQL, ma ᅵ possibile
che non ci sia niente del genere nel componente?

Gianpiero Caretti

unread,
May 11, 2010, 1:52:57 AM5/11/10
to
On 10 Mag, 17:43, Roberto Casarini <r.casar...@tiscali.it> wrote:

> All'interno di un'applicazione faccio uso di query parametriche

> [...]
> quello che mi manca è come tirare fuori il testo SQL completato con


> i valori che sostituiscono i parametri

Quando credi una PS la stringa SQL con i placeholder viene inviata al
driver del tuo DB. Questo poi ne fa un po' quel che vuole per
ottimizzare le performance.
Ti faccio un esempio di quello che alcuni driver/DB fanno:

1. Inviano al DB la PS che la compila o addirittura la compila
direttamente il driver e poi la invia compilata al DB.
2. Il DB poi la esegue crearendo, per esempio, una VIEW dinamica
corredata da indici dinamici.
A questo punto la stringa SQL iniziale non esiste più!

Quando poi tu popoli (credi di popolare) la tua stringa SQL avviene
questo:
3. il driver riceve solo i tuoi params e li manda al DB
4. Il DB li trasforrma in puntatori agli indici della view dinamica
sopra
5. Il DB restituisce i valori della riga puntata.
Cioè il DB, saltando tutto il processo di parsing e compilazione della
stringa SQL con i valori ricevuti al momento, ti restituisce i dati
molto più velocemente

Come vedi, allora, quando popoli la tua PS, essa in realtà non esiste
più per il DB, ma esistono solo dei puntatori a uno o più dei suoi
indici. Se poi ci sono errori di qualsiasi tipo diventa difficile
restituirti la stringa "preparata" perché in realtà non esiste proprio
una stringa preparata, a meno che il driver (o tu) non la scriva in
forma di stringa appositamente per te nella sua gestione dell'errore.

Ultima nota: il meccanismo spiegato sopra mostra anche come molti
usano le PS in modo sbagliato: in java, per esempio, molti creano un
oggetto PreparedStatement al volo solo quando serve e contestualmente
lo popolano con i parametri, costringendo il DB ad eseguire i passi 1
e 2 ad ogni esecuzione.

Ciao,
Gp

Roberto Casarini

unread,
May 11, 2010, 2:58:01 AM5/11/10
to
Molto interessante quanto hai scritto.
Io pensavo che fossero i componenti di accesso al db a fare il parsing
della stringa, e invece fa tutto il db.
Vabb�, vuol dire che nel file di log riporter� la stringa sql con i
parametri e di fianco l'elenco dei valori assegnati ai parametri.

^_Goblin_^

unread,
May 11, 2010, 3:25:40 AM5/11/10
to
Il 11/05/2010 8.58, Roberto Casarini ha scritto:
> Molto interessante quanto hai scritto.
> Io pensavo che fossero i componenti di accesso al db a fare il parsing
> della stringa, e invece fa tutto il db.
> Vabbè, vuol dire che nel file di log riporterò la stringa sql con i

> parametri e di fianco l'elenco dei valori assegnati ai parametri.

Non vorrei fare la cosa piu' facile di quello che potrebbe essere, ma
avendo la stringa SQL di partenza, i parametri, che sono delle liste,
con un ciclo e 1 replacestring riesci a ricavare il tutto ....
qualche cosa del tipo:
sCmd := <Query>Comando;
for j := 0 to <Query>Parameters.Count -1 do;
begin
sPar := <Query>Parameters[j].Value;
sCmd := StringReplace(sCmd,':'+<Query>Parameters[j].Name,
sPar,[rfIgnoreCase]);
end;
NB: Queste 4 righe non sono testate, ma buttate giu' solo come schema,
in quanto non distinguo i tipi di parametro, non testo se il parametro
esiste e altre cose, ma potrebbe essere uno spunto da cui partire.

^_Goblin_^


--
Ibis et redibis non morieris in bello
http://goblinland.myminicity.com/

Roberto Casarini

unread,
May 11, 2010, 5:41:39 AM5/11/10
to
^_Goblin_^ ha scritto:

> Non vorrei fare la cosa piu' facile di quello che potrebbe essere, ma
> avendo la stringa SQL di partenza, i parametri, che sono delle liste,
> con un ciclo e 1 replacestring riesci a ricavare il tutto ....
> qualche cosa del tipo:
> sCmd := <Query>Comando;
> for j := 0 to <Query>Parameters.Count -1 do;
> begin
> sPar := <Query>Parameters[j].Value;
> sCmd := StringReplace(sCmd,':'+<Query>Parameters[j].Name,
> sPar,[rfIgnoreCase]);
> end;
> NB: Queste 4 righe non sono testate, ma buttate giu' solo come schema,
> in quanto non distinguo i tipi di parametro, non testo se il parametro
> esiste e altre cose, ma potrebbe essere uno spunto da cui partire.

Una soluzione di quel genere l'avevo pensata anch'io, ma in realt�
dovrei tener conto del tipo di dato e anche del motore db che ho sotto,
per esempio se uso mysql e il parametro � una data dovr� trasformarlo
nel formato "yyyy-mm-dd", invece se il db � access il formato �
"#mm-dd-yyyy#" (o qualcosa del genere, non ricordo pi� come lavora access).
Comunque per ottenere una stringa SQL eseguibile diventa un lavoraccio.
Ed in effetti a me interessa solo sapere quali dati hanno causato il
problema e la struttura della query eseguita.

ACSH

unread,
May 11, 2010, 7:10:04 AM5/11/10
to
Roberto Casarini ha scritto:

> All'interno di un'applicazione faccio uso di query parametriche, per
> intenderci: "INSERT INTO TABLE_1 (IDPK, Nome, Cognome) VALUES (:IDPK,
> :Nome, :Cognome)".

> Vorrei implementare la funzionalit� di loggare eventuali errori generati

> dal database (tipo il tentativo di duplicare una chiave primaria o un

> indice unique) su un apposito file di log, ma quello che mi manca � come

> tirare fuori il testo SQL completato con i valori che sostituiscono i

> parametri, cio� nel caso precedente qualcosa del tipo "INSERT INTO

> TABLE_1 (IDPK, Nome, Cognome) VALUES ('5', 'Pippo', 'PierPippo')".

> C'� un'automazione nei componenti che ereditano da TQuery o TDataset che

> faccia questo? Ho guardato sul manuale e ho googlato in giro ma non ho
> trovato nulla.

TSQLMonitor potrebbe fare al caso tuo.

http://docs.codegear.com/products/rad_studio/radstudio2007/RS2007_helpupdate
s/HUpdate4/EN/html/devwin32/unidebuggingdbexpressapplications_xml.html

PS: � sempre meglio specificare la versione di Delphi che si usa, il DB,
la
tecnologia di accesso, il sistema operativo, ecc... quando si chiede la
soluzione a qualche dubbio/problema.

ACSH

--

questo articolo e` stato inviato via web dal servizio gratuito
http://www.newsland.it/news segnala gli abusi ad ab...@newsland.it


Morde

unread,
May 13, 2010, 5:24:02 AM5/13/10
to
Roberto Casarini ha pensato forte :

> Comunque per ottenere una stringa SQL eseguibile diventa un lavoraccio.
> Ed in effetti a me interessa solo sapere quali dati hanno causato il problema
> e la struttura della query eseguita.

L'approccio corretto ᅵ di agire sul sistema di logging/tracing del
database.
Come giᅵ spiegato da altri, ᅵ il driver che gestisce l'sql da invocare,
e non ᅵ detto che sia come tu lo hai scritto. Ado per esempio genera
dei micro sql di update, scomponendo la query se ᅵ molto grossa in
piccole query atomiche.

Per lavori di questo genere nel mio logging subsystem ho solo bisogno
di loggare i parametri, perchᅵ la query giᅵ la conosco visto che ᅵ
annegata nei componenti e, di conseguenza, nei sorgenti.

ciao

--
Morde


Morde

unread,
May 13, 2010, 5:25:51 AM5/13/10
to
Nel suo scritto precedente, ACSH ha sostenuto :
> PS: ᅵ sempre meglio specificare la versione di Delphi che si usa, il DB,

> la
> tecnologia di accesso, il sistema operativo, ecc... quando si chiede la
> soluzione a qualche dubbio/problema.

Infatti esiste anche un sistema di logging delle query passate alla dll
ADO (msado....dll) , ma come dicevo pocanzi la sola cosa da conoscere
*runtime* ᅵ il valore del parametro, tutto il resto ᅵ giᅵ conosciuto.
ciao

--
Morde


0 new messages