Or11ConStraintRule
/********
# 파일명 : Or11ConStraintRule.sql
# 제약조건
# 설명 : 테이블 생성시 필요한 여러가지 제약조건에 대해 학습
********/
/*
[primary key : 기본키]
--참조무결성을 유지하기 위한 제약조건이다.
--하나의 테이블에는 하나의 기본키만 생성할 수 있다.
--기본키로 설정되면 그 컬럼은 값이 중복되거나 NULL값을 허용하지 않는다.
--즉 NOT NULL + UNIQUE의 의미를 가진다.
[UNIQUE : 유니크키]
- 값의 중복을 허용하지 않는 제약조건이다.
- 숫자, 문자 등의 데이터는 중복되지 않지만, NULL값에 대해서는 중복을
허용한다. 즉, 빈값(NULL)은 허용된다.
[Foreign key : 외래키]
--외래키는 참조무결성을 유지하기 위한 제약조건이다.
--만약 2개의 테이블이 외래키로 설정되어 있다면 부모테이블의
레코드는 삭제되지 않는다.
[NOT NULL]
--NULL 값을 허용하지 않는 컬럼을 의미한다.
--NOT NULL로 지정된 칼럼에 빈값을 입력하면 오류가 발생한다.
--주민번호, 회원ID와 같이 반드시 입력해야 하는 항목에 설정한다.
[Default]
--데이터 입력시 해당 컬럼에 아무값도 입력하지 않았을 때 자동으로 입력되는
값을 말한다. (제약명을 지정할 수 없다)
[check]
--Domain(자료형) 무결성을 유지하기 위한 제약조건으로 해당 컬럼에 잘못된
데이터가 입력되지 않도록 유지하기 위한 제약조건이다.
*제약조건을 확인하는 방법
select * from user_cons_columns
select table_name, constraint_name from user_constraints;
*/
--primary key(기본키)
/*
칼럼1을 기본키로 설정해야 한다면...
사용법1: 인라인방식
create table 테이블명(
컬럼1 자료형 [constraint PK제약명] primary key
);
사용법2: 아웃라인방식
create table 테이블명(
컬럼1 자료형,
[constraint PK제약명] primary key (컬럼1)
);
사용법3: 테이블 생성 후 별도로 기본키 지정방법
alter table 테이블명 add [constraint PK제약명]
primary key (컬럼1);
[]부분은 생략이 가능함. 생략할 경우 오라클이 임의로 이름을 지정함.
*/
--사용법1을 이용한 PX생성
create table tb_primary1(
student_id number(10) primary key,
name varchar2(30)
);
--사용법2를 이용한 PK생성
create table tb_primary2 (
student_id number(10) ,
name varchar2(30),
primary key (student_id)
);
--사용법3을 이용한 PK생성 : 테이블 생성후 alter명령어 이용
create table tb_primary3
(
student_id number(10),
name varchar2(50)
);
desc tb_primary3;
alter table tb_primary3 add constraint student_pk
primary key (student_id);
/* 제약조건 확인하기 */
select * from user_cons_columns;
select * from user_constraints;
/*
user_cons_columns : 테이블에 걸려있는 제약조건명과 컬럼명을 간단히
확인할 수 있다.
user_constraints : 테이블에 걸려있는 제약조건의 상세한 내용을
확인할 수 있다.
*user_constraints테이블의 constraint_type 플래그 설명
P : Primary key (기본키)
R : (Reference integrity) : Foreign key(외래키 or 참조키)
U : Unique(유니크)
C : Check, Not NULL
*/
insert into tb_primary1 (student_id, name) values (1, '홍길동');
insert into tb_primary1 values (1, '홍길동');/*
PK가 걸려있는 student_id에 중복된 값을 입력했기 때문.
*/
insert into tb_primary1 values (2, '홍길동');
select * from tb_primary;
insert into tb_primary1 values ('', '김길동');/*
ORA-01400: NULL을 ("HR"."TB_PRIMARY1"."STUDENT_ID")
안에 삽입할 수 없습니다
PK가 걸려있는 student_id에 빈값(NULL)을 입력했기 때문.
*/
update tb_primary1 set student_id='' where name='홍길동';
-- Unique(유니크)
/*
사용법 1:
create table 테이블명 (
컬럼명 자료형 unique
);
사용법 2:
create table 테이블명 (
컬럼1 자료형,
컬럼2 자료형,
[constraint FK제약명] unique(컬럼1, 컬럼2)
);
* unique는 2개이상의 컬럼에 적용할 수 있다.
*/
create table tb_unique1 (
member_id number(10) unique not null,
name varchar2(30),
telephone varchar2(20),
nickname varchar2(50),
unique(telephone, nickname)
);
insert into tb_unique1 (member_id, name, telephone, nickname)
values (1, '홍길동', '010-1111-1111', '쾌도길동이'); --입력됨
insert into tb_unique1 values(2, '홍길동', '010-2222-2222', ''); --입력됨
insert into tb_unique1 values(3, '최길동', '', ''); --입력됨
insert into tb_unique1 values(3, '박길동', '010-3333-3333', '박씨길동이');/*
member_id가 3인 레코드가 존재하므로 무결성제약조건 위반, 입력안됨
*/
insert into tb_unique1 values (4, '박길동', '010-3333-3333', '박씨길동이'); --입력됨
select * from tb_unique1;
update tb_unique1 set nickname='길동이최고' where name='홍길동';
update tb_unique1 set nickname='길동이최고'; --정상실행
update tb_unique1 set member_id = 1; --오류발생
/*
nickname과 telephone컬럼이 동일한 제약조건으로 설정 되었으므로
두개의 컬럼이 동시에 동일한 값을 입력받는 경우가 아니라면 중복값이
허용된다.
*/
update tb_unique1 set telephone= '010-9999-9999' , nickname='길동이최고'; --오류!
/*
tb_unique1 테이블을 생성할때 telephone, nickname은 동시에 unique를 생성했기
때문에 하나의 그룹처럼 생성된다.
*/
update tb_unique1 set telephone = '010-9999-9999', nickname ='업뎃오류'
where name = '홍길동'; --오류발생 : name이 홍길동인 레코드가 2개이므로....
/*
foreign key (외래키)
사용법 : 인라인방식
create table 테이블명
(
컬럼명1 자료형 primary key,
컬럼명2 자료형 [constraint 제약조건명] references 부모테이블
(부모테이블의 PK컬럼명)
)
사용법2 : 아웃라인방식
create table 테이블명
(
컬럼명1 자료형 primary key,
컬럼명2 자료형 ,
[constraint 제약조건명] foreign key (컬럼명2)
references 부모테이블 (부모테이블이 PK컬럼)
);
- 외래키 생성시 부모의 컬럼과 자료형은 반드시 일치해야 한다.
- 컬럼명은 달라도 상관없다.
- 외래키 생성시 on delete cascade 혹은 on delete set null 조건을 추가할 수 있다.
예] 컬럼명2 자료형2 references 부모테이블 (부모의 PK컬럼) on delete cascade
-> 부모 레코드 삭제시 지식레코드까지 같이 삭제됨
혹은
constraint 제약조건명 foreign key (컬렴명) references 부모테이블(부모의 PK컬럼)
-> 부모레코드 삭제시 지식레코드값이 null로 설정됨
*/
--외래키 설정하기
create table tb_foreign_key1
(
f_id number(10) primary key,
f_name varchar2(20),
student_id number(10)
constraint st_fk1 references tb_primary1(student_id)
);
update tb_primary1 set name = '이순신' where student_id = 1;
select * from tb_primary1;
insert into tb_foreign_key1 (f_id, f_name, student_id)
values (100, '이순신입니다', 1); -- 성공
insert into tb_foreign_key1 values(101, '김유신입니다.', 3);
/*
ORA-02291: 무결성 제약조건(HR.ST_FK1)이 위배되었습니다- 부모 키가 없습니다
부모키가 현재 1, 2번만 존재함. 3번은 없음
*/
insert into tb_foreign_key1
values (101, '홍길동니다', 2); -- 성공
insert into tb_foreign_key1
values (102, '홍길동일까요?', 2); -- 성공
delete from tb_foreign_key1 where f_id=100; --정상삭제됨
delete from tb_primary1 where student_id=1; /* 삭제되지않음
무결성제약조건 위배됨 */
/*
외래키가 걸려있는 2개의 테이블 사이에서 자식 테이블의 레코드를
삭제하려면 반드시 자식테이블의 레코드를 먼저 삭제 후에
부모테이블의 레코드를 삭제해야 한다.
*/
delete from tb_foreign_key1 where f_id=100;
delete from tb_primary1 where student_id=1;
--외래키설정하기(아웃라인방식)
create table tb_foreign_key2(
f_id number(10) primary key,
f_name varchar(50),
student_id number(10),
constraint dept_fkey2 foreign key (student_id)
references departments (department_id)
);
--제약조건확인
select * from user_cons_columns
where table_name = upper('tb_foreign_key2'); /*
레코드가 저장될 때 대문자로 저장되므로 upper() 함수를 이용하여
문자열을 대문자로 변경후 select해야 한다.
*/
--외래키 설정하기3(테이블 생성후 alter명령 이용하기)
create table tb_foreign_key3
(
f_id number(10) primary key,
f_name varchar(40) not null,
student_id number(10)
);
alter table tb_foreign_key3 add
constraint dept_fkey3 -- 제약조건명
foreign key(student_id) -- 외래키를 지정할 컬럼
references departments (department_id); /*
외래키로 지정된 컬럼이 참조할 테이블의 컬럼
*/
--데이터삽입하기
insert into tb_foreign_key3 (f_id, f_name, student_id)
values(1, '홍길동이',10); --정상입력
insert into tb_foreign_key3 (f_id, f_name, student_id)
values(2, '김길똥이',300); --제약조건위반 : 부서본호 300번은 존재하지 않음
select * from tb_foreign_key3;
-- not null : 공백을 허용하지 않겠다는 제약조건
create table tb_not_null
(
mem_idx number(10) primary key, -- PK 이므로 NN
mem_id varchar2(30) not null, -- not null 지정으로 NN
mem_pw varchar2(50) null, -- nulll허용(디폴트임)
mem_name varchar2(40) -- null을 허용하는 경우 비워두는 것이 일반적
);
desc tb_not_null;
insert into tb_not_null values(1, 'hong1', '1234', '홍길동');
insert into tb_not_null (mem_idx, mem_pw, mem_name)
values (2, '9999', '김유신'); --입력오류 : mem_id에 null값 입력
insert into tb_not_null values(NULL, '', '', ''); --입력오류
insert into tb_not_null (mem_idx, mem_id) values (2, 'Kang1'); --입력성공
/* default : 값을 입력하지 않았을 때 기본으로 입력되는 값 */
create table tb_default
(
name varchar2(30) not null,
pw varchar2(50) default 'qwer'
);
insert into tb_default values ('김길동', '1234'); -- 1234로 입력됨
insert into tb_default values ('최길동', ''); -- null값이 입력됨
insert into tb_default (name) values ('박길동'); --qwer이 입력됨
insert into tb_default values ('성길동' , default); --qwer이 입력됨
select * from tb_default;
/* check : 정해진 값만 입력해야 할 때 사용함 */
create table tb_check
(
gender varchar2(1) not null
constraint check_gender1
check (gender in ('M', 'F'))
);
insert into tb_check values ('M'); --입력성공
insert into tb_check values ('F'); --입력성공
insert into tb_check values ('Male'); --입력실패
insert into tb_check values ('여자'); --입력실패
select * from tb_check;
/*
-------17년 11월 08일-------
#제약조건
1. employees 테이블의 구조를 복사하여 pr_emp_sample 테이블을 만드시오.
복사된 테이블의 사원번호 칼럼에 “my_emp_pk” 라는 이름으로 “primary key” 제약조건을 지정하시오.
2. departments 테이블의 구조를 복사해서 pr_dept_sample 테이블을 만드시오.
부서번호에 “my_dept_pk” 라는 제약조건명으로 “primary_key”를 생성하시오.
3. pr_emp_sample 테이블의 부서번호 칼럼에 존재하지 않는 부서의 사원이
배정되지 않도록 외래키 제약조건을 지정하되 제약조건 이름은 “my_emp_fk”로 지정하시오.
4. pr_emp_sample 테이블의 커미션 칼럼에 0보다 큰 값만을 입력할수 있도록 제약조건을 지정하시오.
5. 위 3번에서는 두 테이블간에 외래키가 설정되어서 PR_DEPT_SAMPLE 테이블에서 레코드를 삭제할 수 없었다.
이 경우 부모 레코드를 삭제할 경우 자식까지 같이 삭제될수 있도록 외래키를 지정하시오.
*/
/* 1 테이블 구조 복사 */
create table pr_emp_sample as
select * from employees where 1=0;
/* 제약조건 */
alter table pr_emp_sample add constraint my_emp_pk
primary key (employee_id);
/*
풀이
create table pr_emp_sample
as
select * from employees where 1=0; -- 테이블의 구조만 복사
alter table pt_emp_sample add constraint my_emp_pk
primary key(employee_id); -- my_emp_pk라는 이름의 기본기를 생성
--제약조건 확인하기
select * from user_cons_columns where constraint_name=upper('my_emp_pk');
select * from user_constraints where constraint_name=upper('my_emp_pk');
*/
select * from pr_emp_sample;
/* 2 테이블 구조 복사 */
create table pr_dept_sample as
select * from departments where 1=0;
/* 제약조건 */
alter table pr_dept_sample add constraint my_dept_pk
primary key (department_id);
/*
풀이
create table pr_dept_sample as select * from departments where 1=0;
alter table pr_dept_sample add constraint my_dept_pk
primary key (department_id);
select * from user_cons_columns where constraint_name=upper('my_dept_pk');
*/
/* 3 칼럼에 존재하지 않는 부서사원이 배정되지 않도록 외래키 설정*/
alter table pr_emp_sample add
constraint my_emp_fk -- 제약조건명
foreign key(department_id) -- 외래키를 지정할 컬럼
references departments (department_id);
desc pr_emp_sample;
-- 풀이
--1,2에서 만들었던 기본키 삭제
alter table pr_emp_sample drop constraint my_emp_pk;
alter table pr_dept_sample drop constraint my_dept_pk;
-- 제약조건이 삭제되었는지 확인
select * from user_cons_columns where constraint_name=upper('my_emp_pk');
--외래키생성
alter table pr_emp_sample add constraint my_emp_fk
foreign key (department_id)
references pr_dept_sample (department_id);
ORA-02270: 이 열목록에 대해 일치하는 고유 또는 기본 키가 없습니다.
* 기본키를 삭제 후 외래키를 지정하면 위와같은 오류발생됨.
--위 1,2에서 기본키를 생성했던 쿼리문을 재실행
alter table pr_emp_sample add constraint my_emp_pk
primary key (employee_id);
alter table pr_dept_sample add constraint my_dept_pk
primary key (department_id);
--외래키 생성
alter table pr_emp_sample add constraint my_emp_fk
foreign key (department_id)
references pr_dept_sample (department_id);
-- 외래키 생성확인
select *
from user_constraints
where table_name = upper('pr_emp_sample');
select *
from user_constraints
where table_name = upper('pr_dept_sample');
select
pk.owner, pk.constraint_name, pk.constraint_type,
pk.table_name, pk.r_constraint_name,
fk.owner, fk.constraint_name, fk.constraint_type, fk.table_name
from
user_constraints pk , user_constraints fk
where
pk.r_constraint_name = fk.constraint_name and
fk.table_name = upper('pr_dept_sample')
;
-- pr_emp_sample 테이블에 레코드 삽입하기
insert into pr_emp_sample
(employee_id, first_name, last_name, email, hire_date,
job_id, department_id)
values
(100, '호옹', '길동', 'gildong@kosmo.com',sysdate,
'의적',10); --삽입 실패(부모테이블에 레코드 없기 때문)
--부모테이블인 pr_dept_sample에 departments 테이블의 레코드 복사하기
insert into pr_dept_sample select * from departments;
select * from pr_dept_sample;
--부모테이블에 레코드 삽입후 자식테이블에 레코드 삽입하기
insert into pr_emp_sample
(employee_id, first_name, last_name, email, hire_date,
job_id, department_id)
values
(100, '호옹', '길동', 'gildong@kosmo.com',sysdate,
'의적',10); --입력성공
--부모테이블에서 부서번호가 10인 레코드 삭제하기
delete from pr_dept_sample where department_id=10; /* 삭제안됨 -
자식레코드가 존재하기 때문
*/
delete from pr_dept_sample where department_id=20; -- 삭제됨
/* 4 */
ALTER TABLE pr_emp_sample
ADD CONSTRAINT commission_pct
CHECK (commission_pct > 0);
/*
풀이
alter table pr_emp_sample add -- constraint 제약조건이름
check (commission_pct > 0);
*/
alter table pr_emp_sample add -- constraint 제약조건이름
check (commission_pct > 0);
insert into pr_emp_sample
(employee_id, first_name, last_name, email, hire_date,
job_id, department_id)
values
(100, '호옹', '길동', 'gildong@kosmo.com',sysdate,
'의적',10); --입력성공 -- --check 제약조건 위반, 0보다 큰값이 입력되어야 함.
insert into pr_emp_sample
(employee_id, first_name, last_name, email, hire_date,
job_id, department_id)
values
(100, '호옹', '길동', 'gildong@kosmo.com',sysdate,
'의적',0.9);
/* 5 */
ALTER TABLE pr_emp_sample ADD CONSTRAINT my_emp_fk
FOREIGN KEY(department_id) REFERENCES pr_dept_sample (department_id) on delete cascade;
/*
풀이
*/
-- 제약조건삭제
alter table pr_emp_sample drop constraint my_emp_fk;
--외래키 재설정 : 부모레코드를 삭제할때 자식레코드도 같이 삭제될 수 있도록 설정
alter table pr_emp_sample add constraint my_emp_fk
foreign key (department_id)
references pr_dept_sample (department_id)
on delete cascade;
--부모레코드 삭제하기
select * from pr_emp_sample;
select * from pr_dept_sample;
delete from pr_dept_sample where department_id=10;/*
on delete cascade 조건으로 인해 부모레코드를 지우면
자식레코드까지 같이 삭제된다.
*/
'프로그래밍 > Oracle' 카테고리의 다른 글
Or13Privileges (0) | 2017.11.15 |
---|---|
Or12Sequenceindex (0) | 2017.11.15 |
Or10DML (0) | 2017.11.15 |
Or09DDL (0) | 2017.11.15 |
Or07Join (0) | 2017.11.15 |