2015-07-22 6 views
0

У меня есть следующий фрагмент кода. Я хочу обновить внешний ключ , если существует соответствующий первичный ключ.Обновление внешнего ключа только при наличии первичного ключа

Пожалуйста, посмотрите на Query No: 2 и Запрос No: 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 и один для основного запроса.

ответ

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 колонке. В следующий раз, когда вы создадите запись из последовательности за столбцами id1 или id3, вы получите нарушение первичного ключа. Вся цель типа bigserial заключается в том, чтобы позволить PostgreSQL управлять значениями первичного ключа.

+0

Следующий вопрос. Помогает ли база данных анализировать запрос, если полный запрос указан как есть. Я имею в виду, если в основном запросе есть какие-то поля, которые зависят от find_rec. Я понимаю, что может быть прямой ответ, и это может зависеть. – gudge

+1

Если я правильно вас понимаю, ответ будет отрицательным. Планировщик запросов оценивает каждый новый запрос, который он встречает, и он выберет самый быстрый план, который он может собрать вместе. Обычно зависимости между подзапросами решаются эффективно, планировщик запросов обычно лучше всего знает. Что поможет планировщику запросов регулярно делать «ВАКУУМНЫЙ АНАЛИЗ» в вашей базе данных, потому что это генерирует статистику, которую использует планировщик запросов. – Patrick

Смежные вопросы