【问题标题】:Check if all values in an array exist in a database column检查数组中的所有值是否都存在于数据库列中
【发布时间】:2021-08-03 21:38:55
【问题描述】:

我有一系列电子邮件,我想通过验证我的数据库来检查所有这些电子邮件是否有效。我想将无效的电子邮件(如果有)添加到一个空数组中。我对 MySQL 不太熟悉,所以我需要一些帮助。这是我目前在我的 PHP 文件中的内容:

<?php

$conn = mysqli_connect($servername, $username, $password, $db);
$conn->select_db($db);

if($conn->connect_error) {
    die("Connection failed " . $conn->connect_error);
}
echo "Connected successfully\n";

$tags = preg_split("/\,/", $_POST['tags']);
$invalidEmails = array();
$count = 0;

$result = $conn->query("SELECT mail FROM dej_colleagues");
for ($i = 0; $i < sizeof($tags); $i++) {
    $trim_brackets = trim($tags[$i], '[]');
    $trim_quotes = trim($trim_brackets, '"');
    
    while ($row = mysqli_fetch_array($result, MYSQL_ASSOC)) {
        if ($trim_quotes == $row["mail"]) {
            $count += 1;
        }
        else {
            array_push($invalidEmails, $tags[i]);
        }
    }
}
if (sizeof($tags) == $count) {
    echo "good";
}
?>

我的数据库连接成功,但即使我的标签数组中的电子邮件存在于数据库中,它也没有检测到它。另外,数据库列有 100k 个条目,如果您知道更有效的方法,请告诉我。

【问题讨论】:

    标签: php mysql database mysqli


    【解决方案1】:

    使用WHERE IN 构建语句以获取匹配的邮件,然后比较结果数组会更有效。 您可以使用array_diff() 来获取数组的差异。

    <?php
    
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $conn = mysqli_connect($servername, $username, $password, $db);
    
    echo "Connected successfully\n";
    
    $tags = preg_split("/\,/", $_POST['tags']);
    $invalidEmails = array();
    $count = 0;
    
    // modify your array how you want it
    foreach ($tags as $i => $tag) {
        $trim_brackets = trim($tag, '[]');
        $trim_quotes = trim($trim_brackets, '"');
        $tags[$i] = $trim_quotes;
    }
    
    // build placeholders for WHERE IN
    $in = str_repeat('?,', count($tags) - 1) . '?';
    // prepare query
    $stmt = $conn->prepare("SELECT mail FROM dej_colleagues WHERE mail IN ($in)");
    // bind an array of values. First params is a type list.
    $stmt->bind_param(str_repeat('s', count($tags)), ...$tags);
    $stmt->execute();
    $results = $stmt->get_result();
    // fetch the matching mails into an array
    $mails = [];
    foreach ($results as $row) {
        $mails[] = $row['mail'];
    }
    
    // get the difference between the two arrays
    $invalidEmails = array_diff($tags, $mails);
    
    if (count($tags) === count($mails)) {
        echo "good";
    }
    
    var_dump($invalidEmails);
    

    【讨论】:

    • 我有没有其他方法可以解包而不是做 ...$tags ?我的php版本不是5.6
    • @viktor 你一定是在开玩笑吧。你能升级到更明智的东西吗?运行这么旧的版本是不负责任的。使用这么旧的版本真的很难。你在伤害自己。这应该会有所帮助,但请尽快升级。 stackoverflow.com/a/42373791/1839439
    • @viktor 另外,尝试远离 mysqli。请改用 PDO。这要容易得多,尤其是考虑到您的 PHP 版本是多少。从这里开始phpdelusions.net/pdo & websitebeaver.com/…
    【解决方案2】:

    问题可能是,一旦结果中没有更多行,mysqli_fetch_array 将返回 null。这意味着for ($i = 0; $i &lt; sizeof($tags); $i++) 循环第二次运行时,它将找不到任何行,因此while 循环不会再次运行。

    您需要将 SQL 结果输出到一个常规的 PHP 数组中,这样您就可以重复循环它们而不会出现这个问题。

    例如:

    $result = $conn->query("SELECT mail FROM dej_colleagues");
    $rows = mysqli_fetch_all($result, MYSQL_ASSOC);
    
    for ($i = 0; $i < sizeof($tags); $i++) {
        $trim_brackets = trim($tags[$i], '[]');
        $trim_quotes = trim($trim_brackets, '"');
        
        foreach ($rows as $row) {
            if ($trim_quotes == $row["mail"]) {
                $count += 1;
            }
            else {
                array_push($invalidEmails, $tags[i]);
            }
        }
    }
    

    文档:https://www.php.net/manual/en/mysqli-result.fetch-all.php


    注意可能有比这更有效的数据搜索方法,但这超出了我的回答范围。

    【讨论】:

    • 请注意,当您获取 10 万条记录时,这会非常慢。根据情况,您也可能会耗尽内存。最好只获取您需要的数据
    • 如果我在 for 循环之后添加 mysqli_free_result($result) ,这有助于释放一些内存吗?
    • @viktor 不,mysqli_free_result 绝对没用。要么尝试我的优化解决方案,要么使用无缓冲的查询,这是一场噩梦。
    • @Dharman 绝对,我在回答的最后部分提到了这一点。我只是想指出逻辑错误。
    猜你喜欢
    • 1970-01-01
    • 2021-08-06
    • 2015-04-12
    • 2021-01-07
    • 1970-01-01
    • 2020-09-19
    • 2014-01-02
    • 2021-06-27
    • 1970-01-01
    相关资源
    最近更新 更多