【问题标题】:How to check if the value in the mySQL DB exist?如何检查 mySQL DB 中的值是否存在?
【发布时间】:2012-01-27 05:53:40
【问题描述】:

我有一个 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 上产生额外的命中。

我试图寻找答案,但这里的每个问题或网络上的线程都在谈论使用主键检查。我不需要这个。数据库结构已经设置,但如果需要,我可以进行更改。该表将用作附加表。

还有其他方法吗?在 DB 和 Perl 中。

【问题讨论】:

  • 公司名称应该是主键的一部分,这样就没有问题了。
  • 好点,马特。我在答案中将其添加为选项 2。
  • @Mat: "company_id" 是另一个表中的外键。如果我使用 2 个字段创建主键,则不需要该表。但是它会破坏数据库规范化。我知道这不是教条,但作为一名优秀的开发人员,我想遵循这些规则。还有其他想法吗?谢谢。
  • 如果我们看到您的确切工作流程会有所帮助。从您的问题和您的一些 cmets 中,您并不清楚您需要改进的确切位置,只是您担心一个额外的 SELECT。 (你只需要$dbh->{mysql_insertid} 吗?)
  • @pilcrow 好的,我有另一个名为投资的表,其结构为:CREATE TABLE investment(investment_id INT NOT NULL AUTO_INCREMENT, company_id INT,investor_id INT, ....);投资表有一个外键“company_id”。我需要的是在“公司”表中插入具有唯一名称的数据,以便“投资”表可以具有适当的外键值。我正在尝试查看是否有一个简单的解决方案,而不需要过多地访问数据库。

标签: mysql perl dbi


【解决方案1】:

“该脚本可以同时运行多次,所以我不能只将数据读入哈希并检查它是否已经存在。”

听起来您最担心的是脚本的一个实例可能会在另一个脚本运行时插入新的公司名称。这两个脚本可能会在该公司名称不存在时检查数据库是否存在,然后它们可能都插入数据,从而导致重复。

  1. 假设我正确理解了您的问题,您需要查看交易。在允许其他人检查该数据之前,您需要能够检查数据并插入数据。这将阻止脚本的第二个实例检查数据,直到第一个实例完成检查和插入。

    查看: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);
    

    $result 将等于 false 出错。所以,

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

    如果您在两个表中的 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');
}

【讨论】:

  • 1.我正在与 DB 一起在一个事务中进行几次插入。基本上我在一个事务(7或8个表)内的几个表中插入数据,但只需要检查3个在这个大事务中检查重复项。 2. 正如我对 Mat 说的,我不能让它成为主键的一部分,我只能将它设置为唯一的。还有什么想法吗?谢谢。
  • 嗯,解决方案 #2 意味着我将访问数据库两次:一次在插入时,然后在选择时检索 id(主键)。这还不够。此外,表会随着时间的推移而增长,并且数据库上的负载将是巨大的。
  • 你是说需要获取插入值的id才能在其他表中使用?这似乎令人难以置信,但实际上并不需要第二次分贝命中。让我知道这是否是您的意思,我会将其添加到我的答案中。
  • 是的,我就是这个意思。我的意思是我将连续访问该表两次,对吧?
  • 那么你错了,因为你可以使用 mysql_insert_id() 来获取最后一个插入值的 id,然后你可以在下一个查询中使用它。请参阅我的编辑。顺便说一句,如果我解决了你的问题,请给我打勾,好吗?或者让我知道您还需要知道什么。
【解决方案2】:

对于 InnoDB 使用事务。对于MyISAM锁表,做修改,解锁。

【讨论】:

    【解决方案3】:

    我建议你写一个存储过程(STP),它把输入作为公司名称。 在此 STP 中,首先检查现有公司名称。如果存在,则返回 id。否则,插入并返回 id。

    这样,你只打 DB 一次

    【讨论】:

    • 是的,但不能保证在同时运行 2 个脚本实例的情况下避免重复插入。
    猜你喜欢
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    • 2011-06-16
    • 1970-01-01
    • 2015-11-07
    • 2014-04-10
    相关资源
    最近更新 更多