postgresql 跨列的唯一索引(不是这些列的组合)

2cmtqfgy  于 2022-12-03  发布在  PostgreSQL
关注(0)|答案(2)|浏览(107)

我有一个疑问:我们有一个表,其中有几个IP/端口对,我希望它们是全局唯一的,以避免使用此配置的流二进制文件中的串扰。
假设表如下所示

Create table config 
(
    Id serial NOT NULL,
    One_IP text,
    One_Port integer,
    Two_IP text,
    Two_Port integer
);

然后我可以添加约束

UNIQUE(One_IP, One_Port)

UNIQUE(Two_IP, Two_Port)

这让我走了很长一段路。不同行和每一组之间不会有串扰。
但这些是相互独立的-没有“一个”IP/端口对会重复,没有“两个”IP/端口对会重复,但我仍然可以有一个IP/端口与两个IP/端口相同(在相同或不同的行上)是否有办法创建一个约束,将它们组合起来?(不是简单的4列唯一)
如果我有这些行:
| 识别码|一个IP(_I)|一个端口(_P)|双IP(_I)|双端口(_P)|
| - -|- -|- -|- -|- -|
| 一个|239.1.1.12|二十一个|239.1.1.13|二十一个|
| 2个|239.1.1.12|二十二个|239.1.1.13|二十二个|
那么我就不能插入下面的任何一行...
| 识别码|一个IP(_I)|一个端口(_P)|双IP(_I)|双端口(_P)|
| - -|- -|- -|- -|- -|
| X射线|239.1.1.12|二十一个|239.4.5.6|四十四|
| X射线|239.1.1.12|二十二个|239.4.5.6|四十五|
| X射线|239.1.1.13|二十一个|239.4.5.6|四十六|
| X射线|239.1.1.13|二十二个|239.4.5.6|四十七|
| X射线|239.7.8.9|八十一|239.1.1.12|二十一个|
| X射线|239.7.8.9|八十二|239.1.1.12|二十二个|
| X射线|239.7.8.9|八十三|239.1.1.13|二十一个|
| X射线|239.7.8.9|八十四|239.1.1.13|二十二个|

ljo96ir5

ljo96ir51#

“column1 and column2 and ...”的任何变化都表示架构设计有问题。SQL中的列表由联接表表示。
另请注意,Postgres具有network address types

create table devices (
    id serial primary key
);

create table device_addresses (
    device_id int not null references devices(id),
    ip inet not null,
    port integer not null check(port > 0),

    unique(ip, port)
);

通过这种设计,设备可以拥有任意数量的地址,并且可以避免地址重复。
通过按设备ID分组并使用string_agg聚合所有地址,可以将单个设备的地址拉到一起。

select
  name,
  string_agg(ip || ':' || port, ', ') as addresses
from devices d
left join device_addresses da on d.id = da.device_id
group by d.id

Demonstration

nxagd54h

nxagd54h2#

也许您需要重新构建您的表

Create table config (
                Id serial NOT NULL,
                IP text,
                Port integer,
                OtherConfigID integer NULL)

这样,您就可以对IP和端口设置唯一的约束。
OtherPortID必须为NULL,以便在没有第二个端口配置的ID时可以插入第一个端口的详细信息,但实际上您将始终填充它。

相关问题