Mysqli-handling-duplicates

提供:Dev Guides
移動先:案内検索

MySQLi-重複の処理

テーブルまたは結果セットに重複レコードが含まれることがあります。 許可される場合もありますが、重複するレコードを停止する必要がある場合もあります。 場合によっては、重複するレコードを識別してテーブルから削除する必要があります。 この章では、テーブルで重複レコードが発生するのを防ぐ方法と、既存の重複レコードを削除する方法について説明します。

テーブル内での重複の防止

適切なフィールドを持つテーブルで PRIMARY KEY または UNIQUE インデックスを使用して、重複レコードを停止できます。 一例を見てみましょう。次の表には、そのようなインデックスや主キーが含まれていないため、first_nameとlast_nameの重複レコードが許可されます。

CREATE TABLE person_tbl (
   first_name CHAR(20),
   last_name CHAR(20),
   sex CHAR(10)
);

同じ姓名の値を持つ複数のレコードがこのテーブルに作成されないようにするには、その定義にPRIMARY KEYを追加します。 あなたがこれを行うとき、プライマリキーはNULL値を許可しないため、NOT NULLであることをインデックス付きカラムとして宣言する必要もあります-

CREATE TABLE person_tbl (
   first_name CHAR(20) NOT NULL,
   last_name CHAR(20) NOT NULL,
   sex CHAR(10),
   PRIMARY KEY (last_name, first_name)
);

テーブルに一意のインデックスが存在すると、通常、インデックスを定義する列の既存のレコードを複製するテーブルにレコードを挿入すると、エラーが発生します。

*INSERT* ではなく *INSERT IGNORE* を使用します。 レコードが既存のレコードと重複しない場合、MySQLiは通常どおりレコードを挿入します。 レコードが重複している場合、IGNOREキーワードは、エラーを生成せずにサイレントに破棄するようMySQLiに指示します。

次の例ではエラーは発生せず、同時に重複レコードは挿入されません。

mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
   -> VALUES( 'Jay', 'Thomas');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
   -> VALUES( 'Jay', 'Thomas');
Query OK, 0 rows affected (0.00 sec)

INSERTではなく REPLACE を使用します。 レコードが新しい場合、INSERTと同様に挿入されます。 重複している場合、新しいレコードは古いレコードを置き換えます-

mysql> REPLACE INTO person_tbl (last_name, first_name)
   -> VALUES( 'Ajay', 'Kumar');
Query OK, 1 row affected (0.00 sec)

mysql> REPLACE INTO person_tbl (last_name, first_name)
   -> VALUES( 'Ajay', 'Kumar');
Query OK, 2 rows affected (0.00 sec)

INSERT IGNOREおよびREPLACEは、有効にする複製処理動作に従って選択する必要があります。 INSERT IGNOREは、重複レコードのセットの最初を保持し、残りを破棄します。 REPLACEは、一連の重複の最後を保持し、以前の重複を削除します。

一意性を強制する別の方法は、プライマリキーではなく、一意のインデックスをテーブルに追加することです。

CREATE TABLE person_tbl (
   first_name CHAR(20) NOT NULL,
   last_name CHAR(20) NOT NULL,
   sex CHAR(10)
   UNIQUE (last_name, first_name)
);

重複のカウントと特定

以下は、テーブル内のfirst_nameとlast_nameを持つ重複レコードをカウントするクエリです。

mysql> SELECT COUNT(*) as repetitions, last_name, first_name
   -> FROM person_tbl
   -> GROUP BY last_name, first_name
   -> HAVING repetitions > 1;

このクエリは、person_tblテーブル内のすべての重複レコードのリストを返します。 一般的に、複製された値のセットを識別するには、次を行います-

  • 重複する可能性のある値が含まれている列を判別します。
  • 列選択リストにそれらの列を、COUNT(*)とともにリストします。
  • GROUP BY句の列もリストします。
  • グループカウントを1以上にする必要があるため、一意の値を削除するHAVING句を追加します。

クエリ結果から重複を削除する:

SELECTステートメントとともに DISTINCT を使用して、テーブルで使用可能な一意のレコードを見つけることができます。

mysql> SELECT DISTINCT last_name, first_name
   -> FROM person_tbl
   -> ORDER BY last_name;

DISTINCTの代わりに、選択する列に名前を付けるGROUP BY句を追加します。 これは、重複を削除し、指定された列の値の一意の組み合わせのみを選択する効果があります-

mysql> SELECT last_name, first_name
   -> FROM person_tbl
   -> GROUP BY (last_name, first_name);

テーブル置換を使用した重複の削除

あなたがテーブルに重複したレコードがあり、そのテーブルからすべての重複したレコードを削除したい場合は、ここに手順があります-

mysql> CREATE TABLE tmp SELECT last_name, first_name, sex
   -> FROM person_tbl;
   -> GROUP BY (last_name, first_name);
mysql> DROP TABLE person_tbl;
mysql> ALTER TABLE tmp RENAME TO person_tbl;

テーブルから重複レコードを削除する簡単な方法は、そのテーブルにINDEXまたはPRIMAY KEYを追加することです。 このテーブルが既に利用可能な場合でも、この手法を使用して重複するレコードを削除でき、将来的にも安全です。

mysql> ALTER IGNORE TABLE person_tbl
   -> ADD PRIMARY KEY (last_name, first_name);