WordPressでSQL文のORDER BYに変数を使用したいが、計算されない

投稿者: Anonymous

SQL文のORDER BYでabs()を用いた近似値の探索をしようとしています。
SQLインジェクション対策として、abs()をプレースホルダーとして渡すようにコーディングしましたが、%sの文字列がシングルクォーテーションで括られるためうまく動きませんでした。

    // 1
        // $keyは可変
        $abs = "abs(" . $key . " - 80)";
        $query = "SELECT * FROM $wpdb->hardness_table ORDER BY %s LIMIT 1";
        $sql = $wpdb->prepare($query,$abs);
        $rows = $wpdb->get_results($sql);
// SQL文が"SELECT * FROM $wpdb->hardness_table ORDER BY 'abs(abc - 80)' LIMIT 1" となる

やむを得ず下記のように直接文章内に変数を配置したら動きますが、warning文が出る状態です。

// 2
    $abs = "abs(" . $key . "- 80)";
    $query = "SELECT * FROM $wpdb->hardness_table ORDER BY $abs LIMIT 1";
    $sql = $wpdb->prepare($query);
    $rows = $wpdb->get_results($sql);

上記のようにプレースホルダーを用いた状態でabs()の計算をさせることは可能でしょうか。または2のコードのように直接書いても問題はないのでしょうか。
ご教示いただければと思います。

解決

プレースホルダは文字列や数値などのリテラルの代わりとして使います。したがって扱えるのは「値」のみです。関数やカラム名などの「識別子」は扱う事ができません。

SELECT * FROM hoge WHERE name = 'nantoka'

こういうSQLがあった時に、'nantoka'をプレースホルダで置き換えることはできますが、hogenameを置き換えることはできません。

識別子をSQLに組み込む時は文字列組み立ててやるしかありません。ただし、その場合でも任意の文字列を指定できるようなI/Fは避けるべきです。

  • ホワイトリストを持っておきそれと照合する
  • 外部から入力されるキーと、実際のカラム名などをテーブルを用いて変換する

などの対応が必要です。

回答者: Anonymous

Leave a Reply

Your email address will not be published.