6

'データベースをテストしていたところ、データベースのテキスト エントリに文字 (一重引用符)が含まれていると問題が発生することに気付きました。現時点での私の解決策は、文字列に対する .execute 操作の前に .exe を呼び出すことescape(string, "'", " "'" ")です。

以下の要約例:

qr = "INSERT INTO tblExample VALUES ( " & "'" & me.testparam & "'" & ");"
qr = Replace(qr, "'", " "'" ")
db.execute qr
'also tried  qr = "INSERT INTO tblExample VALUES ( " & "'" & replace(me.testparam,"'"," ") & "'" & ");"

これは、 などの値からのエラーを防ぐための正しい回避策であると私が想定したものでしたTourette's

これには2つの問題があります。まず第一に、それは機能していません。2 つ目は、コード内に db.execute qr というステートメントを呼び出す場所がアプリ全体で 50 か所あります。ここで、qr は一重引用符を含む可能性のある文字列です。テーブル内のフィールドに一重引用符を含める必要があるため、単にスペースなどに置き換えることはできません。

2 つの部分からなる質問:

  1. Replaceクエリとして実行されるすべての文字列を呼び出すすべてのコードを実行するよりも良い解決策はありますか?

  2. 現在の実装が失敗するのはなぜですか? - 一重引用符をスペースにエスケープしても、クエリ式で構文エラーが発生します。

4

3 に答える 3

4

まず、これらの2行を調べます。

"VALUES ( " & "'" & me.testparam & "'" & ");"
"VALUES ( '" & me.testparam & "');"

どちらもまったく同じ文字列を生成します。私にとっての違いは、私の脳が2番目のバージョンをより速く理解することです。

さて、これがコメントがあなたに何をするように言っているかです...あなたのソース文字列の各一重引用符を2つの一重引用符に置き換えてください。完成した文字列をイミディエイトウィンドウで表示できるように追加しましDebug.Printた(Ctrl + gでそこに移動します)...その後、実際の文字列がどのように見えるかを想像するのではなく、実際の文字列を表示できます。

qr = "INSERT INTO tblExample VALUES ( '" & _
    Replace(Me.testparam, "'", "''" & "');"
Debug.Print qr
db.Execute qr, dbFailOnError 

オブジェクト変数でdbあると想定したので、オプションを含めました。問題が発生した場合に対処するために、コードにエラーハンドラーを含める必要があります。DAO.DatabasedbFailOnErrordbFailOnError

クエリでVBA関数に問題が発生した場合は、[イミディエイト]ウィンドウにドロップして、そこで関数式をテストします。これはコンパイルエラーを引き起こします、「期待される:リストセパレータまたは)」:

? Replace("Tourette's", "'", " "'" ")

しかし、これは機能します:

? Replace("Tourette's", "'", "''")
Tourette''s

一般的に便利であり、タイトルが「不要な文字、主に一重引用符をエスケープする」で始まるためです。Replace()したがって、一重引用符だけでなく他の文字を削除/置換する場合は、機能する式が見つかるまでイミディエイトウィンドウで実験してください。次に、その式をクエリで使用します。

たとえば、不要な文字に改行が含まれている場合...

MyString = "foo" & vbCrlf & "bar" : ? MyString
foo
bar
? Replace(MyString, Chr(13) & Chr(10), " ")
foo bar

注:dbエンジンは関数を使用できますが、名前付き定数()を認識しないため、検索ターゲットとしてChr(13) & Chr(10)ではなく使用しました。vbCrlfChr()vbCrlf

于 2012-07-10T16:16:18.337 に答える
3

挿入する場所を指定していないため、クエリは失敗します。

Dim qd As QueryDef
qr = "INSERT INTO tblExample (AText) VALUES ( [avalue] );"

Set qd = CurrentDB.CreateQueryDef("",qr)
qd.Parameters("avalue").Value = me.testparam
qd.Execute dbFailOnError
于 2012-07-10T16:15:25.867 に答える
1

もう 1 つの方法は、クォートを定数 (Const Quote = """") として定義し、それを使用して SQL ステートメントを構築することです。Const Quote = Chr(34) として引用符を定義することはできません。定数の定義は関数に基づくことができないため、連続して 4 つの二重引用符を使用する必要があります。3 番目の引用は保存するもので、2 番目の引用は 3 番目の引用を除外するもので、最初と最後の引用は割り当てている値が文字列であるためです。

次に、次のような SQL ステートメントを作成できます。

SQL = SELECT * FROM tblSyndromes
WHERE Syndrome = " & Quote & "Tourette's" & Quote & ";"

データに一重引用符があっても問題ありません。

データベースをSQLサーバーにアップスケールし、クエリをパススルークエリに変換するかのように、パラメーターを使用しません。パラメーターを使用できません。私はアップスケールすることはめったにありませんが、その前提ですべてのコードを書いています。また、クエリが期待どおりに機能しない場合、何が問題なのかを調べるにはどうすればよいでしょうか。SQL という変数がある場合、いつでも SQL ステートメントを出力し、新しいクエリで実行して、その動作を確認できます。

于 2016-05-30T04:20:11.607 に答える