7

是否可以使用检查约束(或其他一些技术)来防止在更新记录时设置与其先前值相矛盾的值。

一个示例是 NULL 时间戳,表示发生了某些事情,例如“file_exported”。一旦文件被导出并具有非 NULL 值,就不应再次将其设置为 NULL。

另一个例子是命中计数器,其中整数只允许增加,但不能减少。

如果有帮助,我正在使用 postgresql,但我希望看到适合任何 SQL 实现的解决方案

4

4 回答 4

8

使用触发器。这是一个简单的 PL/PgSQLON UPDATE ... FOR EACH ROW触发器的完美工作,它可以同时看到NEWOLD值。

请参阅触发程序

于 2013-01-16T23:40:39.840 回答
3

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();
于 2014-03-18T00:15:24.273 回答
2

一个示例是 NULL 时间戳,表示发生了某些事情,例如“file_exported”。一旦文件被导出并具有非 NULL 值,就不应再次将其设置为 NULL。

另一个例子是命中计数器,其中整数只允许增加,但不能减少。

在这两种情况下,我根本不会将这些更改记录为带注释的表上的属性。'exported' 或 'hit count' 是一个独特的概念,代表与它们相关的对象相关但正交的现实世界概念:

所以他们只是不同的关系。因为我们只希望“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
于 2013-01-17T21:44:49.853 回答
1

PostgreSQL 中的存储过程和函数可以访问旧值和新值,并且该代码可以访问任意表和列。在存储过程中构建简单的(粗略的?)有限状态机并不难。你甚至可以用这种方式构建表驱动的状态机。

于 2013-01-16T22:18:22.847 回答