Postgresql 复合唯一键(LastName、FirstName、MiddleName)不起作用?

Posted

技术标签:

【中文标题】Postgresql 复合唯一键(LastName、FirstName、MiddleName)不起作用?【英文标题】:Postgresql composite unique keys (LastName, FirstName, MiddleName) not working? 【发布时间】:2014-01-27 10:31:53 【问题描述】:

我在 Laravel (postgresql) 中有以下架构

Schema::create('members', function(Blueprint $table)
    
        $table->increments('id');
        $table->string('lname');
        $table->string('fname');
        $table->string('mname')->nullable();
        $table->string('ename', 10)->nullable();

        $table->unique(array('lname', 'fname', 'mname'));
    );

如您所见,我有一个由lnamefnamemname 组成的复合唯一键。但是我将mname 设置为nullable(),因为并非所有人都有中间名。

但是,当向数据库添加数据时(postgresql)

DB::table('students')->insert(
    array(
        array(
            'lname' => 'Last 1',
            'fname' => 'First 1'
        ),
        array(
            'lname' => 'Last 1',
            'fname' => 'First 1'
        )
    )
);

保存成功!我做错了吗?解决方法是什么?请帮忙。

【问题讨论】:

请显示您的 ORM / 任何抽象工具生成的实际表和约束,并且 实际 SQL 作为插入命令的结果运行。要获取表定义,请连接 psql 并运行 \dt members。对于 SQL,请从您的 ORM 查询日志中找出它。 请阅读kalzumeus.com/2010/06/17/… 并重新考虑此架构。 @CraigRinger 非常好的文章,但我相信他需要更好地理解 NULLS 的概念。使用名称作为键会在某些时候严重烧伤你。但是,不要否认一个人有奋斗和经历的特权吗? 当您尝试插入另一个叫 John Smith 的人时会发生什么? 【参考方案1】:

记住基本规则:

NULL!= NULL or NULL <> NULL

即使两者都有一个NULL 值,它们也无法进行比较,因为它们是未定义的。 NULL 不等于没有。 NULL 等于未定义。像这样想NULL 就像查克诺里斯,因为没有什么可以与查克诺里斯相提并论。

所以你的钥匙:

Last1 NULL First1
Last1 NULL First1 

独一无二,因为 NULLS 无法比较。

要使其正常工作,将 NULL 中间名默认为 '' 字符串或零长度字符串。

【讨论】:

小问题:正确的术语应该是 unknown 而不是 undefined。对于三值逻辑:真、假、未知 @Denis yes unknown 是正确的,但是 Chuck Norris 比较并不能很好地工作。

以上是关于Postgresql 复合唯一键(LastName、FirstName、MiddleName)不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 简单键与复合键

PostgreSQL中复合类型列子列的外键约束

使用 Django 的复合/复合主/唯一键

教义和复合唯一键

使用 sqlalchemy 的复合键关系

SQL Server + 复合键或唯一 ID