85

I've tried following the PHP.net instructions for doing SELECT queries but I am not sure the best way to go about doing this.

I would like to use a parameterized SELECT query, if possible, to return the ID in a table where the name field matches the parameter. This should return one ID because it will be unique.

I would then like to use that ID for an INSERT into another table, so I will need to determine if it was successful or not.

I also read that you can prepare the queries for reuse but I wasn't sure how this helps.

Simon East
  • 55,742
  • 17
  • 139
  • 133
Joe Phillips
  • 49,743
  • 32
  • 103
  • 159

6 Answers6

159

You select data like this:

$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

You insert in the same way:

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

I recommend that you configure PDO to throw exceptions upon error. You would then get a PDOException if any of the queries fail - No need to check explicitly. To turn on exceptions, call this just after you've created the $db object:

$db = new PDO("...");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
troelskn
  • 115,121
  • 27
  • 131
  • 155
  • I assume you mean PDOStatement where you have new PDO(...), right? – Joe Phillips Apr 21 '09 at 02:58
  • 1
    no. PDO is the connection-class (Should probably have been named PdoConnection instead). The connection can create PdoStatements. You call setAttribute() on the connection object - not the individual statements. (Alternatively, you can pass it to the constructor) – troelskn Apr 21 '09 at 13:35
  • 1
    this might be useful: `$db = new PDO('mysql:dbname=your_database;host=localhost', 'junior', '444');` – Junior Mayhé Sep 15 '12 at 02:12
  • 2
    For the line `$statement->execute(array(':name' => "Jimbo"));` , can you explain the Jimbo part? – muttley91 Dec 29 '12 at 16:16
  • 1
    @rar On the previous line, the query is initiated with a placeholder `:name`. Calling `execute` here is done with an associative array of placeholder -> value pairs. So in this case, the `:name` placeholder will be replaced with the string Jimbo. Note that it's not simply doing a string-replace, as the value is either escaped or sent over a different channel from the actual query, thus preventing any kind of injection attacks. – troelskn Dec 29 '12 at 16:32
  • Or said in a different way - It corresponds to writing the SQL query `select id from some_table where name = "Jimbo"` – troelskn Dec 29 '12 at 16:33
  • @troelskn You have: `$statement->execute(array(':some_id' => $row['id']));`. That is for a single column entry. What if I wanted to build an associative array that has huge number of entries. Like for example: `$statement->execute(array(':id1' => $row['id'], ':id2' => $row['id2'], ':id3' => $row['id3'], ........':id500' => $row['id500'], ':id501' => $row['id501']));`. I can type it out, but that'd be super cumbersome. How do you deal with something like that? I hope I make sense. – Honinbo Shusaku Jun 10 '15 at 19:43
  • @troelskn Would the answer to my question be to make an array with all the ':id#' and then loop through and `bindValue()` each corresponding elements? – Honinbo Shusaku Jun 10 '15 at 19:51
  • @Abdul Yes, unfortunately PDO only supports direct replacements - it can't rewrite the query. So you need some sort of php-side logic, that constructs the query and some placeholders. Keep in mind that these queries are usually very bad from a performance perspective, so you might want to deal with the case differently. – troelskn Jun 11 '15 at 10:54
16

I've been working with PDO lately and the answer above is completely right, but I just wanted to document that the following works as well.

$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();
SmashCode
  • 4,227
  • 8
  • 38
  • 56
  • 16
    No, it doesn't, as you haven't selected which database to use. – Rápli András Feb 20 '14 at 11:21
  • 3
    That should actually be in the "server" string, which should actually be a DSN in the form of "{driver}:dbname={db_name};host={server}" replacing the curly brace values with whatever your connection needs – thorne51 Aug 13 '15 at 13:17
12

You can use the bindParam or bindValue methods to help prepare your statement. It makes things more clear on first sight instead of doing $check->execute(array(':name' => $name)); Especially if you are binding multiple values/variables.

Check the clear, easy to read example below:

$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
}

If you are expecting multiple rows remove the LIMIT 1 and change the fetch method into 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
}
Gilly
  • 9,212
  • 5
  • 33
  • 36
  • Not sure. Seems like a valid answer to me. I think it would benefit from using 'myname' instead of 'name' and also using multiple params instead of just one. – Joe Phillips Mar 04 '14 at 23:59
  • @GillianLoWong What does the `$check = $q->fetch(PDO::FETCH_ASSOC); if (!empty($check)){ $row_id = $check['id']; // do something }` do? – Honinbo Shusaku Jun 10 '15 at 19:50
  • 1
    Hi @abdul, I have replaced the count/empty check on the array. It was supposed to see if any results were returned. But pdo also has a function called rowCount() that lets you check if any rows were affected/fetched at all. There is no point in fetching data if you dont even know if any rows were selected, so I moved the fetch statement into the if rowCount() statement. :) – Gilly Jun 11 '15 at 19:28
  • @Gillian La Wong thanks for your clean query of bindValue for multiple where query. that save my project. – php-coder Apr 30 '16 at 12:17
6

A litle bit complete answer is here with all ready for use:

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

 echo $done[0];

Here $dbh is PDO db connecter, and based on id from table users we've get the username using fetch();

I hope this help someone, Enjoy!

Domuta Marcel
  • 509
  • 5
  • 16
  • 1
    Or use `fetchColumn()` to avoid the `[0]` being needed. Also, remember to use `LIMIT 1` in the SQL. – rybo111 Jul 31 '16 at 23:26
4

Method 1:USE PDO query method

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

Getting Row Count

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

Method 2: Statements With Parameters

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

Method 3:Bind parameters

$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);

Want to know more look at this link

Sudhir
  • 835
  • 11
  • 31
-2

if you are using inline coding in single page and not using oops than go with this full example, it will sure help

//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 />";
}
Shiv Singh
  • 6,939
  • 3
  • 40
  • 50
  • While this code snippet may solve the problem, it doesn't explain why or how it answers the question. Please [include an explanation for your code](//meta.stackexchange.com/q/114762/269535), as that really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. **Flaggers / reviewers:** [For code-only answers such as this one, downvote, don't delete!](//meta.stackoverflow.com/a/260413/2747593) – Scott Weldon Nov 14 '16 at 23:45
  • So what should i delete it my self – Shiv Singh Nov 15 '16 at 09:14
  • No, exactly the opposite. I came across this post in the [Low Quality Posts Queue](//stackoverflow.com/review/low-quality-posts), and so the latter part of my comment was to tell people to **not** vote to delete. (The suggestion to downvote instead was meant to prompt provisional downvotes, which would be removed after your post has been edited.) As mentioned in my previous comment, it would be better if you added an explanation for why you suggested the code that you did. Also, this question asks about parameterized queries, but `field > 6969` looks hard-coded rather than parameterized. – Scott Weldon Nov 15 '16 at 16:54