2011-12-24 41 views
3

私はmySQLデータベースを持っており、それに接続してデータ操作を行うPerlスクリプトを持っています。 DB内のテーブルの 一つは、次のようになります。私は、この表にいくつかのデータを挿入したいmySQL DBの値が存在するかどうかを確認するには?

CREATE TABLE `mydb`.`companies` (
    `company_id` INT NOT NULL AUTO_INCREMENT, 
    `company_name` VARCHAR(100) NULL , 
    PRIMARY KEY (`company_id`)); 

。問題は、データ内の一部の企業が繰り返すことができるということです。

質問: "company_name"が既に存在することを確認するにはどうすればよいですか?存在する場合、私は "company_id"を取得し、それを使って別のテーブルにデータを挿入する必要があります。そうでなければ、この情報をこのテーブルに入力する必要がありますが、私はすでにこのコードを持っています。

ここにいくつかの追加要件があります:スクリプトは複数回同時に実行できるので、ハッシュにデータを読み込んで、それがすでに存在するかどうかを確認することはできません。

私は追加の "SELECT"クエリをスローすることができますが、それはDBに追加のヒットを作成します。

私は答えを探しましたが、ここでのすべての質問やウェブ上のスレッドはプライマリキーチェックの使用について話しています。私はこれを必要としません。 DB構造は既に設定されていますが、必要に応じて変更することができます。この表は追加の表として使用されます。

別の方法がありますか? DBとPerlの両方で。

+0

会社名はプライマリキーの一部である必要があります。そうした場合は問題はありません。 – Mat

+0

良い点、マット。私は私の答えにオプション2としてそれを追加しました。 –

+0

InnoDBまたはMyISAM? –

答えて

4

"スクリプトは同時に複数回実行できるので、ハッシュにデータを読み込んで、それがすでに存在するかどうかを確認することはできません。"

これは、スクリプトの1つのインスタンスが、別のスクリプトが実行されている間に新しい会社名を挿入する可能性があるというのが最大の懸念のようです。 2つのスクリプトは、存在しないときにその会社名の存在をDBでチェックし、その後両方でデータを挿入して重複する可能性があります。

  1. あなたの問題を正しく理解していると仮定すると、トランザクションを調べる必要があります。他の誰かがそのデータをチェックする前に、データをチェックしてデータを挿入する必要があります。これは、第1のインスタンスがチェックして挿入するまで、スクリプトの第2のインスタンスがデータをチェックするのを防ぎます。

    チェックアウト:http://dev.mysql.com/doc/refman/5.1/en/innodb-transaction-model.html

    そして:http://dev.mysql.com/doc/refman/5.1/en/commit.html

    のMyISAMはトランザクションをサポートしていません。 InnoDBはそうです。したがって、テーブルがInnoDBであることを確認する必要があります。 START TRANSACTIONで質問のセットを開始してください。

  2. また、company_nameにユニークなインデックスがある場合は、これを行うこともできます。

    $query_string = "INSERT INTO `companies` (NULL,'$company_name')"; 
    

    company_nameが既に存在する場合、これはエラーになります。重複した会社名を挿入しようとしたサンプルを実行してみてください。 PHPでは、

    $result = mysql_query($query_string); 
    

    $結果はエラー時に偽と等しくなります。したがって、

    両方のテーブルのcompany_nameに一意のキーがある場合、MySQLは重複を挿入することを許可しません。複数のスクリプトが複製を挿入するのに多くの時間を費やすことがありますが、成功しません。

上記のコードから引き続き、あなたの仕事をしています。ここでは、挿入が成功した場合のやり方を示します。

if(!$result) { 
    $query2 = "INSERT INTO `other_table` (NULL,`$company_name`)"; 
    $result2 = mysql_query($query2); 
} else if($result !== false) { // must use '!==' rather than '!=' because of loose PHP typing 
    $last_id = mysql_insert_id(); 
    $query2 = "UPDATE `other_table` SET `some_column` = 'some_value' WHERE `id` = '$last_id'"; 
    // OR, maybe you want this query 
    // $query2a = "INSERT INTO `other_table` (`id`,`foreign_key_id`) VALUES (NULL,'$last_id'); 
} 
+0

1.私は、DBと1つのトランザクションで2つの挿入を行っています。基本的には、1つのトランザクション(7または8テーブル)内のカップルテーブルにデータを挿入していますが、この大きなトランザクション内で重複をチェックする必要があるのは3つだけです。 2.私がマットに言ったように、それを主キーの一部にすることはできません。私はそれを一意にすることしかできません。他のアイデア?ありがとうございました。 – Igor

+0

さて、ソリューション#2は、私がDBに2回ヒットすることを意味します。一度挿入してからIDを取得するために選択します(主キー)。これだけでは十分ではありません。また、時間の経過とともにテーブルが大きくなり、DBの負荷が大きくなります。 – Igor

+0

他のテーブルで使用するために挿入された値のIDを取得する必要があると言っていますか?これは信じられないように思えるかもしれませんが、実際には2回目のdbヒットは必要ありません。これがあなたが意味することであれば教えてください。私はそれを私の答えに加えます。 –

0

入力を企業名として使用するストアドプロシージャ(STP)を作成することをお勧めします。 このSTPでは、まず既存の会社名を確認します。存在する場合は、idを返します。それ以外の場合は、idを挿入して返します。

この方法では、DBに一度だけヒットします。

+1

はい、ただし、スクリプトの2つのインスタンスが同時に実行されている重複挿入を避けることはできません。 –

0

InnoDB用トランザクションの場合。 MyISAMロックテーブルでは、変更を行い、ロックを解除します。

関連する問題