【问题标题】:How to populate a table's foreign keys from other tables如何从其他表中填充表的外键
【发布时间】:2012-03-15 21:24:48
【问题描述】:

我有以下表格,其中translation 是空的,我正在尝试填写:

translation {
    id
    translated
    language_id
    template_id
}

language {
    id
    langname
    langcode
}

template {
    id
    tplname
    source
    domain
    total
}

要填充 translation 的源数据是我从外部 CSV 文件填充的临时表:

tmp_table {
    id
    translated
    langname
    tplname
    source
    domain
}

我想做的是用来自tmp_table 的值填充translationtranslated 字段可以直接复制,但是我不太清楚如何获取正确的language_id(tmp_table.langname 可以用来确定language.id)和template_id(tmp_table.tplname, tmp_table.source , tmp_table.domain 一起可以用来确定template.id)。

这可能是一个微不足道的问题,但我对 SQL 很陌生,不确定填充 translation 表的最佳查询应该是什么。有任何想法吗?

【问题讨论】:

    标签: sql database postgresql foreign-keys


    【解决方案1】:
    insert into translation (id, translated, language_id, template_id)
    select tmp.id, tmp.translated, l.id, t.id
      from tmp_table tmp, language l, template t
     where l.langname = tmp.langname
       and t.tplname = tmp.tplname
       and t.source = tmp.source
       and t.domain = tmp.domain;
    

    【讨论】:

    【解决方案2】:

    我对 PostgreSQL 不像其他 RDBMS 那样熟悉,但应该是这样的:

       INSERT INTO translation
       SELECT s.id, s.translated, l.id, t.id FROM tmp_table s
       INNER JOIN language l ON (l.langname = s.langname)
       INNER JOIN template t ON (t.tplname = s.tplname)
    

    看起来有人刚刚发布了基本相同的答案,但语法略有不同,但请记住:如果连接表中没有匹配的 langname 或 tplname,则根本不会插入 tmp_table 中的行,这不能确保您不会创建 translation.id 的副本(因此请确保不要多次运行它)。

    【讨论】:

      【解决方案3】:

      这可以简化为:

      INSERT INTO translation (id, translated, language_id, template_id)
      SELECT tmp.id, tmp.translated, l.id, t.id
      FROM   tmp_table tmp
      JOIN   language l USING (langname)
      JOIN   template t USING (tplname, source, domain)
      ORDER  BY tmp.id
      

      我添加了一个您并不需要的 ORDER BY 子句,但如果您以这种(或其他)方式插入集群数据,某些查询可能会受益。

      如果您想避免丢失在 languagetemplate 中找不到匹配行的行,请将两个表都设为 LEFT JOIN 而不是 JOIN(提供language_idtemplate_id 可以是 NULL

      除了我已经在prequel question下列出的内容:如果INSERT很大并且构成目标表的很大一部分,那么在目标表上DROP所有索引可能更快并在之后重新创建它们。从头开始创建索引要快很多,然后为每一行增量更新它们。

      唯一索引还用作约束,因此您必须考虑是稍后执行规则还是保留它们。

      【讨论】:

      • 谢谢!不过,我对索引部分不太清楚。目标表是从 Django 模型生成的,从 pgadmin3 中查看它,看起来它是在每个外键上使用索引创建的(例如 CREATE INDEX translation_language_id ON translation USING btree (language_id );) - 你的意思是为了提高插入操作的性能,我应该在插入查询之前删除所有这些索引,然后使用相同的CREATE INDEX [...] 查询再次生成每个索引?
      • @DavidPlanella:没错。这也是安全的,因为查询的性质遵守外键规则。如果您担心并发操作,请在一个事务中完成所有操作。如果您不相信这会更快,只需在您的数据库副本中运行测试即可。 EXPLAIN ANALYZE 可用于计时。
      猜你喜欢
      • 2012-07-09
      • 1970-01-01
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 2016-09-28
      相关资源
      最近更新 更多