2013-01-16 5 views
4

레코드가 업데이트 될 때 이전 값과 모순되는 값을 설정하지 못하게하려면 검사 제약 조건 (또는 다른 기술)을 사용할 수 있습니까?이전 값을 기준으로 열을 업데이트하지 못하도록하는 SQL 제약 조건

"file_exported"와 같은 일이 발생했음을 나타내는 NULL 타임 스탬프 일 수 있습니다. 파일이 반출되고 NULL이 아닌 값을 가지면 절대로 NULL로 설정해서는 안됩니다.

또 다른 예로 히트 카운터가 있습니다. 여기서 정수는 증가 만 허용되지만 결코 감소시킬 수는 없습니다.

그것이 내가 PostgreSQL을 사용하고,하지만 난 PostgreSQL의에서

+0

지금까지 조사한 바있으세요? –

+5

이것을 위해 트리거를 사용하는 것이 가장 좋습니다. 현재의 값이 null가 아닌지를 확인한 다음, null로 설정하려고하면 오류가 발생합니다. 역사적인 변경 로그가 필요하다면 직접 빌드해야합니다. –

+0

어떤 DBMS를 사용하고 있습니까? 신탁? PostgreSQL? –

답변

3

예를 들어, "file_exported"와 같은 이 발생했음을 나타내는 NULL 타임 스탬프 일 수 있습니다. 파일이 반출되고 NULL이 아닌 값을 가지면 절대로 NULL로 설정해서는 안됩니다.

다른 예로 히트 카운터가 있는데, 정수는 증가 할 수 있지만, 결코 감소시킬 수는 없습니다.

이 두 가지 경우 모두 단순히 이러한 변경 사항을 주석이 달린 테이블의 특성으로 기록하지 않습니다. '내 보낸'또는 '적중 횟수'는 관련 객체에서 직각으로 연결된 실제 세계 개념을 나타내는 뚜렷한 아이디어입니다.

그래서 그들은 단순히 서로 다른 관계가됩니다. 히트 카운터가 유사하게 다른 테이블

CREATE TABLE thing_file_exported(
    thing_id INTEGER PRIMARY KEY REFERENCES(thing.id), 
    file_name VARCHAR NOT NULL 
) 

: 우리는 단지 원하기 때문에 "file_exported"한 번 발생하는

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 
+0

디자인에있어서 매우 중요한 포인트입니다. – andyortlieb

+1

내 질문에 대한 대답이 아니지만 더 나은 질문에 대한 올바른 대답이기 때문에 받아 들여야합니다. – andyortlieb

+0

예제에 대한 올바른 답변이지만 질문에는 적합하지 않습니다. 또한 카운터를 감소시키고 내보내기 관계를 삭제할 수 있습니다. 이것은 받아 들여서는 안됩니다. – frostymarvelous

1

저장 프로 시저 및 함수가 모두 이전 및 새 값에 액세스 할 수있는 SQL 구현에 맞는 솔루션을보고 싶어하고, 그 코드에 액세스 할 수 있습니다 도움이된다면 임의의 테이블과 컬럼. 저장 프로 시저에 단순 (원유?) 유한 상태 시스템을 구축하는 것이 어렵지 않습니다. 그런 식으로 테이블 중심의 상태 머신을 구축 할 수도 있습니다.

4

트리거를 사용하십시오. 이것은 간단한 PL/PgSQL ON UPDATE ... FOR EACH ROW 트리거에 대한 완벽한 작업이며 NEWOLD 값을 모두 볼 수 있습니다.

trigger procedures을 참조하십시오.

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();