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' )

ただし、その関数は、結果の行が重複キー例外をスローするかどうかに関係なく呼び出されます。ONDUPLICATEKEY句内でユーザー定義関数を参照することもできます。

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は、行が更新されたことを意味するため、必要なプロシージャを条件付きで呼び出すことができます。

行が挿入または更新されるたびにこれらのストアード・プロシージャーのアクションが呼び出されるようにしたい場合は、AFTERINSERTおよびAFTERUPDATEトリガーを検討してください。(AFTERUPDATEトリガーがONDUPLICATE 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;

Q:では、「更新」後、影響を受ける行数は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 に答える