有没有办法让这个唯一索引允许重复的行?我想也许有一些额外的空格字符,但我找不到它们。
=> select *, length(keyword), length(country), length(language) from keyword where id in (4588076, 4951423);
id | keyword | seed_id | source | search_count | country | language | volume | cpc | competition | modified_on | violation | revenue | length | length | length
---------+---------------------+---------+--------+--------------+---------+----------+--------+------+-------------+-------------+-----------+---------+--------+--------+--------
4588076 | power wallet review | | SPYFU | 0 | | | 70 | 0.11 | 0.31 | | | | 19 | |
4951423 | power wallet review | | SPYFU | 2 | | | 70 | 0.11 | 0.31 | | | | 19 | |
(2 rows)
Run Code Online (Sandbox Code Playgroud)
该指数是
"keyword_keyword_country_language" UNIQUE, btree (keyword, country, language)
Run Code Online (Sandbox Code Playgroud)
PostgreSQL 9.5.3
好的,我打算删除其他两列,但我想我会测试该keyword
列并发现:
=> select k1.id, k1.keyword, k2.id, k2.keyword, k1.keyword=k2.keyword from keyword k1, keyword k2 where k1.id=4588076 and k2.id=4951423;
id | keyword | id | keyword | ?column?
---------+---------------------+---------+---------------------+----------
4588076 | power wallet review | 4951423 | power wallet review | f
Run Code Online (Sandbox Code Playgroud)
答案可以在令人惊叹的文档中找到.. 看起来您的表中有 NULL 值.. 当数据库检查唯一性时,它会说“NULL 是否等于 NULL?NOPE!” 并允许它。
下面的重要一点(强调我的):
不允许。空值不被视为相等。多列唯一
如果您想保持所有三列的唯一性,同时将空值视为相等,那么您必须通过使它们成为部分索引来创造性地使用 UNIQUE 索引。
CREATE UNIQUE INDEX ix1 ON table (col1, col2wNull, col3wNull) WHERE col2wNull is not NULL and col3wNull is not Null;
CREATE UNIQUE INDEX ix2 ON table (col1, col2wNull) WHERE col2wNull is not Null and col3wNull is Null;
CREATE UNIQUE INDEX ix3 ON table (col1, col3wNull) WHERE col2wNull is Null and col3wNull is not Null;
CREATE UNIQUE INDEX ix4 ON table (col1) WHERE col2wNull is NULL and col3wNull is NULL;
Run Code Online (Sandbox Code Playgroud)
正如你所看到的......它很容易变得有点疯狂。
另一种替代方法是将 col2wNull 和 col3wNull 定义为 NOT NULL 并在不提供任何内容时提供一些默认值。这可能是也可能不是一个好主意,这取决于您在做什么。“魔法值”有给你以后带来很多问题的倾向。
关于您的编辑和两个字符串似乎相等,但数据库报告它们不是 - 我只能想象字符串中有一些“不可见”字符(UTF-8?)。或者它可以像一个字符串在末尾有一个额外的空间一样简单。这部分取决于您如何将其保存到数据库中。(您是否对它们执行了 trim()、lower() 等操作。)
您可以尝试以各种其他方式比较字符串(例如查看 md5 哈希)。我相信您也可以要求 postgres 将列值转换为十六进制以进行查看,但是目前我无法做到这一点(我很抱歉)。