使用 PDO 的条件选择查询

Posted

技术标签:

【中文标题】使用 PDO 的条件选择查询【英文标题】:Conditional select queries with PDO 【发布时间】:2015-12-29 13:48:51 【问题描述】:

我有一些使用 mysql_query 的 php 脚本,但现在我正试图将其更改为 PDO(他们说更不易受攻击且更安全),但我在条件选择查询方面遇到了一些问题。 我有以下代码:

$querydatahora = $conn->prepare('SELECT 
    Linhas.NomeLinha, Maquinas.Nome as maquina, Tecnicos.Nome, Avarias.DataHoraInicioAvaria, 
    Avarias.DataHoraFimAvaria, Avarias.Descricao, Avarias.Solucao, Avarias.TipoSolucao 
    FROM Avarias, Tecnicos, Linhas, Maquinas, avariatecnico 
    where Linhas.IDLinha = Avarias.IDLinha and avariatecnico.IDAvaria = avarias.IDAvaria and Avariatecnico.IDTecnico = Tecnicos.IDTecnico and 
    Maquinas.IDMaquina = Avarias.IDMaquina and DataHoraInicioAvaria >= :datetimepicker AND DataHoraFimAvaria <= :datetimepicker1 ');


if( $_SESSION['IDLinha'] ) 
    $querydatahora .= $conn->prepare(" AND Avarias.IDLinha = :IDLinha AND Avarias.IDMaquina = :IDMaquina order by DataHoraInicioAvaria DESC LIMIT $startrow, 9");
 else
    $querydatahora .= $conn->prepare(" order by DataHoraInicioAvaria DESC LIMIT $startrow, 9");


$querydatahora->execute( array(
    ':datetimepicker'   => $_SESSION['datetimepicker'], 
    ':datetimepicker1'  => $_SESSION['datetimepicker1'], 
    ':IDLinha'          => $_SESSION['IDLinha'], 
    ':IDMaquina'        => $_SESSION['IDMaquina'])
);

if( $_SESSION['IDLinha'] ) 
    $querycount .= $conn->prepare(' AND Avarias.IDLinha = :IDLinha AND Avarias.IDMaquina = :IDMaquina');


$querycount->execute( array(
    ':datetimepicker'   => $_SESSION['datetimepicker'], 
    ':datetimepicker1'  => $_SESSION['datetimepicker1'], 
    ':IDLinha'          => $_SESSION['IDLinha'], 
    ':IDMaquina'        => $_SESSION['IDMaquina'])
);

我得到的错误是:

可捕获的致命错误:无法将 PDOStatement 类的对象转换为 C:\xxxxxxxxxxxxxxxxxxxxxxxxxx.php 中第 52 行的字符串

我不是这方面的专家,所以我可能做错了什么。感谢所有帮助

【问题讨论】:

prepare() 返回一个 PDOStatement 对象,这是您的异常的来源,它不是字符串。您应该只传递 prepare() 完整的查询,即将 SQL 查询(带占位符)生成一个字符串,然后运行 ​​prepare() 传递完整的查询字符串。 您需要在调用 $conn->prepare...基于该字符串。 我认为如果你使用 join 会更容易... 【参考方案1】:

您需要先构建查询,然后再进行准备

$sql = 'SELECT Linhas.NomeLinha,
               Maquinas.Nome as maquina,
               Tecnicos.Nome, 
               Avarias.DataHoraInicioAvaria,
               Avarias.DataHoraFimAvaria,
               Avarias.Descricao,
               Avarias.Solucao, 
               Avarias.TipoSolucao 
        FROM Avarias, Tecnicos, Linhas, Maquinas, avariatecnico
        WHERE Linhas.IDLinha = Avarias.IDLinha
        AND avariatecnico.IDAvaria = avarias.IDAvaria
        AND Avariatecnico.IDTecnico = Tecnicos.IDTecnico
        AND Maquinas.IDMaquina = Avarias.IDMaquina
        AND DataHoraInicioAvaria >= :datetimepicker
        AND DataHoraFimAvaria <= :datetimepicker1 ';

if ($_SESSION['IDLinha']) 
    $querydatahora = $conn->prepare($sql." AND Avarias.IDLinha = :IDLinha
                                           AND Avarias.IDMaquina = :IDMaquina
                                           ORDER BY DataHoraInicioAvaria
                                           DESC LIMIT $startrow, 9");
else
    $querydatahora = $conn->prepare($sql." ORDER BY DataHoraInicioAvaria
                                           DESC LIMIT $startrow, 9");



$params = array(':datetimepicker' => $_SESSION['datetimepicker'],
                ':datetimepicker1' => $_SESSION['datetimepicker1'],
                ':IDLinha' => $_SESSION['IDLinha'],
                ':IDMaquina' => $_SESSION['IDMaquina']
                );

$querydatahora->execute($params);

$params = array(':datetimepicker' => $_SESSION['datetimepicker'],
               ':datetimepicker1' => $_SESSION['datetimepicker1']);

if ($_SESSION['IDLinha']) 
    $querycount = $conn->prepare($sql.' AND Avarias.IDLinha = :IDLinha 
                                        AND Avarias.IDMaquina = :IDMaquina');
    $params[':IDLinha'] = $_SESSION['IDLinha'];
    $params[':IDMaquina']  $_SESSION['IDMaquina'];


$querycount->execute($params);

【讨论】:

感谢您的回答。我已经尝试过该示例,但出现以下错误: 警告:PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in C:\xxxxxxxxxxxxx.php on line 61 注意:未定义变量:第 67 行 C:\xxxxxxxxxxxxxx.php 中的 querycount 致命错误:第 67 行 C:xxxxxxxxxxxxx.php 中的 null 调用成员函数 execute()【参考方案2】:

你必须先建立一个查询字符串。

$querydatahora = 'SELECT Linhas.NomeLinha, Maquinas.Nome as maquina, Tecnicos.Nome, Avarias.DataHoraInicioAvaria, Avarias.DataHoraFimAvaria, Avarias.Descricao, Avarias.Solucao, Avarias.TipoSolucao 
FROM Avarias, Tecnicos, Linhas, Maquinas, avariatecnico where Linhas.IDLinha = Avarias.IDLinha and avariatecnico.IDAvaria = avarias.IDAvaria and Avariatecnico.IDTecnico = Tecnicos.IDTecnico and 
Maquinas.IDMaquina = Avarias.IDMaquina and DataHoraInicioAvaria >= :datetimepicker AND DataHoraFimAvaria <= :datetimepicker1'

// Your minimal parameters
$params = array(':datetimepicker' => $_SESSION['datetimepicker'], ':datetimepicker1' => $_SESSION['datetimepicker1']);

// Test you have the mandatory variables IDLinha and IDMaquina
if (isset($_SESSION['IDLinha']) && isset($_SESSION['IDMaquina'])) 
    $querydatahora .= " AND Avarias.IDLinha = :IDLinha AND Avarias.IDMaquina = :IDMaquina");
    // Adding parameters
    $params = array_merge($params, array(':IDLinha' => $_SESSION['IDLinha'],':IDMaquina' => $_SESSION['IDMaquina']));


// In anyway you will do the same order by then write it at the end
$querydatahora .= " order by DataHoraInicioAvaria DESC LIMIT $startrow, 9";

// Your querystring is ok then let's prepare it
$stmt = $conn->prepare($querydatahora);

// Now Run with parameters
$stmt->execute($params);

我已删除您的查询计数,因为我想专注于第一个查询并使其正常工作

【讨论】:

致命错误:在“$querydatahora->execute($params);”行中的字符串上调用成员函数 execute() 更新:将 $querydatahora->execute 替换为 $conn->execute $stmt = $conn-&gt;prepare(...); $stmt-&gt;execute(...) 你的意思是? $querydatahora 是一个字符串,你可以在语句上使用 fetchColumn :$stmt->fetchColumn() 使用 $conn->quote($_SESSION['datetimepicker'])

以上是关于使用 PDO 的条件选择查询的主要内容,如果未能解决你的问题,请参考以下文章

PDO 参数化与非参数化查询速度

如何在 mysql PDO 选择查询中仅从时间戳中选择时间?

是否可以将变量值添加到选择查询结果 php pdo

使用PDO执行基于另一个查询结果的查询的函数

Php Pdo - 选择最后插入的

在mysql PDO中更新后选择行