我正在尝试找到一个答案,这是遵循部分代码的最佳做法:
假设我对添加和修改产品进行了一次操作
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();
}
哪个更好?
答案 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)
问题尚不清楚,但第二种选择看起来好多了。 主要原因是如果您的架构发展并且您的列数比现有的多,那么第一个选项将删除现有数据。
另一方面,第二个选项将确保任何现有数据都保存在您的数据库中。