删除&在SQL PDO中插入或更新最佳实践

时间:2017-06-08 16:34:39

标签: php sql pdo

我正在尝试找到一个答案,这是遵循部分代码的最佳做法:

假设我对添加修改产品进行了一次操作

DELETE& INSERT

$product_id = 1;
$this->db->query("DELETE FROM `product_description` WHERE `product_id` = :product_id");
$this->db->bind(array(":product_id" => $product_id));
$this->db->execute();

$updateset = array(
    ":product_id" => $product_id,
    ":name" => $_POST["name"]
);
$this->db->query("INSERT INTO `product_description` SET `product_id` = :product_id, `name` = :name");
$this->db->bind($updateset);
$this->db->execute();

更新或插入

$product_id = 1;
$updateset = array(
    ":name" => $_POST["name"]
    ":product_id" => $product_id
);
$this->db->query("UPDATE `product_description` SET `name` = :name WHERE `product_id` = :product_id");
$this->db->bind($params);
$this->db->execute();
if(!$this->db->row_count()) {
    $this->db->query("INSERT INTO `product_description` SET `product_id` = :product_id, `name` = :name");
    $this->db->bind($updateset);
    $this->db->execute();
}

哪个更好?

2 个答案:

答案 0 :(得分:1)

两种选择都不好。

问题1:

他们都容易受到竞争条件的影响。另一个并发会话可能会在两个SQL语句之间的短暂时间内插入一行。

问题2:

在第二个解决方案中,如果UPDATE的行计数为零,则可能仍然存在匹配的行,因为当更新未更改行中的值时,它不会计算行数。

问题3:

如果您使用第一个选项,并且使用外键,则如果有任何子行引用您删除的行,则它将无效。由于子行的原因,删除将被阻止,否则您使用ON DELETE CASCADE,这意味着您将意外删除子行。

更好的解决方案:

为product_id定义UNIQUE约束。您的用法表明此列将是候选键(即每个product_id只能有一行)。

然后使用INSERT...ON DUPLICATE KEY UPDATE

$updateset = array(
    "product_id" => $product_id,
    "name" => $_POST["name"]
);
$this->db->query("INSERT INTO `product_description` 
    SET `product_id` = :product_id, `name` = :name
    ON DUPLICATE KEY UPDATE `name` = VALUES(`name`)");
$this->db->bind($updateset);
$this->db->execute();

提示:您的数组不需要使用:为列名添加前缀。这在PDO的早期版本中是必需的,但是它们改变了它,所以这不是多年来的要求。

答案 1 :(得分:0)

问题尚不清楚,但第二种选择看起来好多了。 主要原因是如果您的架构发展并且您的列数比现有的多,那么第一个选项将删除现有数据。

另一方面,第二个选项将确保任何现有数据都保存在您的数据库中。