如何将参数化 ORDER BY 与 pg_prepare() pg_execute() 一起使用?
How to use parametric ORDER BY with pg_prepare() pg_execute()?
我想按照用户决定的方式对这个查询进行排序,所以我已将其参数化。我真的不明白为什么第二个参数被忽略了! (它不排序结果)
function getY($id, $order){
....
....
$db = connection_pgsql() or die ('connection failed');
$sql = "SELECT id, y FROM test WHERE id = ORDER BY ";
$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 = ORDER BY {$order}";
它有效,但我认为它不安全(不是吗?)。
我只找到了这个pgsql 42601 error with PDO::execute,它确实不能解决我的问题。
ORDER BY $2 正在对固定值进行排序,如下所示:
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();"; // 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 =
ORDER BY ".$order.";"; // <===== it's 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()。
我想按照用户决定的方式对这个查询进行排序,所以我已将其参数化。我真的不明白为什么第二个参数被忽略了! (它不排序结果)
function getY($id, $order){
....
....
$db = connection_pgsql() or die ('connection failed');
$sql = "SELECT id, y FROM test WHERE id = ORDER BY ";
$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 = ORDER BY {$order}";
它有效,但我认为它不安全(不是吗?)。
我只找到了这个pgsql 42601 error with PDO::execute,它确实不能解决我的问题。
ORDER BY $2 正在对固定值进行排序,如下所示:
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();"; // 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 =
ORDER BY ".$order.";"; // <===== it's 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()。