仅在主键存在时更新外键

时间:2015-07-22 21:48:00

标签: database postgresql join updates

我有以下代码。我想更新一个外键 如果存在相应的主键。

请查看第2号查询和第3号查询。

DROP SCHEMA IF EXISTS s CASCADE;  
CREATE SCHEMA s;

CREATE TABLE s.t1 (
    "id1" BigSerial,
    "id2" BigInt,
    CONSTRAINT "pk1" PRIMARY KEY (id1)
)
WITH(OIDS=FALSE);    

CREATE TABLE s.t2 (
    "id3" BigSerial,
    "id4" Varchar UNIQUE NOT NULL,
    CONSTRAINT "pk2" PRIMARY KEY (id3)
)
WITH(OIDS=FALSE);

ALTER TABLE s.t1 ADD CONSTRAINT "fk" FOREIGN KEY (id2) REFERENCES s.t2 (id3) ON DELETE NO ACTION ON UPDATE NO ACTION;       

INSERT INTO s.t2 (id3, id4) VALUES (1, 'hello');
INSERT INTO s.t2 (id3, id4) VALUES (21, 'hello2');
INSERT INTO s.t2 (id3, id4) VALUES (31, 'hello3');
INSERT INTO s.t1 (id1, id2) VALUES (2, 21);
INSERT INTO s.t1 (id1) VALUES (3);

SELECT id1, id2 FROM s.t1;

UPDATE s.t1
SET id2 = (SELECT id3 FROM s.t2 WHERE s.t2.id4 = 'hello') WHERE s.t1.id1 = 2; 

SELECT id1, id2 FROM s.t1;

QUERY 2

UPDATE s.t1
SET id2 = (SELECT id3 FROM s.t2 WHERE s.t2.id4 = 'xyz') WHERE s.t1.id1 = 2
AND EXISTS (SELECT 1 FROM s.t2 WHERE s.t2.id4 = 'xyz');

SELECT id1, id2 FROM s.t1;

QUERY 3

UPDATE s.t1
SET id2 = (SELECT id3 FROM s.t2 WHERE s.t2.id4 = 'hello3') WHERE s.t1.id1 = 2
AND EXISTS (SELECT 1 FROM s.t2 WHERE s.t2.id4 = 'hello3');

SELECT id1, id2 FROM s.t1;

DROP SCHEMA s CASCADE;  

是否可以通过加入以有效的方式执行上述查询。我不希望两次调用基本相同的子查询。我目前正在这样做。一次用于EXISTS语句,一次用于主查询。

1 个答案:

答案 0 :(得分:0)

您可以使用CTE评估子查询一次,然后多次使用它:

WITH find_rec AS
  (SELECT id3 FROM s.t2 WHERE id4 = 'hello3')
UPDATE s.t1
SET id2 = find_rec.id3
WHERE id1 = 2
  AND EXISTS (SELECT 1 FROM find_rec);

更一般地说,您应该永远不要手动为bigserial分配值。下次从id1id3列后面的序列创建记录时,您将收到主键违规。 bigserial类型的全部目的是让PostgreSQL管理主键值。