Sql 插入新行并获取主键或获取现有记录的主键

Sql 插入新行并获取主键或获取现有记录的主键,sql,postgresql,postgresql-9.3,Sql,Postgresql,Postgresql 9.3,我在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 COAL

我在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
中生成语法错误)


实现这一点最简单的方法是什么?

这应该会给你同样的结果。如果该行不存在,则创建它。在该部分执行之后,该行肯定会存在,我们选择它的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'
这是他的功劳

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

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

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