相关疑难解决方法(0)

使用空列创建唯一约束

我有一个这种布局的表:

CREATE TABLE Favorites
(
  FavoriteId uuid NOT NULL PRIMARY KEY,
  UserId uuid NOT NULL,
  RecipeId uuid NOT NULL,
  MenuId uuid
)
Run Code Online (Sandbox Code Playgroud)

我想创建一个类似于此的唯一约束:

ALTER TABLE Favorites
ADD CONSTRAINT Favorites_UniqueFavorite UNIQUE(UserId, MenuId, RecipeId);
Run Code Online (Sandbox Code Playgroud)

但是,这将允许多行具有相同的(UserId, RecipeId)if MenuId IS NULL.我想允许NULLMenuId存储不具有关联菜单中的最爱,但我只希望每个用户/食谱对这些行中最多只有一个.

我到目前为止的想法是:

  1. 使用一些硬编码的UUID(例如全零)而不是null.
    但是,MenuId每个用户的菜单都有一个FK约束,所以我必须为每个用户创建一个特殊的"空"菜单,这是一个麻烦.

  2. 使用触发器检查是否存在空条目.
    我认为这是一个麻烦,我喜欢尽可能避免触发器.另外,我不相信他们能保证我的数据永远不会处于不良状态.

  3. 只需忘记它并检查中间件或插入函数中是否存在空条目,并且没有此约束.

我正在使用Postgres 9.0.

我有什么方法可以忽略吗?

sql postgresql null database-design referential-integrity

219
推荐指数
2
解决办法
8万
查看次数

SELECT或INSERT是否容易出现竞争条件?

我写了一个函数为一个简单的博客引擎创建帖子:

CREATE FUNCTION CreatePost(VARCHAR, TEXT, VARCHAR[])
RETURNS INTEGER AS $$
    DECLARE
        InsertedPostId INTEGER;
        TagName VARCHAR;
    BEGIN
        INSERT INTO Posts (Title, Body)
        VALUES ($1, $2)
        RETURNING Id INTO InsertedPostId;

        FOREACH TagName IN ARRAY $3 LOOP
            DECLARE
                InsertedTagId INTEGER;
            BEGIN
                -- I am concerned about this part.
                BEGIN
                    INSERT INTO Tags (Name)
                    VALUES (TagName)
                    RETURNING Id INTO InsertedTagId;
                EXCEPTION WHEN UNIQUE_VIOLATION THEN
                    SELECT INTO InsertedTagId Id
                    FROM Tags
                    WHERE Name = TagName
                    FETCH FIRST ROW ONLY;
                END;

                INSERT INTO Taggings (PostId, TagId) …
Run Code Online (Sandbox Code Playgroud)

sql postgresql concurrency upsert plpgsql

25
推荐指数
2
解决办法
8449
查看次数

复合PRIMARY KEY对涉及的列强制执行NOT NULL约束

这是我在Postgres中遇到的一个奇怪的,不需要的行为:当我使用复合主键创建Postgres表时,它会对复合组合的每一列强制执行NOT NULL约束.

例如,

CREATE TABLE distributors (m_id integer, x_id integer, PRIMARY KEY(m_id, x_id));
Run Code Online (Sandbox Code Playgroud)

强制NOT NULL列上的约束m_idx_id,我不想!MySQL没有这样做.我认为Oracle也不会这样做.

据我所知,PRIMARY KEY强制执行UNIQUENOT NULL自动执行但对单列主键有意义.在多列主键表中,唯一性由组合确定.

有没有简单的方法来避免Postgres的这种行为?
如果我执行这个:

CREATE TABLE distributors (m_id integer, x_id integer);
Run Code Online (Sandbox Code Playgroud)

NOT NULL当然没有任何限制.

postgresql null database-design unique primary-key

20
推荐指数
1
解决办法
1万
查看次数