PHP - 在插入之前检查行是否存在

时间:2015-07-04 22:58:00

标签: php mysql pdo

$DBH = new PDO($dsn, $username, $password, $opt);

$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$STH = $DBH->prepare("INSERT INTO requests (id,imdbid,msg) VALUES ('',:imdbid,:msg)");
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);

$STH->execute();
echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";

是否有一些SQL Query会检查和插入或者是什么? 我需要它来检查用户输入的内容是否已经存在于数据库中,因此如果用户键入已经存在的imdbid,那么它将不会继续插入任何内容。我该怎么做?我知道我可以做一个fetch_all并为它做一个foreach但是只有在你执行之后才能工作吗?

3 个答案:

答案 0 :(得分:5)

最好在列上设置约束以防止重复数据,而不是检查和插入。

只需在imdbid上设置UNIQUE约束:

ALTER TABLE `requests` ADD UNIQUE `imdbid_unique`(`imdbid`);

这样做的原因是您不会遇到race condition

在完成检查和实际插入数据之间有一个小窗口,在那个小窗口中,可能会插入与待插入数据冲突的数据。

解决方案?使用约束并检查$DBH->error()是否存在插入错误。如果有任何错误,您知道存在重复,然后您可以通知您的用户。

我注意到您正在使用此$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);。在这种情况下,您无需检查->error(),因为PDO将抛出异常。只需用try尝试包装你的执行,然后像这样抓住:

$duplicate = false;

try {
    $STH->execute();
} catch (Exception $e) {
    echo "<p>Failed to Request ".$_POST['imdbid']."!</p>";
    $duplicate = true;
}

if (!$duplicate)
    echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";

答案 1 :(得分:2)

只需在插入之前运行查询。

如果发现死于剧本:

$DBH = new PDO($dsn, $username, $password, $opt);

$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$sql = 'SELECT COUNT(*) from requests WHERE imdbid = :imdbid';
$stmt = $DBH->prepare($sql);
$stmt->execute(array(':imdbid' => $_POST['imdbid']));

if($stmt->fetchColumn()){ die('Already exist');}

$STH = $DBH->prepare("INSERT INTO requests (id,imdbid,msg) VALUES ('',:imdbid,:msg)");
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);

$STH->execute();
echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";

或者使msg字段唯一。

使用存储过程:

DELIMITER //
 CREATE PROCEDURE insert_request_msg(IN `p_imbd`, IN `p_msg`)
    IF NOT EXISTS (SELECT COUNT(*) from requests WHERE imdbid = p_imbd)
    BEGIN
        INSERT INTO requests (id,imdbid,msg) VALUES ('',p_imbd,p_msg)
    END
    END IF; //
 DELIMITER ;

您可以在一个查询中调用它:

$STH = $DBH->prepare('
call insert_request_msg(:imdbid,:msg)
');
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);

答案 2 :(得分:1)

试试这个

$DBH = new PDO($dsn, $username, $password, $opt);

$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$STH = $DBH->prepare("INSERT INTO requests (id,imdbid,msg) VALUES ('',:imdbid,:msg) WHERE NOT EXISTS(SELECT imdbid FROM requests WHERE imdbid =:imdbid)");
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);

$STH->execute();
echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";

Source