web-dev-qa-db-ja.com

準備されたPDOステートメントを使用してORDER BYパラメーターを設定するにはどうすればよいですか?

SQLのORDER BYセクションでparamsを使用すると問題が発生します。警告は発行されませんが、何も出力されません。

$order = 'columnName';
$direction = 'ASC';

$stmt = $db->prepare("SELECT field from table WHERE column = :my_param ORDER BY :order :direction");
$stmt->bindParam(':my_param', $is_live, PDO::PARAM_STR);
$stmt->bindParam(':order', $order, PDO::PARAM_STR);
$stmt->bindParam(':direction', $direction, PDO::PARAM_STR);
$stmt->execute();

:my_paramは機能しますが、:orderまたは:directionは機能しません。内部で正しくエスケープされていませんか? SQLに直接挿入するのにこだわっていますか?そのようです:

$order = 'columnName';
$direction = 'ASC';

$stmt = $db->prepare("SELECT * from table WHERE column = :my_param ORDER BY $order $direction");

PDO::PARAM_COLUMN_NAME定数またはそれに相当するものはありますか?

ありがとう!

32
Marlorn

はい、SQLに直接挿入することができません。もちろん、いくつかの注意事項があります。 すべての演算子/識別子はハードコードする必要があります次のように、スクリプトで:

$orders=array("name","price","qty");
$key=array_search($_GET['sort'],$orders);
$order=$orders[$key];
$query="SELECT * from table WHERE is_live = :is_live ORDER BY $order";

方向についても同じです。

エスケープする必要がないため、bindParamはエスケープしないことに注意してください。バインディングを行います。

49

私はあなたができるとは思わない:

  • order by句でプレースホルダーを使用する
  • 列名のバインド:値(または変数)のみをバインドでき、準備されたステートメントに値を挿入できます。
12
Pascal MARTIN

可能ですORDER BY句で準備されたステートメントを使用します。残念ながら、名前のinsted列の順序を渡す必要があり、タイプでPDO_PARAM_INTを設定する必要があります。

MySQLでは、次のクエリを使用して列の順序を取得できます。

SELECT column_name, ordinal_position FROM information_schema.columns 
WHERE table_name = 'table' and table_schema = 'database'

PHPコード:

$order = 2;

$stmt = $db->prepare("SELECT field from table WHERE column = :param ORDER BY :order DESC");
$stmt->bindParam(':param', $is_live, PDO::PARAM_STR);
$stmt->bindParam(':order', $order, PDO::PARAM_INT);
$stmt->execute();
10
rray

準備済みステートメントの一部としてASC/DESCを取得できるとは思いませんが、次のようにsqlクエリでそれらをすべてリストした場合にできる列:

// Validate between 2 possible values:
$sortDir = isset($_GET['sortDir']) && $_GET['sortDir'] === 'ASC' ? 'ASC' : 'DESC';
$sql = "
...
     order 
        by 
           case :orderByCol
               when 'email' then email
               when 'age' then age
               else surname
           end
           $sortDir
";
$stmt = $db->prepare($sql);
$stmt->bindParam(':orderByCol', $someColumn);
$stmt->execute();

ASC/DESCは2つの可能な値にすぎないため、PHPコードを使用してハードコードされた値として簡単に検証および選択できます。

このためにELT(FIELD(,)),)関数を使用することもできますが、列が数値データ型であっても、順序付けは常に文字列として行われます数値のセマンティクス/照合を使用してソートされます。

5
goat

可能です。 「order by」句でフィールド名の代わりに番号を使用できます。これは1から始まる番号で、クエリ内のフィールド名の順序です。また、ASCまたはDESCの文字列を連結できます。たとえば、「tab1からcol1、col2、col3を?で選択」+ strDesc +「limit 10,5」。 strDesc = "ASC"/"DESC"。

0
bithom

残念ながら、準備済みのステートメントでは作成できなかったと思います。異なる列には、特別なソート戦略でソートできる値が含まれている可能性があるため、キャッシュ不可になります。

標準エスケープを使用してクエリを作成し、直接実行します。

0
cavila