2010-04-21 124 views
16

我想用事先准备好的声明中传入的参数对于ORDER BYLIMIT条款,比如:如何使用pdo的准备好的语句来排序和限制子句?

$sql = 'SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results'; 
$stmt = $dbh->prepare($sql); 
$stmt->execute(array(
    'sort' => $_GET['sort'], 
    'dir' => $_GET['dir'], 
    'start' => $_GET['start'], 
    'results' => $_GET['results'], 
    ) 
    ); 

$stmt->fetchAll(PDO::FETCH_ASSOC);回报什么。

有人能指出我在做什么错事吗?可以做到吗?如果不是,我应该参考哪些参数可以使用的完整的子句列表?

+0

获取值 – silent 2010-04-21 14:10:50

+0

没有,我在其他地方填充值手动,但它仍然没有工作。 – user198729 2010-04-21 14:12:39

+1

据我所知,你应该只绑定值,而不是列等。 – 2013-10-01 17:22:39

回答

3

您不能绑定参数来指定语言关键字或字段名称 - 它必须替换文字。因此,我认为你的极限值没问题,但你的订单不是。手动替换字符串中的排序和目录将是最好的。逃避它们,但不要使用DB工具来这样做,因为它们不是字符串文字。基本上确保不存在特殊字符。

+0

我用':sss:xxx'替换':sort:dir'但仍然无法工作。 – user198729 2010-04-21 14:25:50

+1

这不是我的意思。它取决于你的DBMS,它看起来像。例如,对于MySQL,您不能使用关键字或名称的绑定参数。在php.net上的用户发现如下:http://www.php.net/manual/en/pdo.prepare.php#71127。但是,如果您使用的是不同的DBMS,则无视我的答案。 – 2010-04-21 21:02:30

20

使用后:

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

我得到的消息:

未捕获的异常 'PDOException' 与 消息“SQLSTATE [42000]:语法错误 或访问冲突1064您有一个您的SQL语法中有 错误;检查对应于你的MySQL 服务器版本正确的语法 利用近“的 手册” 0' ,‘10’”在1号线

所以,当您使用执行阵列,它考虑您输入的字符串,它不是限制好主意

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results"; 
$stmt = $dbh->prepare($sql); 
$stmt->bindParam(':start', $_GET['start'], PDO::PARAM_INT); 
$stmt->bindParam(':results', $_GET['results'], PDO::PARAM_INT); 
$stmt->bindParam(':sort', $_GET['sort']); 
$stmt->bindParam(':dir', $_GET['dir']); 
$stmt->execute(); 

$data = $stmt->fetchAll(PDO::FETCH_ASSOC); 
print_r($data); 
+0

我从来没有看到这样的声明参数不能在'limit'和'order'条款,使用您可以参考提供一些链接?是否有哪些参数可以使用的完整列表? – user198729 2010-04-21 15:06:37

+0

看起来像我错了,只有表/列名不能被参数化。你的问题来自你的数组键,你忘了:(':sort'=> $ _GET ['sort'])。 – Arkh 2010-04-21 15:19:33

+0

不,':'是可选的(它仍然在增加后没有返回':')。你可以在这里看到这一点,如果你拉下来就够了:http://www.php.net/manual/en/pdostatement.execute.php – user198729 2010-04-21 15:22:35

5

预处理语句让DBMS实际执行查询为您提供的参数之前为您的查询的查询计划。更改ORDER BY的字段需要一个不同的查询计划,因为以不同的方式排序数据会严重影响DBMS选择获取数据的方式:例如,某些索引可能在一种情况下有帮助,但在另一种情况下可能不会。因此,ORDER BY字段应该形成传递给prepare()方法的SQL字符串的一部分,而不是绑定到​​之前的查询。

至于LIMIT子句,它的参数是否会影响查询计划并不清楚,所以这些可能会在稍后被绑定,可能取决于您的DBMS。根据this SO answer应该允许。

2

虽然这个问题还比较陈旧,但我认为它可能还是有趣的。对我来说,它的工作后,我

  1. 使用bindParam结合PDO::PARAM_INT像建议之前
  2. 通过调用intval()

代码的相关部分则看起来像转换的变量的内容为整数值这个:

$stmt->bindParam(':start', intval($_GET['start']), PDO::PARAM_INT); 
    $stmt->bindParam(':number', intval($_GET['number']), PDO::PARAM_INT); 

没有使用intval()我也收到了错误语法错误或访问冲突:1064您的SQL语法中有错误;检查对应于你的MySQL服务器版本正确的语法使用近“” 0' ,10' 的线需要1个