Как я устанавливаю параметрические усилители ORDER BY с помощью подготовленного оператора PDO?

У меня есть проблемы с помощью параметрических усилителей в ORDER BY раздел моего SQL. Это не выдает предупреждений, но ничего не распечатывает.

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

Есть ли a PDO::PARAM_COLUMN_NAME постоянный или некоторый эквивалент?

Спасибо!

33
задан Marlorn 30 March 2010 в 20:54
поделиться

4 ответа

Я не думаю, что вы можете получить 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 - это только два возможных значения, вы можете легко проверить и выбрать между ними как жестко заданные значения с помощью кода php.

Вы также можете использовать для этого функции ELT (FIELD (,,,,,) ,,,,,), но тогда порядок всегда будет выполняться в виде строки, даже если столбец имеет числовой тип данных. которые должны быть отсортированы с использованием числовой семантики / сопоставления.

5
ответ дан 27 November 2019 в 17:57
поделиться

Я не думаю, что вы можете:

  • Использовать заполнители в порядке по предложению
  • Привязать имена столбцов: вы может связывать только значения или переменные, и их значение вводится в подготовленный оператор.
12
ответ дан 27 November 2019 в 17:57
поделиться

Да, вы застряли, вставляя его прямо в 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";

То же самое для направления.

Я написал вспомогательную функцию белого списка для использования в таких случаях, она значительно сокращает объем кода, который необходимо написать:

$order = white_list($order, ["name","price","qty"], "Invalid field name");
$direction = white_list($direction, ["ASC","DESC"], "Invalid ORDER BY direction");

$sql = "SELECT field from table WHERE column = ? ORDER BY $order $direction";
$stmt = $db->prepare($sql);
$stmt->execute([$is_live]);

Идея здесь состоит в том, чтобы проверить значение и вызвать ошибку в случае, если это неверно.

51
ответ дан 27 November 2019 в 17:57
поделиться

Если я не совсем ошибаюсь, Паскаль прав.
Единственное возможное связывание в PDO - это связывание значений, как вы это делали с параметром ': my_param'.
Однако ничего страшного в этом нет:

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

Единственное, на что следует обратить внимание, - это правильное экранирование $ order и $ direction , но поскольку вы устанавливаете их вручную и не устанавливаете их через пользовательский ввод, я думаю, что все готово.

-2
ответ дан 27 November 2019 в 17:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: