2016-09-25 60 views
0

我想根據國家/地區列中國家/地區名稱的逗號分隔字符串來更新一系列列表Country1Country2 ... Country 9。我有以下statment這樣做:如何使用多個條件的單條語句更新多列

cur.execute("\ 
      UPDATE t \ 
      SET Country1 = returnCommaDelimitedValue(Country,0),\ 
       Country2 = returnCommaDelimitedValue(Country,1),\ 
       ... 
       Country10 = returnCommaDelimitedValue(Country,9),\ 
      WHERE Country IS NOT NULL\ 
      ;") 

我也有我的田部命名爲Genre列。現在我想更新列表Genre1,Genre2 ... Genre9在同一個語句。我認爲該陳述看起來像這樣:

cur.execute("\ 
       UPDATE t \ 
       SET Country1 = returnCommaDelimitedValue(Country,0), Genre1 = returnCommaDelimitedValue(Genre,0)\ 
        Country2 = returnCommaDelimitedValue(Country,1), Genre2 = returnCommaDelimitedValue(Genre,1)\ 
        ... 
        Country10 = returnCommaDelimitedValue(Country,9), Genre10 = returnCommaDelimitedValue(Genre,9)\ 
       WHERE Country IS NOT NULL\ 
       AND Genre IS NOT NULL 
       ;") 

該陳述是否正確?

+1

這是可怕的表設計。你能改變它嗎? –

+0

不知道我能不能,爲什麼這麼可怕? –

+0

您的意思是'Genre1 = returnCommaDelimitedValue(Genre,0)'而不是'Genre1 = returnCommaDelimitedValue(Country,0)'? – redneb

回答

0

您應該運行2個單獨的update查詢。問題是Country可以獨立於Genre而爲空。因此,不過,如果將查詢中where子句中的條件Country IS NOT NULLGenre IS NOT NULL組合起來,則會錯過某些可能已更新的列,或者您將使用null值更新某些列。

現在我還沒有看到returnCommaDelimitedValue的執行。當字符串參數爲null時,它可能返回null。在這種情況下,您可以考慮完全刪除where子句並更新相同查詢中的countryNgenreN列。在這種情況下,如果Countrynull,這也會使Country1爲空,所以這可能是您想要的。如果幾乎所有行都有非nullCountryGenre,則此方法可能會更快。

+0

是的,有一個'Genre'列。感謝您指出含糊不清。老實說,我不確定是否需要'Genre IS NOT NULL'條件,但考慮到'returnCommaDelimitedValue(String,integer)'將String作爲參數,我認爲如果'Genre'字段可能會消除潛在的錯誤是空的。那有意義嗎? –

+0

我更新了我的答案。 – redneb

0

Country1,Country2,Country3 ...這是一個anti-pattern。你感覺非常糟糕的桌子設計的後果。不要覺得太放棄了,這是一種非常常見的反模式。在標準SQL中使用列表很困難且非常不直觀。整個混亂被稱爲「正常化」。

列表由join tables代表one-to-many relationship。其中一個t有很多國家。這是一個非常大的話題,但這裏是一個草圖。

而不是有國家1,國家2,國家3等等......在任何t是,我打算叫它東西,你會有一個名爲ThingCountries的表來代表列表。

create table ThingCountries (
    ThingID integer references Thing(id), 
    Country text 
); 

屬於物品的每個國家都會與物品的ID一起插入到ThingCountries中。

# Do this in a loop 
insert into ThingCountries (ThingID, Country) values (?, ?) 

它們會通過連接Thing.ID和ThingCountries.ThingID進行檢索。

select ThingCountries.Country from Thing 
join ThingCountries on Thing.ID = ThingCountries.ThingID 
where Thing.ID = ? 

通過查詢ThingCountries您可以快速找出哪些事情有一定的國家。

select ThingID from ThingCountries 
where Country = ? 

它們可以通過簡單的刪除來刪除。

delete from ThingCountries where ThingID = ? and Country = ? 

有沒有必要知道有多少國家列。沒有差距可以填補。對於有多少個國家可以擁有沒有限制。


後來在路上,您可能想要存儲有關每個國家/地區的信息,如名稱和縮寫。在這種情況下,你製作一張國家表。

create table Country (
    id integer primary key, 
    name text not null, 
    abbrev text not null 
); 

然後ThingCountries引用國家是由id而不是存儲國家名稱。

create table ThingCountries (
    ThingID integer references Thing(id), 
    CountryID integer references Country(id) 
); 

現在你可以存儲你想了解每個國家的任何信息,並防止輸入錯誤(因爲該國已經在全國表存在)。

對風格做同樣的事情,你的問題就消失了。

這有點尷尬,但這就是SQL如何做到的。最好習慣它。或者,某些數據庫提供陣列類型以使其更簡單,如Postgres arrays

更多閱讀:

+0

這是心靈彎曲,需要我花一段時間消化。謝謝。 –

+0

我需要看到這個概念的圖形表示來理解它。 –

+0

那麼你是說'ThingCountries'將'ThingID'作爲列標題和國家名稱作爲列值? –