我使用的PostgreSQL(8.3+)和如下所定義的枚舉和桌子的PostgreSQL的存儲過程:添加邏輯以
CREATE TYPE "viewer_action" AS ENUM ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H');
CREATE TABLE "preferences" (
"user_id" integer NOT NULL,
"item_id" integer NOT NULL,
"rating" viewer_action NOT NULL,
"time_created" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ("user_id","video_id")
);
我還創建了一個存儲過程來UPSERT新行插入偏好表,利用從 http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE的例子:
CREATE OR REPLACE FUNCTION add_preference(u INT, i INT, r viewer_action) RETURNS VOID AS $add_preference$
BEGIN
LOOP
-- first try to update the key
UPDATE preferences SET rating = r WHERE user_id = u AND item_id = i;
IF found THEN
RETURN;
END IF;
-- not there, so try to insert the key
-- if someone else inserts the same key concurrently,
-- we could get a unique-key failure
BEGIN
INSERT INTO preferences(user_id,item_id,rating) VALUES (u,i,r);
RETURN;
EXCEPTION WHEN unique_violation THEN
-- do nothing, and loop to try the UPDATE again
END;
END LOOP;
END;
$add_preference$ LANGUAGE plpgsql;
我需要一些額外的邏輯添加到更新插入,以防止覆蓋其他值的一些值。具體做法是:
- A可被B,其可以被C通過覆蓋,其可以通過d通過F.被覆蓋,等等,但是不能被由A覆蓋B,和C都以B,等覆蓋被覆蓋。
- 無論現有值是低還是高,F,G或H都可以覆蓋任何值。
僞代碼,這可能是這樣的:
if (rating >= F) {
insert;
} else if (rating > existing_rating) {
insert;
} else {
return;
}
plpgsql支持控制流。看起來好像你可以直接實現你的代碼。 – 2010-12-20 22:39:10