2012-02-25 65 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(所以一定要確保你沒有更多的運行比一次)。