3

挿入/更新しようとしているSQLテーブルには次の定義があります。

CREATE TABLE `place`.`a_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`some_id` bigint(20) NOT NULL,
`someOther_id` bigint(20) NOT NULL,
`some_value` text,
`re_id` bigint(20) NOT NULL DEFAULT '0',
`up_id` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `some_id_key` (`some_id`),
KEY `some_id_index1` (`some_id`,`someOther_id`),
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;

ご覧のとおり、some_idとsomeOther_idはインデックスを共有しています。

次のような挿入/更新ステートメントを実行しようとしています。

INSERT INTO `a_table` (`re_id`,`some_id`,`someOther_id`,`up_id`,`some_value`) VALUES      
(100,181,7,101,'stuff in the memo wow') On DUPLICATE KEY UPDATE 
`up_id`=101,`some_value`='sampleValues'

idを指定しなかったので、挿入/更新ルールとしてインデックスキー(some_id_index1)にフォールバックすることを期待しています。ただし、挿入のみです。

明らかにこれは正しくありません。私はここで何が間違っているのですか?

4

3 に答える 3

7

OK、最初にあなたがより良い質問をするのを助けるために。「私はここで何が間違っているのですか?」というあなたの質問に対する文字通りの答え。なんでもない。

自動インクリメントの主キーと2つの一意でないセカンダリインデックスを持つテーブルがあります。主キーの値を指定せずにそのテーブルに行を挿入しているため、MySQLは自動インクリメントルールを使用して一意のキーを指定するため、ON DUPLICATE KEY条件がトリガーされることはありません。実際、それは冗長であると主張することができます。

ですから、あなたが自分自身に問いかけなければならない質問は、あなたは何が起こるべきだと思いますかということです。現在、Stack Overflowはフォーラムではないため、元の質問を明確にするために、この質問にコメントを追加して戻ってこないでください。代わりに、あなたが何を求めているのかを正確に答えようとしている人々に明確にする新しい質問を作成します。

私が見ているように、いくつかの可能性があります:

  1. セカンダリインデックスを一意になるように変更する必要があります。これを行うと、ルールがトリガーされ、ON DUPLICATE KEY更新に切り替わります
  2. 実際には、自動インクリメント列はまったく必要ないので、some_id実際には主キーにする必要があります
  3. データベースインデックスがどのように機能するかを理解していません(特に、データベースは通常、複数のインデックスを組み合わせたり、部分インデックスを使用してクエリを最適化できるため、セカンダリインデックスの少なくとも1つは不要である可能性が高いため、2番目のセカンダリインデックスの方が便利です。強制している特定の一意性制約がない限りsomeOther_id、フィールドのみのインデックス。たとえば、特定の特定の行が1つだけで、同じである複数の行が予想される場合は、2番目のセカンダリインデックスが必要になります。その場合、データベースが2番目を部分インデックスとして使用して同じパフォーマンスの最適化を実現できるため、最初の方法は使用できません)some_idsomeOther_idsome_id

コンピューターから離れた場所にペンと紙を持って座って、自分がやりたいことを正確に書き留めておくことをお勧めします。11歳]が理解できます。一枚の紙を細かく切り刻み、間違いなく一度に書き留められるまで捨てます。次に、コンピューターに戻って、今書いたものをコーディングしてみてください。

100回のうち99回は、他の人に質問することなく問題を解決するのに役立つことが実際にわかります。100回のうち99回は、問題自体の理解が不足しているためです。あなたの祖母または11歳の人にあなたの問題を(事実上)説明しようとすると、あなたはあなたを盲目にしているいくつかの仮定を捨てて、彼らが支払うのをやめたときにあなたが目を凝視する前に本当に速く問題の核心に到達することを余儀なくされます注意。[あなたが実際にあなたの祖母/11歳とペアプログラミングしていると言っているのではありません]

これが私があなたのために想像したそのような問題ステートメントの一例です。私はあなたの特定の問題が何であるかわからないので、それはおそらく間違っています:

We need a table that provides cross-reference notes about two other tables. 
There are different types of cross-reference (we use the column 're_id' to 
identify the type of cross-reference) and there are different types of notes 
(we use the columns 'up_id' as well as 'someValue') to store the actual notes.
The cross-reference is indicated with two columns 'some_id' which is the id
of the row in the 'some' table and 'someOther_id' which is the id of the row
in the 'someOther' table. There can be only one cross-reference between any one
row in the 'some' table and any one row in the 'someOther' table, but there can
be multiple cross-references from one specific row in the 'some' table to different
rows in the 'someOther' table.

上記の問題ステートメントを使用して、主キーを自動インクリメントから2列の主キーに切り替えて、(some_id,someOther_id)すべての主キーを削除します。

しかし、問題の説明は私の推測とは異なるため、実際の解決策は実際には異なる可能性があることを理解していただければ幸いです。

于 2012-10-22T10:01:25.940 に答える
3

MySQLドキュメントから

テーブルにAUTO_INCREMENT列が含まれINSERT ... UPDATE、行が挿入されている場合、LAST_INSERT_ID()関数は値を返しAUTO_INCREMENTます。ステートメントが代わりに行を更新する場合、LAST_INSERT_ID()は意味がありません。ただし、を使用してこれを回避できますLAST_INSERT_ID(expr)AUTO_INCREMENTidが列であると仮定します。更新をLAST_INSERT_ID()意味のあるものにするには、次のように行を挿入します。

INSERT INTO table (a,b,c) VALUES (1,2,3)
   ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
于 2012-10-22T09:39:43.727 に答える
1

同じクエリが正常に機能しています columns_value 。DUPLICATEKEYUPDATEを実際の列に変更してください some_value

フィドルデモ

問題は

テーブルのUNIQUE制約のみを列(up_id)に対して定義する必要があります。

unique constraint up_id列のテーブルを変更しました。

Fiddle_demo

于 2012-10-22T09:38:17.707 に答える