为啥我的带有命名参数的查询返回空白结果?

Posted

技术标签:

【中文标题】为啥我的带有命名参数的查询返回空白结果?【英文标题】:Why does my query with named parameters return a blank result?为什么我的带有命名参数的查询返回空白结果? 【发布时间】:2012-09-23 05:40:33 【问题描述】:

我正在将我的 mysql 代码转换为 PDO 以利用准备好的语句。我最初遇到了this question 中描述的致命错误。我已经解决了这个问题,但是在尝试添加参数时会带来更多问题。

我正在尝试使用的代码是:

include ("foo/bar.php");

try 
     $DBH = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
      
catch(PDOException $e)   
    echo $e->getMessage();  
    

    $mydate=date("Y-m-d",strtotime("-3 months"));

    $foo_query=$DBH->prepare("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = :postdate AND postdate > '$mydate' ORDER BY postdate DESC");
    $foo_query->execute( array('postdate' => $_REQUEST['postdate']) );

    $DBH=null;

在英语中,这意味着阅读“取当前日期并将其设置为 3 个月,称之为 $mydate,然后选择所有这些字段(也取正文的前 20 个单词并称之为' preview_text') 来自我的表,其中 postdate 等于参数 postdate 并且 postdate 大于 $mydate"。

然后我在下面显示结果(请注意现在已被删节):

$foo_query->setFetchMode(PDO::FETCH_ASSOC);
    while($r=$foo_query->fetch()) 
    echo $r["id"];
    echo $r["title"];
    echo date("d-M-Y",strtotime($r["postdate"]));
    echo nl2br ($r["preview_text"]); 

现在,SELECT 查询写成:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate > '$mydate' ORDER BY postdate DESC")

...它准确地显示了我所需要的,但当然,在准备好时,它不包含任何参数,因此只能实现 50% 的目标。

我的印象是,按照我已经获得的教程和建议,准备我最初概述的声明的方式会很好。

我尝试打印我的错误,但没有出现任何错误。我手动发送查询如下,但没有得到任何回报。注意我已经尝试过各种排列方式的日期字符串:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = 20121001 AND postdate > 20120701 ORDER BY postdate DESC")

编辑:以上内容被指出不正确,但我将其保留在这里以供参考,因为本节在下面的 cmets 中进行了解释。

编辑:手动发送查询现在可以在键入时正确显示:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = '2012-09-30 08:38:23' ORDER BY postdate DESC")

键入以下任何内容时,查询根本不显示:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = :postdate ORDER BY postdate DESC")
("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = :postdate AND postdate > '$mydate' ORDER BY postdate DESC")
("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = '2012-09-30 08:38:23' AND postdate > '2012-07-01 00:01' ORDER BY postdate DESC")

我在想我应该以某种方式绑定参数,但我读过的教程并没有明确说我应该总是绑定它们 - 我不确定如何继续。

编辑:我希望将语句绑定如下,但没有成功。查询似乎忽略了绑定,因此查询的状态充当上述所有没有绑定的排列:

$foo_query->bindParam (
   ":postdate", strtotime ( $_REQUEST['postdate']), PDO::PARAM_INT);
$foo_query->execute();

我做错了什么,当我不添加参数时不会发生这种情况?我应该在 SELECT 查询以外的地方声明 :postdate 参数吗?

为了防止 SQL 注入,我想使用命名参数以及准备语句,但如果我无法弄清楚,那么我将不得不不使用命名参数。

【问题讨论】:

postdate = 20121001 AND postdate > 20120701 ? 是的 - 在英文中应该是“后日期等于 2012 年 10 月 1 日,后日期应该大于 2012 年 7 月 1 日”。这符合我写该语句的方式 - postdate = :postdate AND postdate > '$mydate' 您错过了这一点,20121001 根据定义大于 20120701。您查询中的 AND 没有任何意义!仅返回日期为 20121001 的记录。有吗? 看到这就是我认为问题所在。我已经尝试了各种日期排列,所以不要过多地阅读实际的字符串。例如,它是否必须采用我在 phpmyadmin 中看到的格式? AND 在 SELECT 查询中没有任何意义吗?我之前在 MySQL 和其他地方的查询中使用过它。 MySQL 的日期格式为 YYYYMMDD。再想一想 .. 你想要 2012 年 1 月 1 日和 2012 年 7 月 1 日之后的东西。结果是什么? 【参考方案1】:

当通过数组使用参数时,你绑定的是默认参数类型PDO::PARAM_STR

取决于数据类型:

MySQL 时间戳数据类型:相同,您将其作为字符串传递 PHP Unix 时间戳,它是一个整数:您将向它传递一个 int。

我建议您像这样更改代码:

$foo_query=$DBH->prepare(
   "SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body 
    FROM BarTable WHERE postdate = :postdate 
    ORDER BY postdate DESC");
$foo_query->bindParam (
   ":postdate", strtotime ( $_REQUEST['postdate']), PDO::PARAM_INT); 
//                                                  ^^^ bind as integer
$foo_query->execute(); 

【讨论】:

这仍然没有为我提出任何查询。但是,我没有收到任何错误。这与我用 $mydate 设置的日期有什么关系? 除了用 OR 替换 AND (​​根据另一个问题......)之外,这很有效。感谢所有帮助。

以上是关于为啥我的带有命名参数的查询返回空白结果?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JDBC 调用带有命名参数的 Sybase 存储过程

jpa命名本机查询无结果

如何在 JPA 命名查询的 IN 子句中使用动态参数?

带输入参数的命名查询

为啥命名查询?

在函数调用中“使用严格”和命名参数