0

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

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

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

编辑:原始插入已经在存储过程中!

4

2 回答 2

1

要执行此类操作,您需要将其放在存储过程本身中,但您必须构建条件逻辑,您无法在这样的单个查询中执行此操作。

你可以在你的存储过程中做这样的事情:

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 ;
于 2012-09-06T14:29:13.557 回答
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 触发器。(您需要测试以确保从 ON DUPLICATE KEY UPDATE 触发 AFTER 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?

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

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

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

于 2012-09-06T14:46:54.597 回答