【问题标题】:Sql UPDATE with automatical INSERT带有自动 INSERT 的 Sql UPDATE
【发布时间】:2016-05-26 08:46:47
【问题描述】:

我有这样的设置

CREATE TABLE Mother (
   id SERIAL PRIMARY KEY
);

CREATE TABLE Kitten (
   id SERIAL PRIMARY KEY AUTO_INCREMENT,
   mother_id INTEGER NULL REFERENCES Mother
);

Kitten 表已填满,其中一些提到了母亲,但有些没有。表格可能如下所示:

== Mother ==
| 1 |
| 2 |

== Kitten ==
| 1 | NULL |
| 2 |    1 |
| 3 | NULL |
| 4 |    2 |
| 5 |    1 |
| 6 | NULL |

现在(由于一些要求的变化)每只小猫都必须有一个刚刚创建的母亲。我尝试了以下不起作用

UPDATE Kitten
SET mother_id = (
  INSERT INTO Mother DEFAULT VALUES RETURNING id
)
WHERE mother_id IS NULL;

错误是

Fehler in der SQL-Abfrage: ERROR: syntax error at or near "INTO"
LINE 3: INSERT INTO Mother DEFAULT VALUES RETURNING id

使用 PosgreSQL 9.3.5

Auto-increment-Comment:“serial”和“primary key”的组合默认开启auto-increment

这里是创建描述的数据库状态的 sql:

drop table if exists Kitten;
drop table if exists Mother;

CREATE TABLE Mother (
  id SERIAL PRIMARY KEY
);

CREATE TABLE Kitten (
  id SERIAL PRIMARY KEY,
  mother_id INTEGER NULL REFERENCES Mother
);

insert into Mother default values;
insert into Mother default values;

insert into Kitten (mother_id) values (NULL);
insert into Kitten (mother_id) values (1);
insert into Kitten (mother_id) values (NULL);
insert into Kitten (mother_id) values (2);
INSERT INTO Kitten (mother_id) VALUES (1);
INSERT INTO Kitten (mother_id) VALUES (NULL);

【问题讨论】:

  • 您想为每只没有幼猫的小猫创建一个新妈妈吗? (所以根据您的样本数据有 2 个新妈妈),或者 只有一个 用于两只孤儿小猫的妈妈(这是您尝试使用的语法所建议的)
  • 是的,每只小猫都有一个新妈妈

标签: sql postgresql sql-update sql-insert


【解决方案1】:

如果您需要每只孤儿小猫一个妈妈,您可以执行以下操作:

with
  orphans as ( -- find the orphans and record their ids, ordered
    select id, row_number() over ()
    from kitten
    where mother_id is null
    ),
  newmothers as ( -- insert as many new mothers as needed, return new ids
    insert into mother
    select nextval('mother_id_seq')
    from orphans
    returning id
    ),
  newmothers2 as ( -- add row number for all new mother ids
    select *, row_number() over ()
    from newmothers
    )
update kitten k set
  mother_id = m.id
from orphans o
join newmothers2 m using (row_number) -- join orphans with new mothers
where o.id = k.id

【讨论】:

  • 我得到:错误:“来自”第 9 行或附近的语法错误:从孤儿中选择...我添加了一个 sql 片段来重现我的数据库
  • @Marcel 我更新了将motherid 替换为mother_id 的脚本。它适用于我的 PostgreSQL 9.5,我将检查代码的任何部分是否与 9.3 不兼容
  • @ZiggyCrueltyfreeZeitgeister pg-9.3 似乎不喜欢 insert into mother select from orphans 中的空列表
  • @joop 现在应该可以工作了,它现在使用序列的 nextval 而不是空列表插入
  • 这是唯一可能的解决方法,所以看起来(DEFAULT (VALUE) 也不起作用)
【解决方案2】:

我找到了一个适合我的纯 SQL 解决方案。它在母亲端使用一个临时列。

-- prepare situation (same like in the question)
DROP TABLE IF EXISTS Kitten; DROP TABLE IF EXISTS Mother;
CREATE TABLE Mother (id SERIAL PRIMARY KEY);
CREATE TABLE Kitten (id SERIAL PRIMARY KEY,mother_id INTEGER NULL REFERENCES Mother);
INSERT INTO Mother DEFAULT VALUES;INSERT INTO Mother DEFAULT VALUES;
INSERT INTO Kitten (mother_id) VALUES (NULL);INSERT INTO Kitten (mother_id) VALUES (1);INSERT INTO Kitten (mother_id) VALUES (NULL);INSERT INTO Kitten (mother_id) VALUES (2);INSERT INTO Kitten (mother_id) VALUES (1);INSERT INTO Kitten (mother_id) VALUES (NULL);

-- create temporarily "bidirectionality"
-- by creating a reference from mother to kitten
ALTER TABLE mother ADD kitten_id INTEGER;

-- create new Mothers for motherless kittens with reference to this kitten
INSERT INTO mother (kitten_id)
  (SELECT id FROM kitten WHERE mother_id IS NULL);

-- update kittens 
UPDATE kitten SET mother_id =
  (SELECT id FROM mother WHERE mother.kitten_id = kitten.id)
WHERE mother_id IS NULL;

-- remove temporary column
ALTER TABLE mother DROP kitten_id;

-- make sure this never happens again
ALTER TABLE kitten ALTER mother_id SET NOT NULL;

-- show results
SELECT kitten.id AS Kitten_Id , mother.id AS Mother_Id FROM kitten, mother WHERE kitten.mother_id = mother.id ORDER BY Kitten_id

【讨论】:

    猜你喜欢
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    相关资源
    最近更新 更多