5

これが私のデータベーススキーマです

+------------------+------------------+------+-----+---------------------+----------------+
| Field            | Type             | Null | Key | Default             | Extra          |
+------------------+------------------+------+-----+---------------------+----------------+
| phone_number     | varchar(64)      | NO   | UNI | NULL                |                |
| id               | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
+------------------+------------------+------+-----+---------------------+----------------+

一度に複数の電話番号( phone_numberは一意のキー)を挿入できるようにしたいのですが、重複している場合はauto_incrementフィールドをインクリメントしたくありません。

私が行った場合

INSERT INTO
   phone_numbers (phone_number) 
VALUES
   (
       % 
   VALUES
       % 
   )
   ON DUPLICATE KEY 
   UPDATE
      id = id;

auto_incrementは、重複している場合でも増加します。

この質問:MySQLの重複挿入で自動インクリメントを防止すると、 一括挿入は処理されません。私はこのようなことをしたいです:

INSERT INTO
   phone_numbers (phone_number) 
   SELECT
      '12345',
      '123456' 
   FROM
      DUAL 
   WHERE
      NOT EXISTS
      (
         SELECT
            phone_number 
         FROM
            phone_numbers 
         WHERE
            phone_number IN 
            (
               '12345',
               '123456'
            );

しかし、DUALテーブルは実際には複数の値をうまく処理しません。

何か案は?MySQL5.5。

4

3 に答える 3

3

他の記事を読んだ後、1​​つの方法は、一括挿入する一時テーブルを作成することです。次に、一時テーブルから実際のテーブルへの行を選択します。その時点で重複する行が削除され、実際のテーブルのauto_incrementフィールドは正しくなります。

CREATE TABLE PHONE_NUMBERS (id int(10) NOT NULL AUTO_INCREMENT, phone_number varchar(64), primary key (id), unique(phone_number) );

CREATE TEMPORARY TABLE TMP_PHONE_NUMBERS ( phone_number varchar(64), unique(phone_number) );

' bulk insert
INSERT INTO tmp_phone_numbers (phone_number) VALUES (%values%)

' remove phone numbers that already exist. This will create a unique
' set of phone numbers that do not exist in the real table.
DELETE FROM tmp_phone_numbers WHERE phone_number in (SELECT phone_number from phone_numbers);

' copy into real table
INSERT INTO phone_numbers (phone_number) SELECT phone_number FROM tmp_phone_numbers;

' Temp table is dropped when your connection is closed.

別のオプションは次のとおりです。

最初のバルクロードまたは後続のバルクロードでint(10)をヒットしないことがわかっている場合はINSERT INTO phone_numbers (phone_number) VALUES (%values%) ON DUPLICATE KEY UPDATE id=id;、idフィールドにギャップを残すために使用できます。ただし、一括読み込みが完了したら、ID列を削除してから再度追加すると、ギャップなしですべてのIDが再作成されます。

于 2012-11-10T01:43:44.347 に答える
0

INSERT IGNOREは(データに変更を加えていない場合でも)テーブルの自動インクリメントカウンターを増やすため、簡単な回避策は、トランザクションの最後に、次のエンジンロジックを利用して自動インクリメント値を復元することです。低すぎる値を強制しようとする場合、常に現在の最高のAI値よりも大きい整数を選択します。

ALTER TABLE phone_numbers AUTO_INCREMENT = 0;

これを行うにはテーブルの再構築は必要なく、次のようにテストできます。

SELECT MAX(id) FROM phone_numbers;
INSERT IGNORE INTO phone_numbers (phone_number) VALUES ("0123456789");
SELECT MAX(id) FROM phone_numbers;
INSERT IGNORE INTO phone_numbers (phone_number) VALUES ("0123456789");
SELECT MAX(id) FROM phone_numbers;
ALTER TABLE phone_numbers AUTO_INCREMENT = 1;
INSERT IGNORE INTO phone_numbers (phone_number) VALUES ("1000000000");
SELECT MAX(id) FROM phone_numbers;

+---------+
| MAX(id) |
+---------+
|    NULL |
+---------+
1 row in set (0.00 sec)

Query OK, 1 rows affected (0.00 sec)

+---------+
| MAX(id) |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+---------+
| MAX(id) |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)

Query OK, 1 rows affected (0.33 sec)
Records: 1  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)

+---------+
| MAX(id) |
+---------+
|       2 |
+---------+
1 row in set (0.00 sec)
于 2014-02-11T03:16:10.790 に答える
-2

INSERTIGNOREを使用するだけです。キーが重複しているために失敗した挿入は無視されます。残りのインサートは問題なく通過します。

于 2012-11-10T03:57:07.897 に答える