我正在使用PostgreSQL(8.3+)并定义了枚举和表格如下:
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")
);
我还使用示例创建了一个存储过程,用于将新行插入到首选项表中 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;
我需要在upsert中添加一些额外的逻辑,以防止某些值覆盖其他值。具体做法是:
在伪代码中,这可能如下所示:
if (rating >= F) {
insert;
} else if (rating > existing_rating) {
insert;
} else {
return;
}
答案 0 :(得分:1)
在此表的INSERT OR UPDATE之前创建一个触发器。为此,您可以使用您的功能,只需稍作更改,例如将返回类型更改为TRIGGER。
在将行插入表之前触发BEFORE触发器,因此您可以在写入数据之前检查数据。
您可以在此处找到有关触发器的更多信息:
http://www.postgresql.org/docs/9.0/interactive/plpgsql-trigger.html
答案 1 :(得分:0)
要查看的方式是CASE
http://www.postgresql.org/docs/8.2/static/functions-conditional.html#AEN13066,实现它应该不那么困难。正如@ szymon-guz建议的那样,将其置于触发器中。
答案 2 :(得分:0)
你不能用案例陈述做点什么吗?
像这样。
--If new rating is greater than existing rating update it else update to current value.
UPDATE preferences
SET rating = CASE WHEN r > rating THEN r ELSE rating END;