1

私の Django アプリでは、次のような MySQL クエリを生成する必要があります。

SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.last_name LIKE 'smi%'))
UNION
SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.first_name LIKE 'smi%'));

Django ORM によって生成されたクエリは UNION を使用せず、上記の UNION クエリよりも少なくとも 40 倍遅く実行されるため、Q オブジェクトを使用して __istartswith フィルターを一緒に OR することはできません。私のアプリケーションでは、このパフォーマンスは受け入れられません。

だから私はこのようなものを試しています:

Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %%s AND (last_name LIKE '%%s%')) UNION SELECT * FROM sports_player WHERE (sport_id = %%s AND (first_name LIKE '%%s%'))", (sport.id, qword, sport.id, qword))

長いワンライナーで申し訳ありませんが、この種の問題をデバッグしようとしているときに、トリプルクォートで囲まれた文字列を使用しないようにしたかったのです。

このクエリセット オブジェクトを実行または再現すると、次のような例外が発生します。

*** ValueError: unsupported format character ''' (0x27) at index 133

これは、三重引用符ではなく、一重引用符の中の一重引用符です。LIKE 句を囲む単一引用符を取り除くと、LIKE 句に続く close-paren ) 文字について同様の例外が発生します。

Django と MySQL は、このクエリの正しい構文について意見が分かれているようですが、両方で機能する構文はありますか?

最後に、文字列補間の %%s 構文が正しいかどうかもわかりません。Django のドキュメントでは、raw() の引数で通常の %s 構文を使用できるはずであることが示唆されていますが、いくつかのオンライン リソースでは、%%s または ? 生の SQL での文字列補間のプレースホルダーとして。

この問題について少しだけ明確にしていただき、心から感謝しています。

4

1 に答える 1

3

私はそれを次のように動作させました:

qword = word + '%'
Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %s AND (last_name LIKE %s)) UNION SELECT * FROM myapp_player WHERE (sport_id = %s AND (first_name LIKE %s))", (sport.id, qword, sport.id, qword))

%s が生のクエリをパラメータ化する正しい方法であると思われるという事実に加えて、ここで重要なのは、raw() を呼び出す前に % ワイルドカードを LIKE 句に追加し、LIKE 句の周りから一重引用符を除外することでした。LIKE 句には引用符がありませんが、最終的に MySQL サーバーに送信されるクエリには引用符が含まれています。

于 2013-06-05T19:59:17.180 に答える