9

データベースからLämmönmyyntipalvelutという単語を見つける必要があります。唯一、データベースでは、値がPHP配列であるフィールドにあり、json_encode()を使用してJSONに変換されるため、特殊文字は16進Unicodeにスクラブされます。

だから私のクエリは

SELECT * FROM table WHERE (services LIKE '%Lämmönmyyntipalvelut%')

結果がありません。当然のことです。次に、特殊文字を変換してクエリを実行します。

SELECT * FROM table WHERE (services LIKE '%L\u00e4mm\u00f6nmyyntipalvelut%')

結果はなく、なぜだろうか。次に、特殊文字のみのクエリをテストしました。

SELECT * FROM table WHERE (services LIKE '%\u00e4%')

見つけることになっていたものを見つけました。次に、どこで問題が発生したかを確認するために、ものを追加し始めました(最初にL)。

SELECT * FROM table WHERE (services LIKE '%L\u00e4%')

結果がありません。別のテスト:

SELECT * FROM table WHERE (services LIKE '%\u00e4mm%')

見つけることになっていたものを見つけました。

だから私の結論は、バックスラッシュがどういうわけか物事を台無しにしているということですが、私はどのように理解していませんか?

編集:

サービスフィールドの正確な内容:

["Neuvonta","L\u00e4mm\u00f6nmyyntipalvelut",
"Mets\u00e4-\/energiapuunkorjuupalvelut"]

正確なクエリ:

SELECT id, uid, company_name, services, logo FROM rekisteroeidy_toimijaks 
WHERE 
    (services LIKE '%L\u00e4mm\u00f6nmyyntipalvelut%' AND 
    services LIKE '%Mets\u00e4-\/energiapuunkorjuupalvelut%') 
ORDER BY company_name ASC

読みやすくするために改行をいくつか追加しました。

4

3 に答える 3

13

理由はまったくわかりませんが、トリプルエスケープが役立ちます!

まあ、それは二重エスケープだけですが、そうです、それは機能します。その理由は次のとおりです。MySQLでは、LIKE演算子を使用するときにエスケープの2番目のレイヤーが含まれます。

services LIKE '%L\\\\u00e4mm\\\\u00f6n%'

そのMySQL文字列リテラルを解析すると、LIKE-queryとの比較が可能になります%L\\u00e4mm\\u00f6n%。MySQLは\LIKEクエリをエスケープとして扱うため、実際にはを含むリテラル文字列と一致しますL\u00e4mm\u00f6n

%これは、リテラルまたは文字を含むクエリ式に対して文字列を照合できるようにするためです_。たとえば、リテラル文字列の列を検索する場合は、それを(クエリでとして記述された)と100%照合して、100%で始まる文字列ではなく、実際に100%を取得していることを確認できます。100\%'100\\%'

MySQLがLIKEクエリのエスケープと文字列リテラルのエスケープの両方にバックスラッシュを使用しているのは残念です。特に、それらも使用する囲みプログラミング言語で記述している場合は、実際のトリプルエンコーディングになります"services LIKE '%L\\\\\\\\u00e4mm\\\\\\\\u00f6n%'"

この動作がANSISQLに準拠しておらず、他のデータベースでは機能しないことを考えると、二重に残念です。ANSI SQLによると、デフォルトではLIKEクエリにエスケープ文字はないため、リテラルと一致させる場合、%または_独自のエスケープ文字を指定してオプトインする必要がある場合は、次のようになります。

something LIKE '100=%' ESCAPE '='

データベース間の互換性のために、常にLIKE...ESCAPEフォームを使用し、恐ろしいバックスラッシュ以外のものを選択するのが最善です。(余談ですが、SQL文字列リテラルをエスケープするためのMySQLのバックスラッシュもANSIに準拠していません!ただし、NO_BACKSLASH_ESCAPES sql_mode設定を使用して、この誤動作をオフにすることができます。)

servicesおそらく、それらを単一の文字列列に押しつぶすのではなく、2番目のテーブルに分割する方が良いでしょう。スキーマを第一正規形にします。そうすれば、低速の全表スキャンの部分文字列一致を実行するのではなく、個々の値の単純なルックアップを取得できます。

于 2012-11-11T00:51:52.290 に答える
3

バックスラッシュはメタ文字です。MySQLはそれを次のように理解します:「次の文字を削除し、メタ文字として解析しないでください」。

したがって、バックスラッシュをエスケープする必要があります:

SELECT * FROM table WHERE (services LIKE '%L\\u00e4%')

これで、MySQLは「\\」を「\」に置き換えます(最初の円記号は、2番目の円記号をエスケープするために使用されるメタ文字です)

于 2012-11-08T10:31:08.260 に答える
1

理由はまったくわかりませんが、トリプルエスケープが役立ちます!

SELECT id, uid, company_name, services, logo
FROM rekisteroeidy_toimijaks
    WHERE (
    services LIKE  '%L\\\\u00e4mm\\\\u00f6n%'
)
ORDER BY company_name ASC 
LIMIT 0 , 30
于 2012-11-08T11:19:09.983 に答える