Rømmer "i Access SQL

stemmer
19

Jeg prøver å gjøre en domeneoppslag i VBA med noe sånt som dette:

DLookup(island, villages, village = ' & txtVillage & ')

Dette fungerer fint til txtVillage er noe som Dillons Bay, når apostrof blir tatt for å være et enkelt sitat, og jeg får en kjøretidsfeil.

Jeg har skrevet en triviell funksjon som unnslipper med apostrof - det erstatter ' med ' '''. Dette synes å være noe som kommer opp ganske ofte, men jeg kan ikke finne noen referanse til en innebygd funksjon som gjør det samme. Har jeg gått glipp av noe?

Publisert på 14/10/2008 klokken 01:08
kilden bruker
På andre språk...                            


10 svar

stemmer
3

Det er verre enn du tror. Tenk på hva som ville skje hvis noen kom inn en verdi som dette, og du har ikke rømt noe:

'); DROP TABLE [YourTable]

Ikke pent.

Grunnen til det er ingen innebygd funksjon for å bare slippe en apostrof er fordi den riktige måten å håndtere dette på er å bruke søkeparametere. For en Ole / Access stil spørring vil du sette dette som søkestrengen:

DLookup("island", "village", "village = ? ")

Og så sette parameter separat. Jeg vet ikke hvordan du går om å sette parameterverdien fra VBA, skjønt.

Svarte 14/10/2008 kl. 01:14
kilden bruker

stemmer
0

Forresten, her er min EscapeQuotes funksjon

Public Function EscapeQuotes(s As String) As String

    If s = "" Then
        EscapeQuotes = ""
    ElseIf Left(s, 1) = "'" Then
        EscapeQuotes = "''" & EscapeQuotes(Mid(s, 2))
    Else
        EscapeQuotes = Left(s, 1) & EscapeQuotes(Mid(s, 2))
    End If

End Function
Svarte 14/10/2008 kl. 01:16
kilden bruker

stemmer
16

"Erstatt" -funksjonen bør gjøre triks. Basert på koden ovenfor:

DLookup("island", "villages", "village = '" & Replace(txtVillage, "'", "''") & "'")
Svarte 14/10/2008 kl. 01:21
kilden bruker

stemmer
1

Jeg tror tilgang kan bruke Chr $ (34) og gjerne ha med apostrof / apostrofer inne.
f.eks

DLookup("island", "villages", "village = " & chr$(34) & nonEscapedString & chr$(34))

Selv da bør du må unnslippe chr $ (34) ( ")

Du kan bruke Bytt funksjonen.

Dim escapedString as String

escapedString = Replace(nonescapedString, "'", "''")
Svarte 14/10/2008 kl. 01:22
kilden bruker

stemmer
3

Selv om stenografi domene funksjoner som DLookup er fristende, de har sine ulemper. Tilsvarende Jet SQL er noe som

SELECT FIRST(island)
FROM villages
WHERE village = ?;

Hvis du har mer enn én samsvar kandidat vil den velge den 'første' en, definisjonen av 'første' er implementering (SQL motor) avhengig og udefinert for Jet / ACE motor IIRC. Vet du hvilken ville være først? Hvis du ikke så styre klar av DLookup :)

[For interesse, vil svaret for Jet / ACE enten være minimumsverdien basert på clusterd indeksen på tidspunktet databasefilen sist ble komprimert eller første (gyldig tid) satt verdi hvis databasen aldri har blitt komprimert. Klynger indeksen er i sin tur bestemt av PRIAMRY KEY hvis pst ellers UNIQUE-begrensning eller indeks er definert på ikke null søyler, ellers den første (gyldige tids) som er innsatt rad. Hva hvis det er mer enn en unik begrensning eller indeks definert på NOT NULL kolonner, hvilken ville bli brukt for clustering? Jeg har ingen anelse! Jeg stoler på at du får ideen om at 'første' er ikke lett å avgjøre, selv når du vet hvordan!]

Jeg har også sett råd fra Microsoft for å unngå å bruke domene samlede funksjoner fra en optimalisering synspunkt:

Informasjon om spørring ytelse i en Access-database http://support.microsoft.com/kb/209126

"Unngå å bruke domene samlede funksjoner, som for eksempel DLookup funksjon ... Jet-databasemotoren kan ikke optimalisere søk som benytter domene samlefunksjoner"

Hvis du velger å omskrive bruke en spørring kan du dra nytte av parametrene syntaks, eller du foretrekker Jet 4.0 / ACE PROSEDYRE syntaks f.eks noe sånt

CREATE PROCEDURE GetUniqueIslandName
(
   :village_name VARCHAR(60)
)
AS 
SELECT V1.island_name
  FROM Villages AS V1
 WHERE V1.village_name = :village_name
       AND EXISTS 
       (
        SELECT V2.village_name
          FROM Villages AS V2
         WHERE V2.village_name = V1.village_name
         GROUP 
            BY V2.village_name
        HAVING COUNT(*) = 1
       );

På denne måten kan du bruke motorens egen funksjonalitet - eller i det minste at av sine dataleverandører - for å unnslippe alle tegn (ikke bare å dobbelt og apostrof) etter behov.

Svarte 14/10/2008 kl. 06:04
kilden bruker

stemmer
1

Parametriseres spørsmål som Joel Coehoorn foreslåtte er veien å gå, i stedet for å gjøre sammensetning i søkestrengen. Først - unngår visse sikkerhetsrisikoer, andre - jeg er rimelig sikker på at det tar å rømme inn i motorens egne hender, og du trenger ikke å bekymre deg for det.

Svarte 04/01/2009 kl. 07:12
kilden bruker

stemmer
0

For hvem har problemer med singel sitat og erstatt-funksjonen, kan denne linjen redde dagen ^ o ^

Replace(result, "'", "''", , , vbBinaryCompare)
Svarte 25/02/2010 kl. 00:28
kilden bruker

stemmer
0

sette parentes rundt de kriterier som kan ha en apostrof i det.

Noe som:

DLookup("island", "villages", "village = '[" & txtVillage & "]'")

De trenger å være utenfor med apostrof eller rett rundt txtVillage som:

DLookup("island", "villages", "village = '" & [txtVillage] & "'")

Men hvis du finner den rette kombinasjonen, vil det ta seg av apostrof.

Keith B

Svarte 04/04/2013 kl. 19:15
kilden bruker

stemmer
-2

Min løsning er mye enklere. Opprinnelig jeg brukte denne SQL uttrykk for å skape et ADO post:

Dim sSQL as String
sSQL="SELECT * FROM tblTranslation WHERE fldEnglish='" & myString & "';"

Når myStringhadde en apostrof i det, som Int'l Electrics, ville mitt program stanse. Bruke anførselstegn løst problemet.

sSQL="SELECT * FROM tblTranslation WHERE fldEnglish="" & myString & "";"
Svarte 14/06/2013 kl. 16:26
kilden bruker

stemmer
1

Men da bør det være som dette (med en mer doublequote hver):

sSQL = "SELECT * FROM tblTranslation WHERE fldEnglish=""" & myString & """;"

Eller hva jeg foretrekker:

Lag en funksjon for å unnslippe enkle anførselstegn, fordi "rømmer" med "[]" vil ikke tillate disse tegnene i strengen ...

Public Function fncSQLStr(varStr As Variant) As String

If IsNull(varStr) Then
        fncSQLStr = ""
    Else
        fncSQLStr = Replace(Trim(varStr), "'", "''")
    End If

End Function

Jeg bruker denne funksjonen for alle mine SQL-spørringer, som SELECT, INSERT og UPDATE (og i WHERE-leddet i tillegg ...)

strSQL = "INSERT INTO tbl" & 
    " (fld1, fld2)" & _
    " VALUES ('" & fncSQLStr(str1) & "', '" & fncSQLStr(Me.tfFld2.Value) & "');"

eller

strSQL = "UPDATE tbl" & _
    " SET fld1='" & fncSQLStr(str1) & "', fld2='" & fncSQLStr(Me.tfFld2.Value) & "'" & _
    " WHERE fld3='" & fncSQLStr(str3) & "';"
Svarte 18/06/2013 kl. 11:58
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more