Not-Null constraints
- 기본적으로 데이터를 입력하지 않은 컬럼에는 null 값이 들어감
- 이러한 null을 허용하지 않고 반드시 값을 입력하도록 NOT NULL을 지정해줄 수 있음
- Primary key는 이 키워드를 지정하지 않더라도 적용되어있음
CREATE TABLE Stduio (
name CHAR(30) PRIMARY KEY,
address VARCHAR(255),
presCNo INT REFERENCES MovieExec(certNo) NOT NULL
);
Attribute-Based Checks
// presCNo가 10만 이상인 경우를 체크함
CREATE TABLE Studio (
name CHAR(50),
address VARCHAR(255),
presCNo INT REFERENCES MovieExec(certNo)
CHECK (presCNo >= 100000),
PRIMARY KEY (name)
);
// gender가 F 또는 N인지 체크함
CREATE TABLE MovieStar (
name CHAR(30)
PRIMARY KEY,
address VARCHAR(255),
gender CHAR
CHECK (gender IN ('F', 'N')),
birthdate DATE
);
- 외래 키의 참조와 CHECK를 통한 방법은 차이가 있음
- 외래키 참조는 presCNo와 certNo의 변경을 양방향으로 감지할 수 있음
- CHECK를 통한 방법은 presCNo의 변경만을 감지할 수 있음
CREATE TABLE Stduio (
name CHAR(50) PRIMARY KEY,
address VARCHAR(255),
presCNo INT REFERENCES MovieExec(certNo)
);
CREATE TABLE Stduio (
name CHAR(50) PRIMARY KEY,
address VARCHAR(255),
presCNo INT
CHECK(presCNo IN (SELECT certNo FROm MovieExec))
);
Tuple-Based CHECK Constraints
CREATE TABLE MovieStar (
name CHAR(30) PRIMARY KEY,
address VARCHAR(255),
gender CHAR(1),
birthdate DATE,
CHECK (gender = 'F' OR name NOT LIKE 'Ms.%')
);
Giving Name to Constraints
CREATE TABLE MovieStar (
name CHAR(30)
CONSTRAINT NameIsKey PRIMARY KEY,
address VARCHAR(255),
gender CHAR(1)
CONSTRAINT NoAndro CHECK (gender IN ('F', 'M')),
birthdate DATE,
CONSTRAINT RightTitle CHECK (gender = 'F' OR name NOT LIKE 'Ms.%')
);
Altering Constraints on Tables
ALTER TABLE MovieStar DROP CONSTRAINT NameIsKey;
ALTER TABLE MovieStar DROP CONSTRAINT NoAndro;
ALTER TABLE MovieStar DROP CONSTRAINT RightTitle;
ALTER TABLE MovieStar AND CONSTRAINT NameIsKey
PRIMARY KEY (name);
ALTER TABLE MovieStar ADD CONSTRAINT NoAndro
CHECK (gender IN ('F', 'M'));
ALTER TABLE MovieStar ADD CONSTRAINT NameIsKey
CHECK (gender = 'F' OR name NOT LIKE 'Ms.%');
Schema-Level Constraints and Triggers
Assertions
- 성능 문제로 인해 대부분이 DBMS는 지원하지 않음
- 아래와 같은 Assertion 시 Studio와 MovieExec을 조인 연산한 뒤 만들어진 모든 튜플에 대해 체크를 하게 됨
CREATE ASSERTION RichPres
CHECK (NOT EXISTS (SELECT *
FROM Studio, MovieExec
WHERE presCNo = certNo
AND netWorth < 10000000
)
);
DROP ASSERTION RichPres;
Oracle-Triggers
- 트리거는 보통 event-condition-action rules 또는 ECA rules라고 불림
- Event: 어떤 테이블의 SQL 문 입력의 발생을 나타냄
- Condition: Event가 발생했을 때 부가적으로 지정된 조건을 말함
- Action: Event가 일어났을 때 Condition을 부합한다면 실행되는 SQL 문을 말함
- 전체 트랜잭션 작업에 대해 발생되는 트리거와 각 행에 발생되는 트리거가 있음
// MovieExecTrig가 없으면 만들고 있다면 대체하는 문
// Studio에 INSERT 문이 실행된 후에
// 각 행에 대하여
// 새로 입력된 튜플의 presCNo가 10000 이상이라면
// MovieExec의 certNo 값을 presCNo 값으로 입력함
// MovieExec의 나머지 값은 default가 지정되어 있지 않다면 null로 채워질 것임
CREATE OR REPLACE TRIGGER MovieExecTrig
AFTER INSERT ON Studio
FOR EACH ROW
WHEN (new.presCNo > 10000)
BEGIN
INSERT INTO MovieExec(certNo)
VALUES(:new.presCNo);
END;
Triggers in SQL3
- Oracle Trigger와 SQL3 표준 문법은 거의 비슷함
PostgreSQL 트리거의 스페셜 변수
- TG_LEVEL: ROW or STATEMENT
- TG_OP: INSERT, UPDATE or DELETE
PostgreSQL 트리거 예시
- 예제 트리거는 다음을 보장함
- 테이블에 행이 삽입되거나 업데이트 됐을 때
- 작업을 수행하는 유저와 당시 시간이 행에 삽입됨
- employee의 name이 주어졌는지와 salary가 양수값인지를 확인함
CREATE TABLE emp(
empname text,
salary integer,
last_date timestamp,
last_user text
);
CREATE FUNCTION emp_stamp() RETURNS trigger AS $$
BEGIN
- check that empname and salary are given
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname cannot be null';
END IF;
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% cannot have null salary', NEW.empname;
END IF;
- Who works for us when she must pay for it?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
END IF;
- Remember who changed the payroll when
NEW.last_date := current_timestamp;
NEW.last_user := current_user;
RETURN NEW;
END; $$
LANGUAGE plpgsql;
CREATE TRIGGER emp_stamp
BEFORE INSERT OR UPDATE ON emp
FOR EACH ROW
EXECUTE PROCEDURE emp_stamp();
// salary 가 NULL 이므로 에러가 발생함
INSERT INTO emp VALUES ('Katie Couric', NULL, NULL, NULL);
// last_date와 last_user에는 current_timestamp, current_user가 삽입됨
INSERT INTO emp VALUES ('Katie Couric', 5000, NULL, NULL);
CREATE TABLE emp (
empname text NOT NULL,
salary integer
);
CREATE TABLE emp_audit(
operation char NOT NULL,
stamp timestamp NOT NULL,
userid text NOT NULL,
empname text NOT NULL,
salary integer
);
CREATE OR REPLACE FUNCTION process_emp_audit()
RETURNS TRIGGER AS $$
BEGIN
-
- Create a row in emp_audit to reflect the operation performed on emp,
- make use of the special variable TG_OP to work out the operation
-
IF (TG_OP = 'DELETE') THEN
INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*;
RETURN NEW;
END IF;
RETURN NULL; - result is ignored since this is an AFTER trigger
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER emp_audit
AFTER INSERT OR UPDATE OR DELETE ON emp
FOR EACH ROW
EXECUTE PROCEDURE process_emp_audit();
Uploaded by Notion2Tistory v1.1.0