2012-09-06 22 views
0

有沒有辦法做這樣的事情在mysql中:Mysql的插入 - 兩個動作如果密鑰不重複

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

基本上,我想呼籲「乾淨」插入一些外MySQL的存儲過程,並且如果插入被重複密鑰阻塞,則調用其他一些過程。這在MySql中可能嗎?

編輯: 存儲過程中原始插入已經存在!

回答

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觸發器會從一個對重複密鑰更新解僱......有在舊版本的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(「no changes made」),則ROW_COUNT()返回0.如果更新導致行更改,則ROW_COUNT()將爲2.

+0

我喜歡這個編輯!那麼,「更新」後受影響的行號會是0? – guest86

+0

如果更新(單個)行,則ROW_COUNT()將爲2.如果更新導致該行「無更改」,則ROW_COUNT()將爲0。 – spencer7593

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 ; 
+0

插入是在存儲過程中,我編輯了我的帖子。抱歉! – guest86