Как установить параметры 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");
Существует ли константа PDO::PARAM_COLUMN_NAME
или какой-либо эквивалент?
Спасибо!
Ответы
Ответ 1
Да, вы застряли, вставив его прямо в 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
не может убежать, так как никакого побега не требуется. Это делает обязательным.
Ответ 2
Я не думаю, что вы можете:
- Использовать заполнители в предложении
order by
- Связывать имена столбцов: вы можете связывать только значения - или переменные и вводить их значение в подготовленный оператор.
Ответ 3
Возможно использование готовых операторов в ORDER BY
, к сожалению, вам нужно передать порядок столбца с именем и требуется установить 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();
Ответ 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
К сожалению, я думаю, вы не могли сделать это с подготовленными заявлениями.
Это сделало бы его недоступным, поскольку разные столбцы могут иметь значения, которые могут быть отсортированы с помощью специальных стратегий сортировки.
Создайте запрос с помощью стандартных экранов и выполните его непосредственно.
Ответ 6
возможно. Вы можете использовать число вместо имени поля в предложении 'order by'. Это число, начинающееся с 1 и имеющее порядок имен полей в запросе. И вы можете конкатенировать строку для ASC или DESC. Например
"Выберите col1, col2, col3 из tab1 order на?" + StrDesc + "limit 10,5".
strDesc = "ASC" / "DESC".
Ответ 7
Если я не ошибаюсь, Паскаль прав.
Единственное связывание, возможное в 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
, но поскольку вы устанавливаете их вручную и не устанавливаете их через пользовательский ввод, я думаю, что вы все настроены.
Ответ 8
Создайте условие if-else.
Если (ascCondion), то привяжите значения, но жесткий код ORDER BY columnName ASC
Else
Свяжите значения, но жесткий код ORDER BY COlumnName DESC