【问题标题】:adding data to interrelated tables..easier way?将数据添加到相互关联的表中……更简单的方法?
【发布时间】:2011-07-20 17:34:59
【问题描述】:

我对 mysql 有点生疏,并试图再次加入。如果这个问题太简单了,很抱歉。

我基本上创建了一个数据模型,其中包含一个名为“Master”的表,其中包含名称和 IDcode 的必填字段,然后是一个带有 IDcode 外键的“详细信息”表。

现在这里变得棘手了..我要进入:

INSERT INTO Details (Name, UpdateDate) Values (name, updateDate)

我收到一个错误:说详细信息上的 IDcode 没有默认值..所以我添加一个然后它抱怨字段“Master_IDcode”没有默认值

这一切都很有道理,但我想知道是否有任何简单的方法可以做我想做的事情。我想将数据添加到详细信息中,如果不存在 IDcode,我想在主表中添加一个条目。问题是我必须首先将名称添加到基金主控..等待生成一个唯一 ID(用于 IDcode),然后在我输入主数据时弄清楚并将其添加到我的查询中。您可以想象,由于我有很多表,因此查询可能会变得很长。

有没有更简单的方法?每次我添加一些东西时,如果外键存在,它会按名称搜索,如果不存在,它会在它链接到的所有表上添加它?人们这样做有标准的方式吗?我无法想象在所有复杂的数据库中人们还没有找到更简单的方法。

对不起,如果这个问题没有意义。如果需要,我可以添加更多信息。

附言这可能是一个不同的问题,但我听说过 Django for python,它有助于创建查询。它对我的情况有帮助吗?

提前非常感谢:-)

【问题讨论】:

  • 如果主记录不存在,为什么要插入子记录开始?我很难想象这种情况何时出现在 GUI 中。比如,加了一个朋友,突然发现你自己不存在?将产品添加到类别并发现您从下拉列表中选择的类别不存在?向您的公司添加员工后,您发现自己忘记了创建公司?
  • 嗨 Ronnis,这不是在 GUI 中使用的。它实际上是为了让我填充数据库。我得到了一个公司的大量详细信息列表,并将导入分解为几个不同的表。为了把所有东西放在一起,我决定创建一个主表,它只有一个名称和一个 ID 代码(这是大多数其他表的外键)。所以在这个表中,当它意识到主记录不存在时,我将一条记录添加到详细信息表中,我希望它可以创建一个。我想我需要在主数据库中搜索一个 ID,如果没有,则生成它,然后基于该添加详细信息行。
  • 如果文件中有数据,可以先将数据加载到中间表中(使用load data infile)。然后对表进行一次传递并“插入不存在的主表”。然后你知道所有masterID都存在,你可以继续“insert into detailX select ... from that_temp_table”。
  • 我想我明白你在说什么。有点创建一个临时表然后一旦它没问题我知道如何处理它然后复制它?我在数据库设计中看到过这种情况,但让我问你一个设计问题(因为我不擅长),这对性能有害吗?我得到的数据组织得非常整齐,我想我会检查文件的日期,如果它是新的,那么添加所有细节,否则就忽略它,如果不需要处理它就不要处理它。
  • @lostsoul,抱歉回复晚了。是的,暂存表方法执行得非常好!使用与其他表的连接来添加参考信息或过滤数据也变得很容易。也许我应该为所有这些添加一个答案:)

标签: mysql django foreign-keys foreign-key-relationship


【解决方案1】:

我认为没有一步法可以做到这一点。

我要做的是发出一个

INSERT IGNORE (..) values (..)

到主表,如果该行不存在,它将创建该行,或者什么都不做,然后发出一个

SELECT id FROM master where someUniqueAttribute = ..

另一种选择是存储过程/触发器,但它们在 MySQL 中仍然很新,我怀疑这是否有助于提高性能。

【讨论】:

    【解决方案2】:

    (决定在上面的cmets上展开,放到一个答案中)

    我建议在您的数据库中创建一组临时表(每个数据集/文件一个)。

    然后使用 LOAD DATA INFILE(或批量插入行)到这些临时表中。 确保在加载之前删除索引,并在加载数据后重新创建所需的内容。

    然后,您可以在临时表上进行一次传递,以创建缺少的主记录。例如,假设您的一个临时表包含一个应该用作 masterID 的国家/地区代码。您可以通过以下方式添加主记录:

    insert 
      into master_table(country_code)
    select distinct s.country_code 
      from staging_table     s
      left join master_table m on(s.country_code = m.country_code)
     where m.country_code is null;
    

    然后,您可以继续将行插入“真实”表中,因为您知道所有明细行都引用了有效的主记录。

    如果您需要与数据一起获取参考信息(例如翻译一些代码),您可以通过简单的连接来完成。此外,如果您想通过其他表过滤行,这现在也很容易。

    insert 
      into real_table_x(
              key
             ,colA
             ,colB
             ,colC
             ,computed_column_not_present_in_staging_table
            ,understandableCode
           )
      select x.key
            ,x.colA
            ,x.colB
            ,x.colC
            ,(x.colA + x.colB) / x.colC
            ,c.understandableCode
         from staging_table_x  x 
         join code_translation c on(x.strange_code = c.strange_code);
    

    这种方法非常有效,并且可以很好地扩展。上述变体通常用于数据仓库的 ETL 部分以加载大量数据。

    MySQL 的一个警告是它不支持哈希连接,这是一种非常适合完全连接两个表的连接机制。 MySQL 改为使用嵌套循环,这意味着您需要非常仔细地索引连接列。 InnoDB 表在主键上具有集群功能可以帮助提高效率。

    最后一点。当您在数据库中有暂存数据时,很容易添加一些数据分析并将“坏”行放在单独的表中。然后,您可以使用 SQL 检查数据,而不是在 yuor 编辑器中浏览 csv 文件。

    【讨论】:

    • 非常感谢 Ronnis,你解释得很好,我想我现在明白了。再次感谢..祝您有美好的一天!
    猜你喜欢
    • 2023-04-06
    • 2011-01-15
    • 2013-01-12
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2017-09-03
    相关资源
    最近更新 更多