【问题标题】:Replacing existing record in MySQL or create new record without having Primary keys or Unique fields在没有主键或唯一字段的情况下替换 MySQL 中的现有记录或创建新记录
【发布时间】:2012-10-13 13:39:50
【问题描述】:

我正在使用 PHP,我需要在 MySQL 数据库中插入一条新记录,或者如果它存在,只需更新它。我读了几个答案,他们建议使用REPLACEINSERT...ON DUPLICATE KEY UPDATE,但是如果我很好理解,这两个选项意味着使用唯一字段或主键(这是唯一的)。在我的例子中,MySQL 表的值类似于:

Timestamp            | Query1   | Query2   | Result
-------------------------------------------------------- 
2012-10-13 08:15:27  | American | Men      | here result

2012-10-13 08:15:23  | American | Men      | result2

2012-10-13 08:15:27  | American | Women    | other result

2012-10-13 08:15:27  | German   | Men      | here result

因此我不能有主键或唯一字段,因为“query1”、“query2”和“Result”可以具有相同的值(例如,我可以有多个包含“American”(query1)和“Men”的字段的记录(query2) 和不同的结果。

目前我正在使用 PHP:

INSERT INTO results (Timestamp, Query1, Query2, Result) VALUES ('$current_timestamp', '$nationality', '$gender', '')

这只是追加所有记录并创建一个巨大的数据库。但是我想要实现的是在整个组合 query1&query2&result 不存在的情况下添加一条新记录。否则我只想更新“时间戳”字段。

例如,如果我的 PHP 脚本生成以下数据:

Timestamp            | Query1   | Query2   | Result
2012-10-13 08:15:23  | American | Men      | result2

并且数据库已经包含“American”&“Men”&“result2”的精确组合,然后只更新字段“timestamp”。否则,如果组合不同(例如“American”“Men”“result3”),则会将新记录添加到表中。

提前感谢您的帮助

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    即使没有像典型的 AUTO_INCREMENT 整数那样的单个 PRIMARY KEY 列,如果这三列是唯一的组合,您应该将它们定义为复合键。这不仅会保持唯一性,还会强制对它们作为一个单元进行索引。

    CREATE TABLE results (
      `Timestamp` DATETIME NOT NULL,
      `Query1` VARCHAR() NOT NULL,
      `Query2` VARCHAR() NOT NULL,
      `Result` VARCHAR() NOT NULL,
      /* Composite key across three columns */
      PRIMARY KEY (`Query1`,`Query2`,`Result`)
    );
    

    然后,您可以在插入时使用ON DUPLICATE KEY UPDATE 以中止键违规的插入并改为更新时间戳。

    INSERT INTO results (
       Timestamp, 
       Query1, 
       Query2, 
       Result
    ) VALUES (
       '$current_timestamp', /* see note below about NOW() */
       '$nationality', 
       '$gender',
       ''
    ) ON DUPLICATE KEY UPDATE `Timestamp` = '$current_timestamp';
    

    注意:我们假设 PHP 变量已经被正确转义了。

    注意2:如果$current_timestamp的值确实是当前时间戳而不是某个存储值,我建议使用MySQL的NOW()函数而不是传入PHP变量。

    ON DUPLICATE KEY UPDATE `Timestamp` = NOW()
    

    VALUES() 列表中的 $current_timestamp 也是如此...

    【讨论】:

      【解决方案2】:

      您可以使用“WHERE NOT EXISTS”子句,如下所示:

      INSERT INTO results (Timestamp, Query1, Query2, Result)
      SELECT '$current_timestamp', '$nationality', '$gender', '$result'
      FROM Dual
      WHERE NOT EXISTS (SELECT * 
          FROM results 
          WHERE Query1 = '$nationality' 
          AND Query2 = '$gender'
          AND Result = '$result'
        )
      

      这里的 Dual 是一个存根/假表,您可以在 mysql 中使用它来使查询在语法上正确。

      【讨论】:

      • -1,您在第 2 行有语法错误,您的答案与我的有何不同?
      • 我只是想帮忙,是的,我们找到了相同的解决方案,因为它是最明显的解决方案。现在,如果这让你对我投了反对票,那对你有好处,我可以接受。
      【解决方案3】:

      你可以像这样使用条件插入:

      INSERT INTO results (Timestamp, Query1, Query2, Result) 
      SELECT '$current_timestamp', '$nationality', '$gender', '$result'
          FROM DUAL
          WHERE NOT EXISTS (SELECT * FROM results
                               WHERE Query1 = '$nationality' 
                                 AND Query2 = '$gender'
                                 AND Result = '$result')
      

      dual是Oracle最初引入的特殊单列表

      来源:http://en.wikipedia.org/wiki/DUAL_table

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-18
        • 2017-12-24
        相关资源
        最近更新 更多