Create a multicolumn index to enforce uniqueness

浪尽此生 提交于 2019-12-08 11:04:20

问题


I've got two fields in my table that if they(tat and dim) are equal I'm discarding them i.e

id| tat | dim | visible
1 | 11  | 22  | true
2 | 11  | 22  | false

This is considered not to be valid entry for ids 1 and 2 . Because I want to allow one dim per tat. So I have a script that cleaned these duplicates for me and after that I added index on this table to prevent this from happening like this :

CREATE UNIQUE INDEX dim_tat_idx
ON predictions (tat, dim);

As explained quite nicely in this answer:

https://stackoverflow.com/a/8918141/169277

Now going further in this case

This way you can enter (1,2), (1,3) and (1, NULL)
but neither of them a second time

What type of index would I create or what other mechanism would I use at the database level to allow entering 1, NULL combination but prevent (1,2) and (1,3) more times?


回答1:


This seems to be a misunderstanding.

Your quote from my answer is a bit misleading, since it only applies if you also create the additional partial index as described over there:
How to add a conditional unique index on PostgreSQL

If you do not add this second index (like you did not), you already have your solution, it would seem. With the multicolumn unique index alone, you can enter (1, NULL) multiple times, but (1,2) or (1,3) only once.

Empty strings

If, by mistake, you were considering empty strings ('') (for a character type) instead of NULL values: those are handled like any other value. You could deal with this situation using a multicolumn, partly functional unique index (index on an expression):

CREATE UNIQUE INDEX predictions _dim_tat_uni_idx
ON predictions (tat, NULLIF(dim, ''));

This way you can enter (1, 'a'), (1, 'b') only once.
But (1, NULL) and (1, '') multiple times.

Side effects

The index would still fully support plain queries on the first column (tat).
But queries on both columns would have to match the expression to utilize the full potential. This would be faster, even if it doesn't seem to make sense:

SELECT * FROM predictions
WHERE  tat = 1
AND    NULLIF(dim, '') = 'foo';

.. than this:

SELECT * FROM predictions
WHERE  tat = 1
AND    dim = 'foo';

.. because the first query can use both index columns. Result would be the same (except when searching for '' or NULL). Details in this related answer on dba.SE.



来源:https://stackoverflow.com/questions/18915759/create-a-multicolumn-index-to-enforce-uniqueness

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!