Как использовать параметрический ORDER BY с pg_prepare () pg_execute ()?

0

Я хочу заказать этот запрос с помощью чего-то определенного пользователем, поэтому я сделал его параметризованным. Я действительно не могу понять, почему второй параметр игнорируется! (Он не упорядочивает результаты)

function getY($id, $order){
    ....
    ....
    $db = connection_pgsql() or die ('connection failed');
    $sql = "SELECT id, y FROM test WHERE id = $1 ORDER BY $2";
    $resource = pg_prepare($db, "get_y", $sql);

    $value = array($id, $order);
    $resource = pg_execute($db, "get_y", $value);
    ....
    ....
}

Если я пройду так:

$sql = "SELECT id, y FROM test WHERE id = $1 ORDER BY {$order}";

он работает, но я думаю, что это не безопасно (не так ли?).

Я нашел эту ошибку pgsql 42601 с PDO :: execute, которая действительно не решает мою проблему.

  • 0
    см. stackoverflow.com/questions/149380/…
  • 0
    Моя не хранимая процедура. Это должно работать так же?
Теги:
prepared-statement

1 ответ

1
Лучший ответ

ORDER BY $ 2 сортирует значение fix, что-то вроде этого:

SELECT * FROM t1 ORDER BY 'some string';

Поскольку все записи будут отсортированы по одной и той же строке, сортировки не будет...

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

Чтобы исправить это, вам понадобится динамический SQL и некоторые другие меры безопасности:

function getY($id, $order){
    ....
    ....
    $db = connection_pgsql() or die ('connection failed');

    $sql = "SELECT quote_ident($1);"; // give me a secure object name

    $resource = pg_query_params($db, $sql, array($order)); // error handling is missing

    $order = pg_fetch_result($resource, 0, 0);

    $sql = "SELECT id, y FROM test WHERE id = $1 
        ORDER BY ".$order.";"; // <===== it now safe to use

    $resource = pg_prepare($db, "get_y", $sql); // error handling is missing

    $value = array($id);
    $resource = pg_execute($db, "get_y", $value); // error handling is missing
    ....
    ....
}

Теперь вы создаете полную строку SQL, которая может быть подготовлена и сохраняется из-за quote_ident(). Какой бы контент ни находился в $ order, он будет рассматриваться как идентификатор в PostgreSQL. Как колонка в этом случае. Если этот столбец отсутствует, подготовка завершится неудачей. Вот почему вам нужна правильная обработка ошибок, вы знаете, что однажды этот запрос завершится неудачно из-за плохого ввода.

Если вы используете этот оператор только один раз, вы также можете использовать pg_query_params() вместо pg_prepare() + pg_execute().

Ещё вопросы

Сообщество Overcoder
Наверх
Меню