Newsgroup: it.comp.lang.visual-basic
Titolo: Problema SQL nella ricerca di stringhe con caratteri particolari

Salve a tutti :-)
Ho un problema con SQL nella ricerca di parti di stringhe, quando nella
stringa da cercare compare il carattere apice (').
So che il carattere apice (') viene usato nella stringa SQL per
delimitare delle stringhe.
La stringa da cercare nel DB è un numero di serie... e fra i tanti
numeri di serie mi è capitato uno che al suo interno contiene il
carattere apice (').
Per cui quando lo vado a cercare non lo trovo.
In pratica la stringa SQL diventa qualcosa del genere:
"SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE '%
01ABC123456'00054%' ;"
In questo modo mi da giustamente un errore perchè non trova il
delimitatore...
Ho provato a cambiare a manina nel DB mettendo due apici ('')  [nota non
un doppio apice (") ]. In questo modo non da errore, però non trova il
numero di serie...
C'è un modo per ovviare a questo ... oppure conviene che cambi il
carattere a manina nel DB con un altro... e che quando lo incontro nelle
volte successive in inserimento lo converta in quel carattere?
Ringrazio anticipatamente per le risposte :-)
-- 
Daniele Pinna  (leva oops. per rispondere)
Utente Skype: dapinna
Sito Web 
DAPINNA.COM
: 
http://www.dapinna.com
Il Docfa in Pillole:  
http://www.ildocfainpillole.it

 numero di serie...
Sicuro che cosě non funzioni?
Mi pare strano...
 "SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE '%
 01ABC123456''00054%' ;"
-- 
Freccia@Bulldozer63 :D

  01ABC123456''00054%' ;"
Si perchè la stringa viene interpretata da SQL (o almeno credo... non ho
molta esperienza in merito) come se non avesse quei due apici, cioè:
"SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE '%
01ABC12345600054%' ;"
Anzi domani provo a togliere dal database i due apici consecutivi e
vedere se così li trova...
Hummm c'è per caso un carattere che, nella sintassi SQL, se messo prima
di un altro carattere lo fa interpretare in modo letterale, cioè nel mio
caso come il carattere apice e non come un carattere speciale di
delimitazione?


> In questo modo non da errore, però non trova il numero di serie...
In realta' tu hai cambiato SIA nel DB che nella stringa di ricerca
l'apice singolo in doppio apice, risolvendo (senza volerlo) il vero
problema... ma solo a meta'.
L'apice e' considerato un delimitatore in SQL. Per passare una stringa
che contiene UN SOLO apice, bisogna raddoppiarlo.
Es.
Se nel DB ho la stringa "abc'123", nell'opportuna SELECT dovro' passare come parametro di ricerca 
'abc''123'. Nota quindi che l'apice raddoppiato viene interpretato come UN SINGOLO apice all'interno 
di una stringa SQL.
Per risolvere il problema originale ti bastava quindi raddoppiare gli apici nella stringa di ricerca 
(e NON nel DB).
Raddoppiandoli nel DB e nella stringa di ricerca, in base a quanto detto, stai ora cercando una 
stringa che contiene UN SOLO apice, mentre nel DB ce ne sono DUE.
Per trovare il record, dopo le modifiche che hai fatto dovresti modificare la select inserendo 4 
apici (LIKE '%01ABC123456''''00054%'). L'interprete SQL ne cerchera' la meta', ovvero DUE, ovvero 
quanti ce ne sono ora nel DB.
hth,
Lokar 

io prima di comporre la query, prendo la stringa di partenza e faccio un 
replace degli apici con questo:
miaStringa = "hfhfhfh ' hfhfhf ' hfhfh"
miaStringa = Replace(miaStringa,"'", "'+''''+'")
e poi creo il like con i due apici iniziale finale
"miatabella.miocampo Like " +"'" +miaStringa +"'" 

 quanti ce ne sono ora nel DB.
OK... nel DB ovviamente ora rimetto le cose apposto :-)
Anche se si riferisce ad un solo componente, se non lo rimetto come
prima poi quando/se gli sparo il seriale per cercarlo non lo troverebbe
più...
Cmq Grazie per il prezioso aiuto :-)))


 "miatabella.miocampo Like " +"'" +miaStringa +"'" 
-- 


ed eventualmente raddoppiarlo
Se lo fai tout-court ti risparmi un test e un mal ti test (scusa non ho 
resistito)
"SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE '%" + 
REPLACE(tuastringa, "'", "''") + "%"
dove
"'" = apicedoppio apicesingolo apicedoppio
"''" = apicedoppio apicesingolo apicesingolo apicedoppio
ciao
Stefano

 01ABC123456'00054%' ;"
soluzione che uso da anni:
    sql = "SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE " & Chr(39) &
"%01ABC123456'00054%" & Chr(39) & ";"
    rs.Open sql, cn, Options:=adCmdText
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 "''" = apicedoppio apicesingolo apicesingolo apicedoppio
Ma i caratteri speciali nelle comparazioni LIKE non si mettono tra quadre?
LIKE 'abc[']def'
Ciao 


Si, ma i caratteri speciali sono [ _ % (e forse altri), mentre ' non è 
un carattere speciale in questo senso.
Ergo personalmente quando uso una stringa da inserire in una query uso 
una funzione del tipo:
Function String2Sql( _
  ByVal s As String, _
  Optional Byval PerLike As Boolean = False _
  ) As String
    s=Replace$(s, "'", "''", 1&, -1&, vbBinaryCompare)
    If PerLike Then
       s=Replace$(s, "[", "[[]", 1&, -1&, vbBinaryCompare)
       s=Replace$(s, "_", "[_]", 1&, -1&, vbBinaryCompare)
       s=Replace$(s, "%", "[%]", 1&, -1&, vbBinaryCompare)
    End If
    String2Sql=s
End Function
Se si vuole usare una stringa per una query con Like basta quindi:
"SELECT * FROM t WHERE x LIKE '%" & String2Sql(y, True) & "%';"
Negli altri casi:
"UPDATE t SET x='" & String2Sql(y) & "';"
Ciao
    Michele


Non vorrei dire una stupidata, quindi prendi con le mollo ciň che scrivo,
le parentesi quadre si utilizzano per la ricerca dei caratteri jolly che a 
loro volta dipendono dal db utilizzato, * in access, % in sqlserver ad 
esempio.
ciao
Stefano 

     rs.Open sql, cn, Options:=adCmdText
Sicuro che funzioni? Ho i miei dubbi...
definire la variabile sql così come fai tu è idendito a scrivere
   sql = "SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE " & "'" &
    "%01ABC123456'00054%" & "'" & ";"
ovvero
   sql = "SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE " &_
    "'%01ABC123456'00054%';"
ovvero
   Il problema rimane.
Ho postato un messaggio 1 minuto fa su come risolvere il problema...
Ciao
    Michele

"'+''''+'"
così la condizione è come se fosse una somma di più sottostringhe, compresi 
gli apici intermedi. 

 Ho postato un messaggio 1 minuto fa su come risolvere il problema...
Si ma mi sembra un po' complicata, soprattutto perché gestisce l'esistenza
di tutti i caratteri speciali nel campo, mentre non sempre li troviamo tutti
in un campo di database. Per esempio in un campo Cognome non si trova mai
l'underscore, o gli apici doppi, o le parentesi quadre, o il segno
percentuale. La tua funzione sarà utilissima nel caso dei campi Memo (nei
quali però di solito non si fanno ricerche) o Password, o altre situazioni
particolari. Ma in generale con due piccole aggiunte sulla stessa riga di
codice io risolvo il problema annoso - e il caso più frequente - dell'apice
nel campo.
Spero sia utile. Ciao.


 Spero sia utile. Ciao.
Ho provato a scrivere un programmino:
    Dim cn As ADODB.Connection, rs As ADODB.Connection, sql As String
    Set cn = New ADODB.Connection
    cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\db1.mdb"
    sql = "SELECT * FROM Fatture_Dettagli WHERE NumeriSerie LIKE " &_
       Chr(39) & "%01ABC123456'00054%" & Chr(39) & ";"
    Set rs = cn.Execute(sql, , adCmdText)
    rs.Close
    Set rs = Nothing
Risultato:
    Errore di run-time '-
2147217900
 (80040e14)':
    Errore di sintassi (operatore mancante) nell'espressione della query
    'NumeriSerie LIKE '%01ABC123456'00054%';'.
Ergo non capisco come tu possa usarla da tanti anni...
Ciao
    Michele

 'NumeriSerie LIKE '%01ABC123456'00054%';'.
No, aspetta, la stringa di cui sopra io l'ho copiancollata dal post dell'OP.
Io non so se con il tuo provider, o con il suo, il carattere di percentuale
o l'apice singolo assumono un altro significato, non posso rispondere di
errori di sintassi su codice non mio.
Io dico che uso da anni la funzione Chr(39) al posto dell'apice singolo, e
con successo. Però io uso SQL Server e se uso Access ho usato qs. trucco
dentro l'Access VBA. Non conosco altri utilizzi, e l'OP parlava di apici
singoli, cioé una caratteristica di SQL Server. Inoltre se ben ricordo, gli
apici singoli non sono nemmeno necessari se si modifica il contenuto di un
Recordset.Fields(n).Value aperto di ADO, perché ADO stesso provvede ad
adattare la sintassi del valore da passare.
Alcuni miei pezzi di codice - funzionanti - per SQL Server sono i seguenti:
    sql = "SELECT * FROM NUM_NUMERAZIONI"
    sql = sql & " WHERE NUM_DITTA_DIT = " & glo.DittaCorrenteCodice
    sql = sql & " AND NUM_SERIE = " & Chr(39) & txtSerie.Text & Chr(39)
    sql = sql & " AND NUM_ANNO = " & Chr(39) & txtAnno.Text & Chr(39) & ";"
    rs.Open sql, glo.conn, adOpenReadOnly, adLockReadOnly, adCmdText
                sql = "UPDATE NUM_NUMERAZIONI SET "
                sql = sql & Choose(Int((selectedfield - 4) / 2 + 1), "NUM_ULTIMABOLLA",
"NUM_ULTIMAFATT", "NUM_ULTIMARICEVUTA", "NUM_ULTIMAPACKING")
                sql = sql & " = " & txtNumDoc.Text & ", "
                sql = sql & Choose(Int((selectedfield - 4) / 2 + 1), "NUM_DATAULTIMABOLLA",
"NUM_DATAULTIMAFATT", "NUM_DATAULTIMARICEVUTA", "NUM_DATAULTIMAPACKING")
                sql = sql & " = " & Funx.NNT(txtDataDoc.Text, nntDirectCONVERT)
                sql = sql & " WHERE NUM_DITTA_DIT = " & glo.DittaCorrenteCodice
                sql = sql & " AND NUM_SERIE = " & Chr(39) & txtSerie.Text & Chr(39)
                sql = sql & " AND NUM_ANNO = " & Chr(39) & txtAnno.Text & Chr(39) & ";"
                glo.conn.Execute sql, , adCmdText
        sql = "SELECT COUNT(*) FROM CLI_CLIENTI " & "WHERE CLI_PIVA = " & Chr(39) &
txtPartitaIVA.Text & Chr(39) & ";"
        tmpRs.Open sql, glo.conn, adOpenForwardOnly, adLockReadOnly, adCmdText
        sql = "SELECT COUNT(*) FROM CLI_CLIENTI " & "WHERE CLI_CODFISCALE = " &
Chr(39) & UCase$(txtCodiceFiscale.Text) & Chr(39) & ";"
        tmpRs.Open sql, glo.conn, adOpenForwardOnly, adLockReadOnly, adCmdText
    sql = sql & ", DC2_DESCRAGG_ART = " & IIf(Not txtDescrAggArticolo.Text =
vbNullString, _
        Chr(39) & txtDescrAggArticolo.Text & Chr(39), "NULL")
Questi sono soltanto esempi di istruzioni funzionanti che io uso. E
naturalmente, anch'io ho le mie funzioni personalizzate che aggiungono
Chr(39) e gestiscono le stringhe nulle (che sono il vero problema del lavoro
con i database), ma qui ho solo voluto spiegare il concetto.
Comunque sono anche anni che suggerisco questa soluzione, e ci sono diverse
correnti di pensiero.



Hai usato access, la stringa riportata è per sqlserver.
Per access devi sostituire % con * ed eliminare il ; finale.
Infatti in SQLServer puoi concatenare più query separate da ; cosa che in 
access (a quanto ne so) non si può fare, quanto meno utilizzando il provider 
ado.
ciao
Stefano 

     rs.Open sql, glo.conn, adOpenReadOnly, adLockReadOnly, adCmdText
Hai provato a inserire nella tua form un valore con un apice (uno solo) 
nel campo txtSerie?
Tutto questo non per pignoleria: questo ng è usato da tantissime persone 
per imparare, e secondo me (oltre che secondo i due test che ho fatto 
per riportarli qui), questa storia del Chr(39) proprio non va...
Ciao
    Michele

 Per access devi sostituire % con * ed eliminare il ; finale.
Dipende: usando Access tramite ADO/OLEDB si deve usare % (e _) invece di 
* (e ?).
Oltre alla mia personale esperienza trovi parecchi link su internet al 
riguardo.
Ciao
    Michele

 REPLACE(tuastringa, "'", "''") + "%"
Ottimo suggerimento :-)
Ho fatto proprio così... tutto risolto :-)))
Grazie a tutti!!! :-)


 singoli, cioé una caratteristica di SQL Server. Inoltre se ben ricordo, gli
Non uso SQL Server... ma accedo semplicemente ad un file di access ^_^;;;


 Per access devi sostituire % con * ed eliminare il ; finale.
Hemm ... preciso che in SQL sono alle primisssssssime armi
e che stavo accedendo ad un file di access.
Finchè usavo come carattere Jolly l'asterisco, facendo alcune ricerche,
a volte, non trovavo la stringa.
Da quando ho sostituito * con % più nessun problema :-)
Se serve, sto facendo alcune "personalizzazioni" al progetto
Fattura Fast (VB6)
www.fatturafast.org
