可以使用檢查約束(或某種其他技術)來防止在更新其記錄時設置與其先前值相矛盾的值。防止根據先前值更新列的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的? –