不可以。不能从 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。