web-dev-qa-db-fra.com

Comment définir les paramètres ORDER BY à l'aide d'une instruction PDO préparée?

J'ai des problèmes pour utiliser les paramètres dans la section ORDER BY de mon code SQL. Il n'émet aucun avertissement, mais n'imprime rien. 

$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();

Le :my_param fonctionne, mais pas le :order ni le :direction. N’at-il pas été échappé correctement en interne? Suis-je coincé en l'insérant directement dans le code SQL? Ainsi:

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

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

Existe-t-il une constante PDO::PARAM_COLUMN_NAME ou un équivalent?

Merci!

29
Marlorn

Voici la question montre que les déclarations préparées très appréciées n’est pas la solution miracle, hehe :)

Oui, vous êtes coincé en l'insérant directement dans le code SQL Avec quelques précautions, bien sûr. Chaque opérateur/identifiant doit être codé en dur dans votre script, comme ceci:

$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";

Même chose pour la direction.

Notez que bindParam n'échappe pas, car aucun échappement n'est nécessaire. il fait contraignant.

46
Your Common Sense

Je ne pense pas que vous puissiez:

  • Utiliser des espaces réservés dans une clause order by
  • Lier les noms de colonnes: vous pouvez uniquement lier des valeurs - ou des variables, et voir leur valeur injectée dans l'instruction préparée.
12
Pascal MARTIN

C'est possible utilisez des instructions préparées dans la clause ORDER BY. Malheureusement, vous devez passer l'ordre de la colonne insted du nom. Il est nécessaire de définir PDO_PARAM_INT avec le type.

Dans MySQL, vous pouvez obtenir l'ordre des colonnes avec cette requête:

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

Code 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();
9
rray

Je ne pense pas que vous puissiez obtenir ASC/DESC dans le cadre de l'instruction préparée, mais la colonne que vous pouvez.

 order 
    by 
       case :order
           when 'colFoo' then colFoo
           when 'colBar' then colBar
           else colDefault
       end
       $direction

Comme ASC/DESC n’est que deux valeurs possibles, vous pouvez facilement les valider et les sélectionner en tant que valeurs codées en dur.

Vous pouvez également utiliser les fonctions ELT (FIELD (,) ,) pour cela, mais l'ordre sera toujours effectué sous forme de chaîne, même s'il s'agit d'une colonne numérique.

4
goat

C'est possible. Vous pouvez utiliser le numéro au lieu du nom du champ dans la clause 'order by'. C'est un nombre commençant par 1 et dans l'ordre des noms de champs dans la requête. Et vous pouvez concaténer une chaîne pour ASC ou DESC. Par exemple "Sélectionnez col1, col2, col3 dans l'ordre du tab1 par" + strDesc + "limite 10,5" . StrDesc = "ASC"/"DESC". 

0
bithom

Malheureusement, je suppose que vous ne pourriez pas utiliser des instructions préparées… Cela ne le rendrait pas en mémoire cache car différentes colonnes peuvent avoir des valeurs pouvant être triées avec des stratégies de tri spéciales.

Créez une requête en utilisant des échappements standard et exécutez-la directement.

0
cavila