如何在postgresql中表示元组数组?

时间:2016-09-13 10:28:56

标签: postgresql

这是我能想到的最简单的解释方法。想象一下,用户想要为一堆网页添加书签。有一个带有UrlID和实际网址的网址表。我希望用户有一个唯一的UrlID列表(但我不需要约束)和一个32位的int值,例如一个纪元日期。我关心的唯一两件事是:1)检查UrlID是否在此列表中; 2)获取整个列表并按日期(或第二个值)对其进行排序

如果它有帮助我预计不会超过8K书签,但最有可能是<128

1 个答案:

答案 0 :(得分:0)

如果你真的想避免额外的表来表达这种关系,你可以这样做:

CREATE TABLE "user" (
    id integer primary key,
    name text not null,
    bookmarks integer[] not null
);
CREATE TABLE url (
    id integer primary key,
    time timestamp with time zone not null,
    val text not null
);

然后找到特定用户的所有书签(比如id 66)会涉及到这样的事情:

SELECT url,time
FROM (SELECT bookmarks FROM "user" WHERE id=66) u
     JOIN url ON url.id=ANY(bookmarks)
ORDER BY TIME;

现在这就是我不喜欢这种架构的原因。首先,添加新书签需要重写书签数组,因此需要整个user行(因此,一个接一个地添加n个书签需要Θ(n^2)时间)。其次,您不能在数组的元素上使用外键。然而,许多查询将变得更复杂,例如,为了检索所有用户的所有书签,您必须执行以下操作:

SELECT "user".id,"user".name,url.val,url.time
FROM "user",
     LATERAL unnest((SELECT bookmarks)) b
     LEFT JOIN url ON b = url.id;

编辑:所以这是我将使用的架构,我认为最适合关系范式

CREATE TABLE "user" (
    id integer primary key,
    name text not null
);
CREATE TABLE url (
    id integer primary key,
    val text not null
);
CREATE TABLE bookmark (
    user_id integer not null REFERENCES "user",
    url_id integer REFERENCES url,
    time timestamp with time zone not null,
    UNIQUE (user_id,url_id)
);