2014-01-31 57 views
1

我有以下表格:Postrgersql + Django的:NULL值会导致IntegrityError:重复键值违反唯一约束

Column  |   Type    |       Modifiers       
----------------+-----------------------------+--------------------------------------------------------------- 
user_id   | bigint      | not null default nextval('employee_user_id_seq'::regclass) 
name   | character varying(50)  | not null              
phonenumber  | character varying(20)  | not null              
phonenumber2 | character varying(20)  |                
email   | character varying(75)  |  
Indexes: 
"employee_pkey" PRIMARY KEY, btree (user_id) 
"employee_email_key" UNIQUE CONSTRAINT, btree (email) 
"employee_phonenumber2_key" UNIQUE CONSTRAINT, btree (phonenumber2) 
"employee_phonenumber_email_key" UNIQUE CONSTRAINT, btree (phonenumber, email) 
"employee_phonenumber_key" UNIQUE CONSTRAINT, btree (phonenumber)               

在models.py:

class Employee(models.Model): 
    user_id = models.AutoField(primary_key=True) 
    name = models.CharField(max_length=50) 
    phonenumber = models.CharField(max_length=20, unique=True) 
    phonenumber2 = models.CharField(max_length=20, unique=True) 
    email = models.EmailField(blank=True, unique=True) 

使用Django我已经插入了没有phonenumber2的员工进入表格。它会顺利的事业,这是第NULL,则在第二次尝试第一次我得到的错误:

IntegrityError: duplicate key value violates unique constraint "employee_phonenumber2_key" 
DETAIL: Key (phonenumber2)=() already exists. 

从我的理解NULL不应被视为限制值,我想要实现的是同一电话号码或电话号码与电子邮件的组合不能为不同的员工复制。

我该如何解决这个问题?

+0

“models.py”。疯狂猜测,你使用的是Django? (这是一件很好的事,或者至少是标签)。 –

+0

@CraigRinger谢谢,我已经编辑了这个问题 –

回答

2

根本不是真的插入NULL,而是插入空字符串''。如果您插入了NULL,则无法获取您显示的错误。如果你想要一个唯一的约束来忽略NULL,你必须实际使用NULL

如果您检查PostgreSQL服务器错误日志,您将看到运行的查询;不过,您可能需要启用log_statement = all以获取所有详细信息。它将显示为''phonenumber2,而不是NULL

要决定性地证明这一点:

ALTER TABLE employee ADD CONSTRAINT phonenumber2_nonempty 
CHECK (phonenumber2 IS NULL OR length(phonenumber2) > 0); 

它会拒绝具有零个长度字符串的所有行。包括你已经添加的那个你认为是空的,所以添加检查约束将会失败。

您似乎在使用Django,通过提及“models.py”。 Django有IMO糟糕的观点,认为Python值None应该存储在字符字段中,如'',而不是NULL;它将''None都视为“空值”。 You can tell it to store None as NULL with Field.null。我不确定它是否会强制''存储为NULL;我希望没有,但没有经过测试。

+0

@liva建议一个新的问题,如果你在调查了一下后无法弄清楚它。我不使用Django。 –

相关问题