如何检查mySQL数据库中的值是否存在?

3

我有一个mySQL数据库,有一个Perl脚本连接并进行数据操纵。其中一个表格如下:

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和Perl中都可以。

公司名称应该是主键的一部分,如果这样做,您就不会有问题。 - Mat
不错,马特。我在我的答案中加了这个作为选项2。 - Buttle Butkus
@Mat:在另一张表中,“company_id”是一个外键。如果我使用两个字段来创建主键,那么这张表就不再需要了。但是这样做会破坏数据库的规范化。我知道这不是绝对的规则,但作为一名优秀的开发者,我想要遵循这些规则。还有其他的想法吗?谢谢。 - Igor
如果我们能看到您的确切工作流程,那会很有帮助。从您的问题和一些评论中,我们并不清楚您需要改进的确切位置,只知道您关注一个额外的SELECT。(您是否只需要$dbh->{mysql_insertid}?) - pilcrow
@pilcrow 好的,我有另一张名为 investments 的表格,结构如下:CREATE TABLE investments(investment_id INT NOT NULL AUTO_INCREMENT, company_id INT, investor_id INT, ....); investments 表格有一个外键“company_id”。我需要将数据插入到“companies”表中,以具有唯一的名称,这样“investments”表才能有适当的外键值。我正在尝试查看是否有简单的解决方案,而不必多次访问数据库。 - Igor
我需要先检查公司表中是否存在该记录。如果存在,则检索现有公司名称的ID。如果不存在,则添加记录并获取最后一个ID。然后,使用检索到的公司ID将记录插入投资表中。谢谢。 - Igor
3个回答

4
“该脚本可以同时运行多次,因此我不能只将数据读入哈希表中,然后检查它是否已经存在。”
看起来您最担心的是脚本的一个实例在另一个脚本运行时插入了一个新的公司名称。 当这个公司名称不存在时,两个脚本都可能会检查数据库中是否存在该公司名称,然后它们可能都会插入数据,导致重复。
  1. Assuming I'm understanding your problem correctly, you need to look at transactions. You need to be able to check for the data and insert the data before anyone else is allowed to check for that data. That will keep a second instance of the script from checking for data until the 1st instance is done checking AND inserting.

    Check out: http://dev.mysql.com/doc/refman/5.1/en/innodb-transaction-model.html

    And: http://dev.mysql.com/doc/refman/5.1/en/commit.html

    MyISAM doesn't support transactions. InnoDB does. So you need to make sure your table is InnoDB. Start your set of queries with START TRANSACTION.

  2. Alternatively, you could do this, if you have a unique index on company_name (which you should).

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

    This will result in an error if the company_name already exists. Try a sample run attempting to insert a duplicate company name. In PHP,

    $result = mysql_query($query_string);
    

    $result will equal false on error. So,

    if(!$result) {
      $query2 = "INSERT INTO `other_table` (NULL,`$company_name`)";
      $result2 = mysql_query($query2);
    }
    

    If you have a unique key on company_name in both tables, then MySQL will not allow you to insert duplicates. Your multiple scripts may spend a lot of time trying to insert duplicates, but they will not succeed.

编辑:继续上面的代码,为了帮助你完成工作,如果插入成功,下面是你需要做的步骤。

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

  1. 我正在使用数据库进行一些事务插入操作。基本上,我在一个事务中向几个表格插入数据(7或8个表格),但只有3个需要在这个大事务中检查重复项。
  2. 正如我告诉Mat的那样,我不能将其作为主键的一部分,我只能将其设置为唯一。还有其他想法吗?谢谢。
- Igor
方案#2意味着我需要两次访问数据库:一次在插入时,另一次在选择时检索id(主键)。这并不是非常有效的方法。此外,随着时间的推移,表格会变得越来越大,对数据库的负载也会变得巨大。 - Igor
你是说你需要获取插入值的ID以在其他表中使用吗?这似乎令人难以置信,但实际上并不需要第二次数据库查询。如果这就是你的意思,请告诉我,我会在我的答案中添加它。 - Buttle Butkus
事务的想法是,如果在任何时候失败,数据库将恢复到其事务之前的状态。虽然我不确定嵌套事务,但你可以尝试上面的代码,看看它是否有效?你可以将数据库结构复制到测试数据库中,输入一些测试值并进行测试。你的问题似乎是你没有尝试任何潜在的解决方案。搜索“perl mysql last insert id”。从mysql中查看此内容:http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id - Buttle Butkus
没错,你不需要付费。希望这对你有用! - Buttle Butkus
显示剩余3条评论

0
我建议您编写一个存储过程(STP),以公司名称作为输入。 在此STP中,首先检查现有公司名称。 如果存在,则返回ID。 否则,插入并返回ID。这样,您只会访问数据库一次。

1
是的,但不能保证在同时运行2个脚本实例时避免重复插入。 - Buttle Butkus

0

对于InnoDB使用事务。对于MyISAM,锁定表,进行修改,解锁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接