【发布时间】:2020-04-23 20:57:35
【问题描述】:
PostgreSQL 11.1
我已经为这个问题苦苦挣扎了很长时间。 (我已经尝试改进之前的问题)。
问题:一个人在表 tempA 中有两个不同的名字。每个名称在表 tempB 中都有其关联的记录。如何将与一个名称关联的所有记录移动到另一个名称,然后删除该名称?
示例:我有两个名字——“Tom”和“Bob”。我想将与“Bob”关联的所有记录更改为“Tom”,然后从数据库中删除“Bob”。
在将关联记录保留在表 tempb 中的同时如何做到这一点?
CREATE TABLE tempA
(
id serial PRIMARY KEY,
name text UNIQUE NOT NULL
);
CREATE TABLE tempb
(
id serial PRIMARY KEY,
tempa_id integer NOT NULL,
description text NOT NULL,
CONSTRAINT foo_bar_fk FOREIGN KEY (tempa_id)
REFERENCES tempa (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED
)
INSERT INTO tempA (name) VALUES('tom');
INSERT INTO tempA (name) VALUES('bob');
INSERT INTO tempB (tempA_id, description) SELECT id, 'test1' FROM tempA WHERE tempA.name = 'tom';
INSERT INTO tempB (tempA_id, description) SELECT id, 'test2' FROM tempA WHERE tempA.name = 'tom';
INSERT INTO tempB (tempA_id, description) SELECT id, 'test3' FROM tempA WHERE tempA.name = 'bob';
INSERT INTO tempB (tempA_id, description) SELECT id, 'test4' FROM tempA WHERE tempA.name = 'bob';
Initial set:
-- tempA
id name
1 "tom"
2 "bob"
id tempA_id description
1 1 "test1"
2 1 "test2"
3 2 "test3"
4 2 "test4"
我想要达到的目标是:
--Desired Results
-- tempA
id name
1 "tom"
-- tempB
id tempA_id description
1 1 "test1"
2 1 "test2"
3 1 "test3"
4 1 "test4"
这是我尝试过的,但仍然失败:
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
-- from 'tom' to 'bob' -- when all is done 'tom' must be the name to keep.
WITH _in (name1, name2) AS(
VALUES('tom','bob')
),
_bob AS( -- DELETING 'bob' record FROM tempA.
DELETE FROM tempA
USING _in
WHERE (tempA.name = _in.name2)
RETURNING tempA.*
)
UPDATE tempA -- REPLACING 'bob' with 'tom'. REPLACING 'bobs' id with 'toms' id.
SET name = _in.name1, id = _tom.id
FROM _in
JOIN _bob ON (_bob.name = _in.name2)
JOIN tempA _tom ON (_tom.name = _in.name1)
WHERE (tempA.id = _bob.id);
COMMIT;
错误:表“tempa”上的更新或删除违反了表“tempb”上的外键约束“foo_bar_fk” 详细信息:键 (id)=(2) 仍然从表“tempb”中引用。
在执行删除之前我似乎无法进行更新。
非常感谢任何帮助。 TIA
【问题讨论】:
标签: sql postgresql join sql-update sql-delete