RETURNING
절은 체인 쿼리 할 수 있습니다; 두 번째 쿼리는 첫 번째 쿼리의 결과를 사용합니다. (이 경우 동일한 행을 다시 만지는 것을 피하기 위해) (RETURNING은 postgres 8부터 가능합니다.4)
여기에 표시되는 기능에 포함하지만, 일반 SQL 작동, 너무
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE my_table
(updated_time timestamp NOT NULL DEFAULT now()
, updated_username varchar DEFAULT '_none_'
, criteria1 varchar NOT NULL
, criteria2 varchar NOT NULL
, value1 varchar
, value2 varchar
, PRIMARY KEY (criteria1,criteria2)
);
INSERT INTO my_table (criteria1,criteria2,value1,value2)
SELECT 'C1_' || gs::text
, 'C2_' || gs::text
, 'V1_' || gs::text
, 'V2_' || gs::text
FROM generate_series(1,10) gs
;
SELECT * FROM my_table ;
CREATE function funky(_criteria1 text,_criteria2 text, _newvalue1 text, _newvalue2 text)
RETURNS VOID
AS $funk$
WITH ins AS (
INSERT INTO my_table(criteria1, criteria2, value1, value2, updated_username)
SELECT $1, $2, $3, $4, COALESCE(current_user, 'evgeny')
WHERE NOT EXISTS (
SELECT * FROM my_table nx
WHERE nx.criteria1 = $1 AND nx.criteria2 = $2
)
RETURNING criteria1 AS criteria1, criteria2 AS criteria2
)
UPDATE my_table upd
SET value1 = $3, value2 = $4
, updated_time = now()
, updated_username = COALESCE(current_user, 'evgeny')
WHERE 1=1
AND criteria1 = $1 AND criteria2 = $2 -- key-condition
AND (value1 <> $3 OR value2 <> $4) -- row must have changed
AND NOT EXISTS (
SELECT * FROM ins -- the result from the INSERT
WHERE ins.criteria1 = upd.criteria1
AND ins.criteria2 = upd.criteria2
)
;
$funk$ language sql
;
SELECT funky('AA', 'BB' , 'CC', 'DD'); -- INSERT
SELECT funky('C1_3', 'C2_3' , 'V1_3', 'V2_3'); -- (null) UPDATE
SELECT funky('C1_7', 'C2_7' , 'V1_7', 'V2_7777'); -- (real) UPDATE
SELECT * FROM my_table ;
결과 :
updated_time | updated_username | criteria1 | criteria2 | value1 | value2
----------------------------+------------------+-----------+-----------+--------+---------
2013-03-13 16:37:55.405267 | _none_ | C1_1 | C2_1 | V1_1 | V2_1
2013-03-13 16:37:55.405267 | _none_ | C1_2 | C2_2 | V1_2 | V2_2
2013-03-13 16:37:55.405267 | _none_ | C1_3 | C2_3 | V1_3 | V2_3
2013-03-13 16:37:55.405267 | _none_ | C1_4 | C2_4 | V1_4 | V2_4
2013-03-13 16:37:55.405267 | _none_ | C1_5 | C2_5 | V1_5 | V2_5
2013-03-13 16:37:55.405267 | _none_ | C1_6 | C2_6 | V1_6 | V2_6
2013-03-13 16:37:55.405267 | _none_ | C1_8 | C2_8 | V1_8 | V2_8
2013-03-13 16:37:55.405267 | _none_ | C1_9 | C2_9 | V1_9 | V2_9
2013-03-13 16:37:55.405267 | _none_ | C1_10 | C2_10 | V1_10 | V2_10
2013-03-13 16:37:55.463651 | postgres | AA | BB | CC | DD
2013-03-13 16:37:55.472783 | postgres | C1_7 | C2_7 | V1_7 | V2_7777
(11 rows)
복제본 [삽입, 중복 업데이트 (postgresql)] 가능 복제본 (http://stackoverflow.com/questions/1109061/insert-on-duplicate-update-postgresql) –
아니요 복제본이 아닙니다. 대답은 기본적으로 위에서 작성한 함수로 캡슐화됩니다. – EMP