Mysql插入 - 如果密钥不重复,则执行两个操作

时间:2012-09-06 14:27:34

标签: mysql stored-procedures

有没有办法在mysql中做这样的事情:

INSERT INTO <sometable> SET 
someRow = inputSomeValue, someOtherRow = inputValue2 AND
call function1()
ON DUPLICATE KEY ID = inNewID AND
call function2();

基本上,我想在“clean”插入上调用一些外部mysql存储过程,如果插入被重复键阻塞,则调用其他一些过程。这可能在MySql中吗?

修改: 存储过程中的原始插入已经是ALREADY!

2 个答案:

答案 0 :(得分:0)

要做类似的事情,你需要在存储过程本身,但你必须建立条件逻辑,你不能在这样的单个查询中做到这一点。

您可以在存储过程中执行以下操作:

DELIMITER $$
DROP FUNCTION IF EXISTS `dbname`.`ConditionalInsert` $$
CREATE FUNCTION `dbname`.`ConditionalInsert` (inputSomeValueVARCHAR(20), inputValue2 VARCHAR(20), oldID INT(10), inNewID INT(10)) RETURNS INT
BEGIN
  DECLARE testval INT;
  DECLARE returnval INT DEFAULT 0;
  SELECT COUNT(1) INTO testval FROM dbname.sometable WHERE ID = oldID;
  IF testval = 0 THEN
    INSERT INTO dbname.sometable someRow, someOtherRow) VALUES (inputSomeValue, inputValue2);
    CALL function1();
    SET returnval = 1;
  ELSE
    UPDATE dbname.sometable SET ID = inNewID WHERE ID = oldID;
    CALL function2();
    SET returnval = 2;
  END IF;
  RETURN returnval;
END $$
DELIMITER ;

答案 1 :(得分:0)

没有。无法从INSERT语句调用存储过程。

有一种方法可以从INSERT语句调用存储的程序,但它必须是用户定义的函数,例如:

INSERT INTO sometable (col)
SELECT IF( user_defined_function() , 'abc' , 'abc' )

但是,无论生成的行是否抛出重复的键异常,都会调用该函数。也可以在ON DUPLICATE KEY子句中引用用户定义的函数。

INSERT INTO sometable (col1)
SELECT IF( user_defined_function() , 'abc' , 'abc' )
ON DUPLICATE KEY UPDATE col1 = IF( udf_duplicate() , VALUES(col1), VALUES(col1) )

请注意,使用这些结构存在二进制日志记录(行与语句)的问题,这些类型的语句可能不是“安全”进行复制。

所以我认为你真的不想采用这种方法。如果要插入单行,则最好执行INSERT ... ON DUPLICATE KEY UPDATE ...语句,然后检查受影响的行数。受影响的行值1将告诉您插入了一行,受影响的行值为2表示该行已更新,因此您可以有条件地调用所需的过程。

如果您总是希望在插入或更新任何行时调用这些存储过程中的操作,您可以考虑AFTER INSERT和AFTER UPDATE触发器。 (您需要进行测试以确保AFTER UPDATE触发器从ON DUPLICATE KEY UPDATE触发...在MySQL的旧版本中存在问题,其中未调用AFTER UPDATE触发器。)


编辑:

原始问题的最新更新指定此INSERT语句是在MySQL存储过程中执行的。

我会推荐这种方法:

DECLARE affected_rows INT;

INSERT INTO sometable (id,foo) VALUES (123,'bar')
ON DUPLICATE KEY UPDATE foo = VALUES(foo);

SELECT ROW_COUNT() INTO affected_rows;

IF affected_rows = 1 THEN
   CALL stored_procedure_after_insert(); 
ELSE
   CALL stored_procedure_after_update(); 
END IF;

问:那么,“更新”后受影响的行号将为0?

答:如果没有对任何行进行修改(通过INSERT ... ON DUPLICATE KEY UPDATE语句,则ROW_COUNT()函数将返回0.

如果没有插入行,并且更新了单行,则ROW_COUNT()函数将返回2.

获取0和2之间的区别在于是否实际修改了行。当更新结果导致行与行的当前内容相同时(“未进行更改”),则ROW_COUNT()返回0.如果更新导致对行的更改,则ROW_COUNT()将是2。