【问题标题】:Insert new row and get primary key or get primary key of existing record插入新行并获取主键或获取现有记录的主键
【发布时间】:2014-05-07 17:18:02
【问题描述】:

我在 Postgres 9.3 中有一个简单的标签表:

CREATE TABLE tag (
  id SERIAL PRIMARY KEY,
  text TEXT NOT NULL UNIQUE
);

目前我可以很容易地插入一个新标签并取回新的 id:

INSERT INTO tag (text) VALUES ('hey') RETURNING id

但是我想检查该标签是否不存在(唯一约束),如果它确实存在,则返回现有标签的 id。

我尝试使用COALESCE 来实现:

SELECT COALESCE(
    (SELECT id FROM tag WHERE text='hey'),
    (INSERT INTO tag (text) VALUES ('hey') RETURNING id)
)

但不幸的是,虽然我相信这个逻辑是合理的,但看起来我不能在 COALESCE 中包含 INSERT 语句(在 INTO 处生成语法错误)。

最简单的方法是什么?

【问题讨论】:

标签: sql postgresql postgresql-9.3


【解决方案1】:

这应该会给你同样的结果。如果该行不存在,则创建它。该部分执行后,该行肯定存在,我们选择它的id。

IF NOT EXISTS (SELECT id FROM tag WHERE text = 'hey')
BEGIN
    INSERT INTO tag (text) VALUES ('hey')
END
SELECT id FROM tag WHERE text = 'hey'

【讨论】:

  • 对不起,我不知道 PostgreSQL 和 MSSQL 的区别。我应该在回答之前调查一下。它对于某些平台 (MSSQL) 是有效的 SQL,因此请更具体地提出您的批评,以使其更具建设性。
  • 它可能是有效的T-SQL,但肯定是无效的SQL。 SQL 中没有IF 语句(也没有BEGIN 或END)。
  • 知道了。从原始帖子的语法中,我推断它是 t-sql 或 pl/sql。不想争论,只是解释。我以后会记住这一点的:)
【解决方案2】:

他的answer 归功于Clodoaldo Neto。

我把我的答案放在这里是因为虽然他的回答确实为我指明了方向,但它略有不同,我已经简化了一点。

WITH 
    existing AS (SELECT id FROM tag WHERE text='hey'),
    new AS (INSERT INTO tag (text) SELECT 'hey' WHERE NOT EXISTS (SELECT 1 FROM existing) RETURNING id)

SELECT id FROM existing UNION ALL SELECT id FROM new

【讨论】:

    猜你喜欢
    • 2012-09-02
    • 2013-08-10
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多