可以使用检查约束(或某种其他技术)来防止在更新其记录时设置与其先前值相矛盾的值。防止根据先前值更新列的SQL约束
一个例子是一个NULL时间戳,指示发生了什么,如“file_exported”。一旦文件被导出并具有非NULL值,它不应该再次设置为NULL。
另一个例子是一个计数器,其中一个整数只允许增加,但不能减少。
如果它有助于我使用PostgreSQL,但我想看到适合任何SQL执行
可以使用检查约束(或某种其他技术)来防止在更新其记录时设置与其先前值相矛盾的值。防止根据先前值更新列的SQL约束
一个例子是一个NULL时间戳,指示发生了什么,如“file_exported”。一旦文件被导出并具有非NULL值,它不应该再次设置为NULL。
另一个例子是一个计数器,其中一个整数只允许增加,但不能减少。
如果它有助于我使用PostgreSQL,但我想看到适合任何SQL执行
一个例子是NULL时间戳表示发生了什么, 像“file_exported”。一旦文件被导出并且具有非NULL值,它不应再次设置为NULL。
另一个例子是一个计数器,其中一个整数只允许增加 ,但不能减少。
在这两种情况下,我都不会将这些更改记录为注释表上的属性; '出口'或'点击数'是一个独特的想法,代表了与它们相关的对象的相关但正交的现实世界概念:
所以它们只是不同的关系。因为我们只想要 “file_exported” 发生一次:
CREATE TABLE thing_file_exported(
thing_id INTEGER PRIMARY KEY REFERENCES(thing.id),
file_name VARCHAR NOT NULL
)
命中计数器同样是一个不同的表:
CREATE TABLE thing_hits(
thing_id INTEGER NOT NULL REFERENCES(thing.id),
hit_date TIMESTAMP NOT NULL,
PRIMARY KEY (thing_id, hit_date)
)
,你可能会与
SELECT thing.col1, thing.col2, tfe.file_name, count(th.thing_id)
FROM thing
LEFT OUTER JOIN thing_file_exported tfe
ON (thing.id = tfe.thing_id)
LEFT OUTER JOIN thing_hits th
ON (thing.id = th.thing_id)
GROUP BY thing.col1, thing.col2, tfe.file_name
这是设计中非常重要的一点。 – andyortlieb
这不是我的问题的答案,但我必须接受它,因为它是更好问题的正确答案。 – andyortlieb
这是例子的正确答案,但不是问题的关键。此外,您仍然可以递减计数器并删除导出关系。这不应该被接受。 – frostymarvelous
在PostgreSQL的存储过程和函数都可以访问两个新旧价值的解决方案,而且代码可以访问任意表和列。在存储过程中构建简单(粗糙的)有限状态机并不困难。你甚至可以用这种方式构建表驱动的状态机。
使用触发器。这对于一个简单的PL/PgSQL ON UPDATE ... FOR EACH ROW
触发器来说是一个完美的工作,它可以同时看到NEW
和OLD
的值。
lfLoop查询有最好的解决这个问题。但要继续使用触发器Craig Ringer的方法,这里是一个例子。本质上,您在更新之前将列的值设置回原始(旧)值。
CREATE OR REPLACE FUNCTION example_trigger()
RETURNS trigger AS
$BODY$
BEGIN
new.valuenottochange := old.valuenottochange;
new.valuenottochange2 := old.valuenottochange2;
RETURN new;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
DROP TRIGGER IF EXISTS trigger_name ON tablename;
CREATE TRIGGER trigger_name BEFORE UPDATE ON tablename
FOR EACH ROW EXECUTE PROCEDURE example_trigger();
到目前为止您是否研究过任何内容? –
可能最好使用触发器。检查当前值是否为null,如果尝试将其设置为null,则会引发错误。虽然如果你需要一个历史更改日志,你必须自己构建它。 –
你正在使用哪些DBMS?甲骨文? PostgreSQL的? –