MySQL如果存在则更新,不存在则插入到审核或日志表中

9
有没有一种方法可以实现这个?
INSERT IGNORE INTO some_table (one,two,three) VALUES(1,2,3)
ON DUPLICATE KEY (INSERT INTO audit_table VALUES(NOW(),'Duplicate key ignored')

我真的不想用PHP来完成这个 :(

谢谢!


1
我猜想“不行”,除非您使用存储过程来执行此逻辑。 - dma_k
3个回答

11

如果您考虑使用存储过程,可以使用 DECLARE CONTINUE HANDLER。下面是一个例子:

CREATE TABLE users (
    username    VARCHAR(30), 
    first_name  VARCHAR(30), 
    last_name   VARCHAR(30),
    PRIMARY KEY (username)
);

CREATE TABLE audit_table (timestamp datetime, description varchar(255));

DELIMITER $$
CREATE PROCEDURE add_user 
       (in_username    VARCHAR(30),
        in_first_name  VARCHAR(30),
        in_last_name   VARCHAR(30))
    MODIFIES SQL DATA
BEGIN
    DECLARE duplicate_key INT DEFAULT 0;
    BEGIN
        DECLARE EXIT HANDLER FOR 1062 SET duplicate_key = 1;

        INSERT INTO users (username, first_name, last_name)
               VALUES (in_username, in_first_name, in_last_name);
    END;

    IF duplicate_key = 1 THEN
        INSERT INTO audit_table VALUES(NOW(), 'Duplicate key ignored');
    END IF;
END$$
DELIMITER ;

让我们添加一些数据,试图插入重复的键:

CALL add_user('userA', 'Bob', 'Smith');
CALL add_user('userB', 'Paul', 'Green');
CALL add_user('userA', 'Jack', 'Brown');

结果:

SELECT * FROM users;
+----------+------------+-----------+
| username | first_name | last_name |
+----------+------------+-----------+
| userA    | Bob        | Smith     |
| userB    | Paul       | Green     |
+----------+------------+-----------+
2 rows in set (0.00 sec)

SELECT * FROM audit_table;
+---------------------+-----------------------+
| timestamp           | description           |
+---------------------+-----------------------+
| 2010-10-07 20:17:35 | Duplicate key ignored |
+---------------------+-----------------------+
1 row in set (0.00 sec)
如果在数据库层面上审计很重要,那么您可能希望仅授予EXECUTE权限,以便您的数据库用户只能调用存储过程。

存储过程或触发器(如MatTheCat所建议的)可以解决这个问题,但大多数托管提供商不会在他们的服务器上接受SP或触发器,我不知道为什么,可能是某种安全问题。 - analogic.al
@ricardocasares:我会把这看作是一个更换托管提供商的机会 :) - Daniel Vassallo
非常感谢你,Daniel!我会考虑更换托管服务;非常感谢你提供的优秀示例! - analogic.al

0

不确定这是否有效,但请查看MySQL的IF语句

伪代码

IF(SELECT id_key_index FROM tbl WHERE id_key_index = $index) THEN (UPDATE SECOND TBL);
    ELSE
      INSERT ...
    END IF;

0

ON DUPLICATE KEY 用于更新行,而不是插入到另一个表中,您必须根据第一个查询的结果使用两个查询。

编辑:您也可以使用触发器。


你需要根据第一个查询的结果使用两个查询。你能否进一步解释或给我一个例子呢? 非常感谢! - analogic.al
忘记了,你必须使用PHP ^^' 使用触发器或尝试Daniel的解决方案。 - MatTheCat
谢谢您的回复 Mat ;) - analogic.al

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接