【问题标题】:How can I properly use a PDO object for a parameterized SELECT query如何正确使用 PDO 对象进行参数化 SELECT 查询
【发布时间】:2010-10-20 12:04:00
【问题描述】:

我已尝试按照 PHP.net 的说明进行 SELECT 查询,但我不确定执行此操作的最佳方法。

如果可能,我想使用参数化的SELECT 查询在name 字段与参数匹配的表中返回ID。这应该返回一个ID,因为它是唯一的。

然后我想将ID 用作另一个表中的INSERT,因此我需要确定它是否成功。

我还读到您可以准备查询以供重复使用,但我不确定这有什么帮助。

【问题讨论】:

    标签: php mysql select pdo


    【解决方案1】:

    您选择这样的数据:

    $db = new PDO("...");
    $statement = $db->prepare("select id from some_table where name = :name");
    $statement->execute(array(':name' => "Jimbo"));
    $row = $statement->fetch(); // Use fetchAll() if you want all results, or just iterate over the statement, since it implements Iterator
    

    你用同样的方法插入:

    $statement = $db->prepare("insert into some_other_table (some_id) values (:some_id)");
    $statement->execute(array(':some_id' => $row['id']));
    

    我建议您将 PDO 配置为在出错时抛出异常。如果任何查询失败,您将获得PDOException - 无需明确检查。要打开异常,请在创建 $db 对象后调用它:

    $db = new PDO("...");
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    

    【讨论】:

    • 我假设你的意思是 PDOStatement,你有新的 PDO(...),对吧?
    • 没有。 PDO 是连接类(应该改名为 PdoConnection)。连接可以创建 PdoStatements。您在连接对象上调用 setAttribute() - 而不是单个语句。 (或者,您可以将其传递给构造函数)
    • 这可能有用:$db = new PDO('mysql:dbname=your_database;host=localhost', 'junior', '444');
    • 对于$statement->execute(array(':name' => "Jimbo"));这一行,能解释一下Jimbo部分吗?
    • @rar 在上一行中,查询以占位符:name 启动。在这里调用execute 是使用占位符-> 值对的关联数组完成的。所以在这种情况下,:name 占位符将被替换为字符串 Jimbo。请注意,它不是简单地进行字符串替换,因为值要么被转义,要么通过与实际查询不同的通道发送,从而防止任何类型的注入攻击。
    【解决方案2】:

    我最近一直在使用 PDO,上面的答案是完全正确的,但我只是想证明以下内容也有效。

    $nametosearch = "Tobias";
    $conn = new PDO("server", "username", "password");
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $sth = $conn->prepare("SELECT `id` from `tablename` WHERE `name` = :name");
    $sth->bindParam(':name', $nametosearch);
    // Or sth->bindParam(':name', $_POST['namefromform']); depending on application
    $sth->execute();
    

    【讨论】:

    • 不,它没有,因为您还没有选择要使用的数据库。
    • 这实际上应该在“server”字符串中,它实际上应该是一个DSN,形式为“{driver}:dbname={db_name};host={server}”替换花括号值与您的连接需要的任何值
    【解决方案3】:

    您可以使用bindParambindValue 方法来帮助准备您的陈述。 它使事情一目了然,而不是 $check->execute(array(':name' => $name));,尤其是在绑定多个值/变量时。

    查看下面清晰易读的示例:

    $q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname LIMIT 1");
    $q->bindValue(':forename', 'Joe');
    $q->bindValue(':surname',  'Bloggs');
    $q->execute();
    
    if ($q->rowCount() > 0){
        $check = $q->fetch(PDO::FETCH_ASSOC);
        $row_id = $check['id'];
        // do something
    }
    

    如果您希望多行删除LIMIT 1并将获取方法更改为fetchAll

    $q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname");// removed limit 1
    $q->bindValue(':forename', 'Joe');
    $q->bindValue(':surname',  'Bloggs');
    $q->execute();
    
    if ($q->rowCount() > 0){
        $check = $q->fetchAll(PDO::FETCH_ASSOC);
        //$check will now hold an array of returned rows. 
        //let's say we need the second result, i.e. index of 1
        $row_id = $check[1]['id']; 
        // do something
    }
    

    【讨论】:

    • 不确定。对我来说似乎是一个有效的答案。我认为使用“myname”而不是“name”以及使用多个参数而不是一个参数会受益。
    • @GillianLoWong $check = $q->fetch(PDO::FETCH_ASSOC); if (!empty($check)){ $row_id = $check['id']; // do something } 做什么?
    • 嗨@abdul,我已经替换了阵列上的计数/空检查。它应该看看是否返回了任何结果。但是 pdo 也有一个名为 rowCount() 的函数,可以让您检查是否有任何行受到影响/获取。如果您甚至不知道是否选择了任何行,那么获取数据是没有意义的,因此我将 fetch 语句移到了 if rowCount() 语句中。 :)
    • @Gillian La Wong 感谢您对多个 where 查询的 bindValue 的干净查询。保存我的项目。
    【解决方案4】:

    这里有一点完整的答案,一切准备就绪:

        $sql = "SELECT `username` FROM `users` WHERE `id` = :id";
        $q = $dbh->prepare($sql);
        $q->execute(array(':id' => "4"));
        $done= $q->fetch();
    
     echo $done[0];
    

    这里 $dbh 是 PDO 数据库连接器,基于表 users 中的 id,我们使用 fetch(); 得到了 username

    我希望这对某人有所帮助,享受吧!

    【讨论】:

    • 或使用fetchColumn() 来避免需要[0]。另外,记得在 SQL 中使用LIMIT 1
    【解决方案5】:

    方法一:使用PDO查询方法

    $stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    

    获取行数

    $stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
    $row_count = $stmt->rowCount();
    echo $row_count.' rows selected';
    

    方法二:带参数的语句

    $stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
    $stmt->execute(array($name));
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    

    方法三:绑定参数

    $stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
    $stmt->bindValue(1, $name, PDO::PARAM_STR);
    $stmt->execute();
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    **bind with named parameters**
    $stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
    $stmt->bindValue(':name', $name, PDO::PARAM_STR);
    $stmt->execute();
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    or
    $stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
    $stmt->execute(array(':name' => $name));
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    

    想知道更多看这个link

    【讨论】:

    • 请去掉方法一。它允许mysql注入。
    【解决方案6】:

    如果你在单页中使用内联编码而不是使用 oops,而不是使用这个完整的示例,它肯定会有所帮助

    //connect to the db
    $dbh = new PDO('mysql:host=localhost;dbname=mydb', dbuser, dbpw); 
    
    //build the query
    $query="SELECT field1, field2
    FROM ubertable
    WHERE field1 > 6969";
    
    //execute the query
    $data = $dbh->query($query);
    //convert result resource to array
    $result = $data->fetchAll(PDO::FETCH_ASSOC);
    
    //view the entire array (for testing)
    print_r($result);
    
    //display array elements
    foreach($result as $output) {
    echo output[field1] . " " . output[field1] . "<br />";
    }
    

    【讨论】:

    • 虽然这段代码 sn-p 可以解决问题,但它没有解释为什么或如何回答这个问题。请include an explanation for your code,因为这确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。 举报者/评论者: For code-only answers such as this one, downvote, don't delete!
    • 那我应该怎么删除它自己
    • 不,恰恰相反。我在Low Quality Posts Queue 看到了这篇文章,所以我评论的后半部分是告诉人们不要投票删除。 (相反,反对投票的建议是为了提示临时反对票,这将在您的帖子被编辑后被删除。)正如我之前的评论中提到的,如果您添加一个解释为什么您建议您所做的代码会更好.此外,这个问题询问参数化查询,但 field &gt; 6969 看起来是硬编码而不是参数化。
    猜你喜欢
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多