49

I need help checking if a row exists in the database. In my case, that row contains an email address. I am getting the result:

email no longer exists publisher@example.com

This is the code I'm currently using:

if (count($_POST)) {
    $email = $dbl->real_escape_string(trim(strip_tags($_POST['email'])));

    $query = "SELECT `email` FROM `tblUser` WHERE `email` = '$email'";
    $result = mysqli_query($dbl, $query);
    if (is_resource($result) && mysqli_num_rows($result) == 1) {
        $row = mysqli_fetch_assoc($result);
        echo $email . " email exists " .  $row["email"] . "\n";
    } else {
        echo "email no longer exists" . $email . "\n";
    }
}

Is there a better way to check if a row exists in MySQL database (in my case, check if an email exists in MySQL)?

Dharman
  • 30,962
  • 25
  • 85
  • 135
user2882684
  • 539
  • 1
  • 5
  • 10
  • 2
    $query is a string so is_resource($query) will always fail... you're not running the query. – Digital Chris Mar 07 '14 at 14:37
  • Read up on [`is_resource()`](http://php.net/is_resource) – Funk Forty Niner Mar 07 '14 at 14:54
  • Possible duplicate of [Best way to test if a row exists in a MySQL table](http://stackoverflow.com/questions/1676551/best-way-to-test-if-a-row-exists-in-a-mysql-table) – T.Todua Aug 15 '16 at 18:34
  • 1
    **Never** concatenate data directly into a query... it create ambiguous queries which can lead to errors and security issues. Use prepared/parameterized queries to avoid this issue entirely. At a minimum, proper escaping must be used. – Brad Jul 14 '17 at 18:34

4 Answers4

81

Using mysqli prepared statements legacy approach:

$query = "SELECT 1 FROM `tblUser` WHERE email=?";
$stmt = $dbl->prepare($query);
$stmt->bind_param("s", $email);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$emailExists = (bool)$row;

Using mysqli modern approach staring PHP 8.2:

$query = "SELECT 1 FROM `tblUser` WHERE email=?";
$result = $dbl->execute_query($query, [$email]);
$row = $result->fetch_assoc();
$emailExists = (bool)$row;

Using PDO prepared statement:

$email = $_POST['email'];
$stmt = $conn->prepare('SELECT 1 FROM `tblUser` WHERE email = :email');
$stmt->execute(["email" => $_POST['email']]);
$row = $result->fetch();
$emailExists = (bool)$row;
  • Prepared statements are best to be used to help protect against an SQL injection.

N.B.:

When dealing with forms and POST arrays as used/outlined above, make sure that the POST arrays contain values, that a POST method is used for the form and matching named attributes for the inputs.

  • FYI: Forms default to a GET method if not explicity instructed.

Note: <input type = "text" name = "var"> - $_POST['var'] match. $_POST['Var'] no match.

  • POST arrays are case-sensitive.

Consult:

Error checking references:

Please note that MySQL APIs do not intermix, in case you may be visiting this Q&A and you're using mysql_ to connect with (and querying with).

  • You must use the same one from connecting to querying.

Consult the following about this:

If you are using the mysql_ API and have no choice to work with it, then consult the following Q&A on Stack:

The mysql_* functions are deprecated and will be removed from future PHP releases.

  • It's time to step into the 21st century.

You can also add a UNIQUE constraint to (a) row(s).

References:

How add unique key to existing table (with non uniques rows)

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
  • 4
    Am I right in thinking the first 2 examples are NOT injection safe, and the latter 2 are? Thanks – slaw Oct 20 '15 at 06:47
  • 1
    The methods here that are concatenating data into the query are broken and should not be used. Always use parameterized queries of some kind, or escaping at a minimum. – Brad Jul 14 '17 at 18:15
  • @Brad *"Always use parameterized queries of some kind, or escaping at a minimum"* - Err.. isn't that in my answer? what are you looking for anyway? – Funk Forty Niner Jul 14 '17 at 18:19
  • Flag away... your code concatenating up top is broken and that's just reality. Your code below that is obviously fine. If you edit your post and remove broken code, I'd be happy to undo the downvote. And, thanks for calling attention to the other broken answers... I'll get to those later today. – Brad Jul 14 '17 at 18:32
  • @Brad *"your code concatenating up top is broken"* - you're going to have to be specific here, because I don't see where anything is "broken", you're just trolling me if anything. There is nothing wrong with my answer or any of the syntax used, please don't insult me. Edit: If you're talking about `email='".$email."'` that is valid syntax where you may think it should have been written as `email='$email'`, I don't know. – Funk Forty Niner Jul 20 '17 at 14:04
  • @Brad FYI: I did update my answer but it wasn't in regards to what you may have been talking about in regards to concatenation for `'".$var."'` and `'$var'` if that's what you were talking about (and made a side note about that in the edit), I don't know since you never mentioned specifics. The update I did make, was in regards to my using `mysqli_query()` twice, to which that was fixed/edited. That is pretty much *it*. If that doesn't satisfy your concern, then you will need to type this all out for me, because I don't know what you were talking about *exactly*. – Funk Forty Niner Jul 20 '17 at 14:30
8

You have to execute your query and add single quote to $email in the query beacuse it's a string, and remove the is_resource($query) $query is a string, the $result will be the resource

$query = "SELECT `email` FROM `tblUser` WHERE `email` = '$email'";
$result = mysqli_query($link,$query); //$link is the connection

if(mysqli_num_rows($result) > 0 ){....}

UPDATE

Base in your edit just change:

if(is_resource($query) && mysqli_num_rows($query) > 0 ){
        $query = mysqli_fetch_assoc($query);
        echo $email . " email exists " .  $query["email"] . "\n";

By

if(is_resource($result) && mysqli_num_rows($result) == 1 ){
        $row = mysqli_fetch_assoc($result);
         echo $email . " email exists " .  $row["email"] . "\n";

and you will be fine

UPDATE 2

A better way should be have a Store Procedure that execute the following SQL passing the Email as Parameter

SELECT IF( EXISTS (
                  SELECT *
                  FROM `Table`
                  WHERE `email` = @Email)
          , 1, 0) as `Exist`

and retrieve the value in php

Pseudocodigo:

 $query = Call MYSQL_SP($EMAIL);
 $result = mysqli_query($conn,$query);
 $row = mysqli_fetch_array($result)
 $exist = ($row['Exist']==1)? 'the email exist' : 'the email doesnt exist';
Emilio Gort
  • 3,475
  • 3
  • 29
  • 44
  • 1
    I'm so making a band called Pseudocodigo. – Brian Powell Apr 12 '16 at 16:26
  • 2
    **Never** concatenate data directly into a query... it create ambiguous queries which can lead to errors and security issues. Use prepared/parameterized queries to avoid this issue entirely. At a minimum, proper escaping must be used. – Brad Jul 14 '17 at 18:34
  • @Brad `A better way should be have a Store Procedure that execute the following SQL passing the Email as Parameter` – Emilio Gort Jul 14 '17 at 18:56
  • 1
    @EmilioGort That depends on how you execute that stored procedure! – Brad Jul 14 '17 at 18:57
  • @Brad just a question: Is it MYSQL prepare to handle a parameter like @Email='email@email.com');DROP TABLE USERS; ' ?? – Emilio Gort Jul 14 '17 at 19:01
6

There are multiple ways to check if a value exists in the database. Let me demonstrate how this can be done properly with PDO and mysqli.

PDO

PDO is the simpler option. To find out whether a value exists in the database you can use prepared statement and fetchColumn(). There is no need to fetch any data so we will only fetch 1 if the value exists.

<?php

// Connection code. 
$options = [
    \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
    \PDO::ATTR_EMULATE_PREPARES   => false,
];
$pdo = new \PDO('mysql:host=localhost;port=3306;dbname=test;charset=utf8mb4', 'testuser', 'password', $options);

// Prepared statement
$stmt = $pdo->prepare('SELECT 1 FROM tblUser WHERE email=?');
$stmt->execute([$_POST['email']]);
$exists = $stmt->fetchColumn(); // either 1 or null

if ($exists) {
    echo 'Email exists in the database.';
} else {
    // email doesn't exist yet
}

For more examples see: How to check if email exists in the database?

MySQLi

As always mysqli is a little more cumbersome and more restricted, but we can follow a similar approach with prepared statement.

<?php

// Connection code
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli('localhost', 'testuser', 'password', 'test');
$mysqli->set_charset('utf8mb4');

// Prepared statement
$stmt = $mysqli->prepare('SELECT 1 FROM tblUser WHERE email=?');
$stmt->bind_param('s', $_POST['email']);
$stmt->execute();
$exists = (bool) $stmt->get_result()->fetch_row(); // Get the first row from result and cast to boolean

if ($exists) {
    echo 'Email exists in the database.';
} else {
    // email doesn't exist yet
}

Instead of casting the result row(which might not even exist) to boolean, you can also fetch COUNT(1) and read the first item from the first row using fetch_row()[0]

For more examples see: How to check whether a value exists in a database using mysqli prepared statements

Minor remarks

  • If someone suggests you to use mysqli_num_rows(), don't listen to them. This is a very bad approach and could lead to performance issues if misused.
  • Don't use real_escape_string(). This is not meant to be used as a protection against SQL injection. If you use prepared statements correctly you don't need to worry about any escaping.
  • If you want to check if a row exists in the database before you try to insert a new one, then it is better not to use this approach. It is better to create a unique key in the database and let it throw an exception if a duplicate value exists.
Community
  • 1
  • 1
Dharman
  • 30,962
  • 25
  • 85
  • 135
2

After validation and before INSERT check if username already exists, using mysqli(procedural). This works:

//check if username already exists
       include 'phpscript/connect.php'; //connect to your database

       $sql = "SELECT username FROM users WHERE username = '$username'";
       $result = $conn->query($sql);

       if($result->num_rows > 0) {
           $usernameErr =  "username already taken"; //takes'em back to form
       } else { // go on to INSERT new record
robhoomph
  • 45
  • 2
  • 2
    **Never** concatenate data directly into a query... it create ambiguous queries which can lead to errors and security issues. Use prepared/parameterized queries to avoid this issue entirely. At a minimum, proper escaping must be used. – Brad Jul 14 '17 at 18:33