2016-09-25 25 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'作为列标题和国家名称作为列值? –