38301


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

[code]

        // 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" となる
    
[/code]

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

[code]

    // 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);
    
[/code]

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


CC BY-SA 3.0
2017-09-29T08:59:10.593
38291
2017-09-29T12:22:59.320
24506
question
php sql wordpress
WordpressでSQL文のORDER BYに変数を使用したいが、計算されない


そもそも`$key`は何を想定されているのでしょうか？ 質問文で言及されていませんがカラム名でしょうか？
[`prepare()`](https://developer.wordpress.org/reference/classes/wpdb/prepare/)
が受け入れるプレースホルダーは

> %d (integer) %f (float) %s (string)

の３種類だけであり、カラム名は受け入れられません。その前提でクエリを見直す必要があります。


CC BY-SA 3.0
2017-09-29T11:15:03.440
38298
2017-09-29T11:15:03.440
4236
38291
answer


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

[code]

    SELECT * FROM hoge WHERE name = 'nantoka'
    
[/code]

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

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

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

などの対応が必要です。


CC BY-SA 3.0
2017-09-29T12:22:59.320
38301
2017-09-29T12:22:59.320
5793
38291
answer