如何检查MySQL中是不是存在行? (即检查电子邮件是不是存在于 MySQL 中)

Posted

技术标签:

【中文标题】如何检查MySQL中是不是存在行? (即检查电子邮件是不是存在于 MySQL 中)【英文标题】:How to check if a row exists in MySQL? (i.e. check if username or email exists in MySQL)如何检查MySQL中是否存在行? (即检查电子邮件是否存在于 MySQL 中) 【发布时间】:2014-04-10 18:23:38 【问题描述】:

我需要帮助检查数据库中是否存在行。就我而言,该行包含一个电子邮件地址。我得到了结果:

email no longer exists publisher@example.com

这是我目前使用的代码:

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";
    

有没有更好的方法来检查 MySQL 中是否存在一行(在我的例子中,检查 MySQL 中是否存在电子邮件)?

【问题讨论】:

$query 是一个字符串,所以 is_resource($query) 总是会失败...你没有运行查询。 继续阅读is_resource() Best way to test if a row exists in a MySQL table的可能重复 从不将数据直接连接到查询中...它会创建可能导致错误和安全问题的模糊查询。使用准备好的/参数化的查询来完全避免这个问题。至少,必须使用适当的转义。 【参考方案1】:

有多种方法可以检查数据库中是否存在值。让我演示如何使用 PDO 和 mysqli 正确完成此操作。

PDO

PDO 是更简单的选择。要查明数据库中是否存在某个值,您可以使用准备好的语句和fetchColumn()。无需获取任何数据,因此我们只会在值存在时获取1

<?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

更多示例见:How to check if email exists in the database?

MySQLi

与往常一样,mysqli 更麻烦一些,也更受限制,但我们可以使用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

除了将结果行(甚至可能不存在)转换为布尔值,您还可以获取 COUNT(1) 并使用 fetch_row()[0] 从第一行读取第一项

更多示例见:How to check whether a value exists in a database using mysqli prepared statements

小记

如果有人建议您使用mysqli_num_rows(),请不要听他们的。这是一种非常糟糕的方法,如果使用不当,可能会导致性能问题。 不要使用real_escape_string()。这并不是用来防止 SQL 注入的。如果您正确使用准备好的语句,则无需担心任何转义。 如果您想在尝试插入新行之前检查数据库中是否存在行,那么最好不要使用这种方法。最好在数据库中创建一个唯一键,如果存在重复值则让它抛出异常。

【讨论】:

【参考方案2】:

以下是检查行是否存在的经过尝试、测试和验证的方法。

(其中一些我自己用过,或者过去用过)。

编辑:我在我的语法中犯了一个错误,我使用了两次mysqli_query()。请查阅修订版。

即:

if (!mysqli_query($con,$query)) 应该简单地读作if (!$query)

对于忽略了这个错误,我深表歉意。

旁注:'".$var."''$var' 做同样的事情。您可以使用任何一种,两者都是有效的语法。

这是两个编辑后的查询:

$query = mysqli_query($con, "SELECT * FROM emails WHERE email='".$email."'");

    if (!$query)
    
        die('Error: ' . mysqli_error($con));
    

if(mysqli_num_rows($query) > 0)

    echo "email already exists";

else

    // do something


在你的情况下:

$query = mysqli_query($dbl, "SELECT * FROM `tblUser` WHERE email='".$email."'");

    if (!$query)
    
        die('Error: ' . mysqli_error($dbl));
    

if(mysqli_num_rows($query) > 0)

    echo "email already exists";

else

    // do something


你也可以使用mysqli_ with a prepared statement方法:

$query = "SELECT `email` FROM `tblUser` WHERE email=?";

if ($stmt = $dbl->prepare($query))

        $stmt->bind_param("s", $email);

        if($stmt->execute())
            $stmt->store_result();

            $email_check= "";         
            $stmt->bind_result($email_check);
            $stmt->fetch();

            if ($stmt->num_rows == 1)

            echo "That Email already exists.";
            exit;

            
        
    

Or a PDO method with a prepared statement:

<?php
$email = $_POST['email'];

$mysql_hostname = 'xxx';
$mysql_username = 'xxx';
$mysql_password = 'xxx';
$mysql_dbname = 'xxx';

try 
$conn= new PDO("mysql:host=$mysql_hostname;dbname=$mysql_dbname", $mysql_username, $mysql_password); 
     $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 catch (PDOException $e) 
     exit( $e->getMessage() );


// assuming a named submit button
if(isset($_POST['submit']))
    

        try 
            $stmt = $conn->prepare('SELECT `email` FROM `tblUser` WHERE email = ?');
            $stmt->bindParam(1, $_POST['email']); 
            $stmt->execute();
            while($row = $stmt->fetch(PDO::FETCH_ASSOC)) 

            
        
        catch(PDOException $e) 
            echo 'ERROR: ' . $e->getMessage();
        

    if($stmt->rowCount() > 0)
        echo "The record exists!";
     else 
        echo "The record is non-existant.";
    


    
?>
准备好的语句最好用于帮助防止 SQL 注入。

注意:

在处理上面使用/概述的表单和 POST 数组时,请确保 POST 数组包含值,POST 方法用于表单并匹配输入的命名属性。

仅供参考:如果没有明确指示,表单默认为 GET 方法。

注意:&lt;input type = "text" name = "var"&gt; - $_POST['var'] 匹配。 $_POST['Var'] 不匹配。

POST 数组区分大小写。

咨询:

http://php.net/manual/en/tutorial.forms.php

错误检查参考:

http://php.net/manual/en/function.error-reporting.php http://php.net/manual/en/mysqli.error.php http://php.net/manual/en/pdo.error-handling.php

请注意 MySQL API 不会混合使用,以防您在访问此问答时使用 mysql_ 进行连接(和查询)。

从连接到查询必须使用同一个。

请咨询以下内容:

Can I mix MySQL APIs in PHP?

如果您正在使用 mysql_ API 并且无法选择使用它,请参阅 Stack 上的以下问答:

MySql php: check if Row exists

mysql_* 函数已弃用,将从未来的 PHP 版本中删除。

是时候迈入 21 世纪了。

您还可以向 (a) 行添加 UNIQUE 约束。

参考资料:

http://dev.mysql.com/doc/refman/5.7/en/constraint-primary-key.html http://dev.mysql.com/doc/refman/5.7/en/alter-table.html How to check if a value already exists to avoid duplicates? How add unique key to existing table (with non uniques rows)

【讨论】:

我认为前两个例子不是注射安全的,而后两个例子是正确的吗?谢谢 此处将数据连接到查询中的方法已损坏,不应使用。始终使用某种参数化查询,或至少转义。 @Brad “总是使用某种形式的参数化查询,或者至少转义” - Err.. 这不是我的答案吗?你到底在找什么? 标记离开...您的顶部连接代码已损坏,这就是现实。您下面的代码显然很好。如果您编辑帖子并删除损坏的代码,我很乐意撤消反对票。而且,感谢您提请注意其他错误的答案...我会在今天晚些时候解决这些问题。 @Brad “你的代码连接到顶部被破坏了” - 你必须在这里具体说明,因为我看不出有什么地方被“破坏”了,如果有的话,你只是在拖钓我。我的回答或使用的任何语法都没有错,请不要侮辱我。编辑:如果你说的是email='".$email."',这是有效的语法,你可能认为它应该写成email='$email',我不知道。【参考方案3】:

在验证之后和插入之前检查用户名是否已经存在,使用 mysqli(procedural)。这有效:

//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

【讨论】:

从不将数据直接连接到查询中...它会创建可能导致错误和安全问题的模糊查询。使用准备好的/参数化的查询来完全避免这个问题。至少,必须使用适当的转义。【参考方案4】:

您必须执行查询并在查询中为 $email 添加单引号,因为它是一个字符串,并删除 is_resource($query) $query 是一个字符串,$result 将是资源

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

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

更新

在您的编辑基础上进行更改:

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

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

你会没事的

更新 2

更好的方法应该是有一个存储过程,它执行以下 SQL 并将电子邮件作为参数传递

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

并在php中检索值

伪代码:

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

【讨论】:

我正在组建一个名为 Pseudocodigo 的乐队。 从不将数据直接连接到查询中...它会创建可能导致错误和安全问题的模糊查询。使用准备好的/参数化的查询来完全避免这个问题。至少,必须使用适当的转义。 @Brad A better way should be have a Store Procedure that execute the following SQL passing the Email as Parameter @EmilioGort 这取决于您如何执行该存储过程! @Brad 只是一个问题:MYSQL 是否准备处理像 @Email='email@email.com');DROP TABLE USERS; 这样的参数' ??

以上是关于如何检查MySQL中是不是存在行? (即检查电子邮件是不是存在于 MySQL 中)的主要内容,如果未能解决你的问题,请参考以下文章

检查返回的值是不是为空[重复]

如何检查电子邮件是不是确实存在

检查mysql表php中是不是存在任何记录

SQLAlchemy - MySQL - 检查现有表中是不是存在行[重复]

如何在 Python 中检查电子邮件是不是存在?

使用 Python 检查电子邮件是不是真实 [关闭]