我已经阅读了UPSERTPostgreSQL 中的不同实现,但所有这些解决方案都相对较旧或相对奇特(例如,使用可写 CTE)。
而且我根本不是 psql 专家,无法立即找出这些解决方案是否过时,因为它们被很好地推荐,或者它们(好吧,几乎所有这些都是)只是不适合生产使用的玩具示例。
在 PostgreSQL 中实现 UPSERT 的最线程安全的方法是什么?
我有一张桌子:
CREATE TABLE mytable (id SERIAL, name VARCHAR(10) PRIMARY KEY)
Run Code Online (Sandbox Code Playgroud)
现在我想向这个表中添加名称,但前提是它们不存在于表中,并且在这两种情况下都返回id. 我怎样才能用 PostgreSQL 做到这一点?
我已经看到了一些用于此的脚本,但是没有单个 SQL 语句可以执行此操作吗?
例如,我可以插入并返回id:
INSERT INTO mytable (name) VALUES ('Jonas') RETURNING id
Run Code Online (Sandbox Code Playgroud)
它第一次工作并返回id。但是如果Jonas表中已经存在它会失败,但id即使插入失败我也想返回。这可能与PostgreSQL有关吗?
说我有表users,teams和teams_users结表(team_ID,user_ID/复合PK)。如果我想将用户添加到团队中,那么在性能/并发问题方面,最佳选择是什么?
首先查询表并查看关系是否已经存在,如果它只是通知发出请求的用户。
插入时,使用WHERE EXISTS语法(第二个示例)。
将 Postgres 9.5 Beta 用于 UPSERT 功能。(我想在学校项目中使用 Beta 版本不是一个坏主意吗?)。
在并发方面,哪种选择最好。我对 SQL 不是很有经验(只是 CRUD 应用程序的标准内容)。但据我所知,在第一个选项中,另一个用户可以在查询联结表之后但在自己实际插入关系之前插入关系。我想不会有任何重复项,因为我在该联结表中有一个复合主键,但我觉得让它成为例外并继续是不好的做法。此外,在我当前的代码中,在这种情况下我会返回 500 http 状态(因为 db 异常),这似乎并不正确。
我读过我可以通过“锁定”数据库/表来部分解决上述问题,但我不知道这是否是正确的方法。
最后,我不知道第二个选项是否存在竞争条件。