SQL to INSERT-DELETE将不相交的行导入MySQL?

时间:2014-11-03 07:13:09

标签: mysql

我有food_tableperson_table。然后我有第三个表格fav_food_table,使用food_idperson_id存储食物与人之间的关系。

当此人转到帐户信息并更新他喜欢的食物时,输入数据将作为选定food_id的数组传递给PHP(HTTP)脚本。一个人可以拥有多个fav_food,这种关系是一对多的。

更新fav_food_table的天真方法是从fav_food_table删除属于person_id的所有内容,然后重新插入所有行。因此,使用2个语句。

是否有一个声明可以做同样的事情?

PSUEDO代码:

CREATE TABLE food_table (food_id, food_name);
CREATE TABLE person_table (person_id, person_name);
CREATE TABLE fav_food (person_id, food_id);

2 个答案:

答案 0 :(得分:0)

person_tablefood_table之间存在m:n关系。这意味着您的关系表中有多个与同一个人相关的记录。当一个人更新他们喜欢的食物时,可能会出现四种独立病例的任意组合:

  1. 食物A之前很受欢迎,但不再是(DELETE FROM fav_food_table
  2. 食物B之前很受欢迎,现在仍然是! (什么都不做
  3. 食物C以前不是最喜欢的,但现在是最受欢迎的(INSERT INTO fav_food_table
  4. 食物D以前不是最喜欢的,但仍然不是最喜欢的! (什么都不做
  5. 要正确保持数据库的最新状态,您必须处理所有四种情况。案例2和4很容易被覆盖。只是不做任何事情:))

    这意味着,您必须至少执行两个步骤才能使数据库保持最新:1和3。

    您的目标似乎是减少必须执行的sql语句的数量。

    从表中删除一个人的所有收藏夹总是可以用一个语句来完成:

    DELETE
    FROM fav_food_table
    WHERE person_id = ?;
    

    要删除一个人的所选收藏夹,只需在AND food_id IN (?,?,?)子句中添加WHERE

    也可以使用single statement

    插入表格
    INSERT INTO fav_food_table (person_id,food_id)
    VALUES (?,?),
           (?,?),
           (?,?),
           .....;
    

    截至目前的摘要: 无论我们是否删除此人的所有旧记录然后插入所有新记录,或者我们是否只删除所选记录并插入新记录:我们可以用两个陈述来做到这一点!

    然而,在第二种情况下(" smart" case),我们不仅要知道关系的新状态,还要知道计算两者之间差异的旧状态。这将导致另外一个SELECT语句或需要一些智能"客户端" (PHP)逻辑。

    你的两步过程似乎并不天真,但对我来说简单有效。没有办法将此过程减少到少于两个语句。

    如果您想减少必须有效地将命令从PHP发送到服务器的次数,您可以查看mysqli_multi_query()或创建一个包含{{1}的存储过程}和DELETE语句。但最重要的是,这与执行两个查询本身是一回事。 您还可以查看MySQL Transactions以实现更安全的过程,并在以后发生错误时能够回滚INSERT命令。

答案 1 :(得分:-1)

我可以提出一些与众不同的建议。而不是删除,更新?

应该考虑删除共同的数据。无法检索删除数据。所以看看这个。

我们正在调整您的代码。

CREATE TABLE food_table (food_id, food_name);
CREATE TABLE person_table (person_id, person_name);
CREATE TABLE fav_food (person_id, food_id, fav_food_active); 
/* see the last column i added. It should be a bit type and can only hold the values 0 and 1. */

现在技术上每次都可以更新。无需删除值。这句话是

/* deletion */
UPDATE Fav_Food
SET fav_food_active = 0
WHERE food_id = (your food_id)
AND person_id = (your person_id)

/* activating it again */
UPDATE Fav_Food
SET fav_food_active = 1
WHERE food_id = (your food_id)
AND person_id = (your person_id)

所以现在你在这两个之间切换用于激活和删除它,而没有删除硬数据的后果。总之,你可以在你的代码中这样称呼它

SELECT *
FROM fav_food
WHERE (here your where clause on which you wanna search for)
AND fav_food_active = 1

请记住,当您在数据库中输入内容时,应始终将其添加为1.您可以将PHP myadmin中的内容添加为自动值,或在INSERT语句中对其进行硬编码。

我不确定你的后端代码是什么(好吧拿回来,它的PHP,我看了你的帖子)看着你通过数组拍摄所有内容的问题,但尝试使用foreach的一些检查fav_food条目,如果查询有问题,请先在数据库中检查。如果是,请更新它,如果没有,请插入它。让它在一个循环中运行。

类似

foreach ($food_id as $value){
    // check here the overal statement if it excists in your db
    // give back count
    if ($count == 1){
        // update query to delete it.
    }else{
        // create  your insert query here
    }
}

希望这会有所帮助。快乐的编码!