【问题标题】:Why does Postgres to throw a unique constraint violation on an empty table?为什么 Postgres 在空表上抛出唯一约束冲突?
【发布时间】:2014-03-10 04:14:38
【问题描述】:

好的,我有,在我看来这是一个非常奇怪的问题。我有一个使用以下 SQL 创建的 Postgres 表:

CREATE TABLE message
(
  message text,
  author integer,
  thread integer,
  id serial NOT NULL,
  "createdAt" timestamp with time zone,
  "updatedAt" timestamp with time zone,
  CONSTRAINT message_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
  ALTER TABLE message
  OWNER TO glenselle;

我正在使用 Sails.js(它使用 Waterline ORM)将消息模型保存到数据库中。请注意,在尝试隔离问题的过程中,每次尝试保存新记录时我都会开始丢弃表,并且行为始终相同。 ORM 正在为我做一些关联,以将作者与用户模型相关联,将线程与线程模型相关联。无论如何,当我尝试保存记录时,我首先得到的是:

ERROR:  duplicate key value violates unique constraint "message_pkey"
DETAIL:  Key (id)=(1) already exists.
STATEMENT:  INSERT INTO "message" ("message", "author", "thread", "id", "createdAt", "updatedAt") values ($1, $2, $3, $4, $5, $6) RETURNING *

所以这应该很容易理解。表中已经有一行 id 为 1,这就是违反“message_pkey”约束的原因。但具有讽刺意味的是,没有数据!所以我的问题是,如果表中绝对没有数据(它只是被删除并使用我上面发布的 SQL 重新创建),会发生什么导致 Postgres 引发唯一约束违规?

这是我为创建模型而运行的内容:

create: function(req, res) {
    var self = this;

    Thread.create({}, function(err, newThread) {
        if(err) return console.log(err);

        Message.create({message: req.body.conversation[0].message}, function(err, newMessage) {
            if(err) return console.log(err);
            // This returns an array of user ids
            sails.controllers.thread.parseUserIds(req.body.participants, req.user, function(idList) {

                // First, associate the message with the author
                newMessage.author = req.user.id;
                newMessage.save(function(err, savedMessage) {
                    if(err) return console.log(err);

                    // First, associate the participants with the thread
                    newThread.participants.add(idList);

                    // Next, associate the message with the thread
                    newThread.conversation.add(savedMessage);

                    newThread.save(function(err, savedThread) {
                        if(err) return console.log(err);

                        console.log('The thread looks to have been saved. Check it out!');
                        return res.json(savedThread);
                    });
                });
            });
        });
    });
},

【问题讨论】:

  • 您的config/bootstrap.js 文件中有任何内容吗?
  • 不...除了 cb();我认为这只是 Express 中的 next() 之类的默认回调?
  • 报错后,能不能去db里看看有没有记录?
  • postgresql.conf 中启用log_statement = 'all' 并查看是否有两个 语句正在运行,第二个语句失败。或单个多行插入。
  • 和/或发布您用来保存记录的代码...

标签: database postgresql sails.js waterline


【解决方案1】:

您正在尝试将模型实例传递给newThread.conversation.add,这是“创建和添加”的快捷方式。要将现有实例添加到集合中,您需要传递其 ID。将行更改为:

newThread.conversation.add(savedMessage.id);

它应该可以工作。

其他几点:

  1. 与其直接通过sails.controllers.thread.parseUserIds 访问控制器方法,不如考虑将该代码移至服务(在/api/services 中)文件夹中。服务由 Sails 自动全球化,并且可以从任何控制器访问。
  2. 如果您尝试将一组 ID 传递给newThread.participants.add,最终也会失败。您需要遍历数组并使用每个单独的元素调用add

可能会在不久的将来添加对 ID(以及传递现有实例对象)的支持,但我们不想让花里胡哨的东西延迟基线关联支持的发布。进行这些调整,您的代码现在应该可以工作了!

【讨论】:

    猜你喜欢
    • 2021-04-16
    • 1970-01-01
    • 2011-04-01
    • 2015-03-06
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多