2012-02-25 40 views
2

我已经得到了下面的表格,其中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 
} 

我想要做的是填补translation与值从tmp_table。该translated场可以直接复制,但我不太清楚如何获取正确的language_id(tmp_table.langname可以用来确定language.id)和template_id(tmp_table.tplname,tmp_table.source,tmp_table.domain可以一起用于确定template.id)。

这可能是一个微不足道的问题,但我很新的SQL和不知道的最好的查询应该是填充translation表什么。有任何想法吗?

回答

4

这可以简化为:

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是巨大的,构成了目标表的一个大的比例,它可能更快,是删除所有索引目标表并随后重新创建它们创建索引从零开始的。 很多更快,然后逐行更新它们的每一行。

唯一索引另外用作限制,所以你必须考虑是否以后执行规则或者让它们保持原状。

+0

谢谢!不过,我对索引部分不太清楚。从Django模型生成的目标表,从pgadmin3看着它,它看起来像它得到了在每个外键索引创建(如:'CREATE INDEX translation_language_id的翻译使用的B树(LANGUAGE_ID);') - 你的意思是,在为了提高插入操作的性能,我应该在插入查询之前删除所有这些索引,然后用相同的'CREATE INDEX [']查询再次生成它们中的每一个? – 2012-02-26 18:11:29

+0

@DavidPlanella:的确如此。这也是安全的,因为查询的性质遵守外键规则。如果您担心并发操作,请在一次事务中完成所有操作。如果您不确定这会更快,只需在数据库副本中运行测试即可。 [EXPLAIN ANALYSE](http://www.postgresql.org/docs/current/interactive/sql-explain.html)可用于计时。 – 2012-02-27 11:34:00

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; 
+1

使用连接。这是非常难以阅读的。 http://hashmysql.org/wiki/Comma_vs_JOIN – 2012-02-26 02:48:08

1

我不熟悉的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) 

看起来像有人刚刚发布基本符合语法略有不同一样的答案,但要记住:如果在连接表从tmp_table的行不会得到插入一切,这不会确保你没有创建translation.id的副本中没有匹配langname声明或tplname(所以一定要确保你没有更多的运行比一次)。