[oracle] 오라클 PL/SQL intro
오라클 PL/SQL intro
intro
0장 PL/SQL 살펴보기
Program?
- 해야 할 일을 미리 기술해 놓은 것.
- 인간의 언어
인간의 언어 ↓ translate(사람) 프로그래밍 언어 : C, Java, SQL, PL/SQL, HTML, ... ↓ translate(소프트웨어) 기계어
PL/SQL
- PLSQL = https://en.wikipedia.org/wiki/PL/SQL
- SQL = https://en.wikipedia.org/wiki/SQL#Procedural_extensions
- Pascal -> Ada -> PL/SQL
- SQL(Manipulating power) + 3GL(Processing power) = PL/SQL
- SQL 엔진 + PL/SQL 엔진
- 할당 연산자 vs 비교 연산자
function은 SQL에 포함시킬 수 있다는 점에서 procedure에 비해 유리한 점 있음
- 구조
Block Structured Language -> Anonymous block -> Named block : procedure, function, package, trigger, object, ...
--Anonymous block
declare --옵션
선언부
begin --필수 키워드
실행부
exception --옵션
예외처리부
end; --필수 키워드
/ --종결
--Named block
SOMETHING --옵션
선언부
begin --필수 키워드
실행부
exception --옵션
예외처리부
end; --필수 키워드
/ --종결
Anonymous Block 예제들
--plsql을 사용하여 Hello World 출력
set serveroutput on --화면 출력 기능 툴
begin
dbms_output.put_line('Hello World!'); --오라클 서버에 요청해서 화면에 출력
end;
/
--
begin
for i in 1..10 loop
dbms_output.put_line(i||'번째, Hello World!');
end loop;
end;
/
--begin 안에 select문, v_sal 변수를 넣기 위해 declare에 v_sal 변수 선언
declare
v_sal number;
begin
select sal into v_sal
from emp
where empno = 7788;
dbms_output.put_line(v_sal);
end;
/
Named Block 예제들
--plsql을 사용하여 Hello World 출력
create or replace procedure p1 --dbms()....을 p1에 저장
is
begin
dbms_output.put_line('Hello World!');
end;
/
col object_name format a30
select object_name, object_type
from user_objects
where object_type in ('PROCEDURE', 'FUNCTION', 'PACKAGE')
order by 2, 1;
col name format a30
col text format a80
select name, text
from user_source;
execute p1
--p1
create or replace procedure p1(a number)
is
v_sal number;
begin
select sal into v_sal
from emp
where empno = a;
dbms_output.put_line(v_sal);
end;
/
desc p1
exec p1(7788) --7788사원의 월급이 리턴 = 3000
--p2
create or replace procedure p2(a number)
is
begin
for i in 1..a loop
dbms_output.put_line(i||'번째, Hello world!');
end loop;
end;
/
desc p2
exec p2(100)
--p3
create or replace procedure p3(a number)
is
v_sal number;
begin
select sal into v_sal
from emp
where empno = a;
dbms_output.put_line(v_sal);
end;
/
exec p3(7788)
exec p3(7900)
문제. 부서번호를 입력하면 평균급여를 리턴하는 프로시져를 생성할 것
set serveroutput on
select * from emp;
create or replace procedure emp_avg_sal(a number) --헤더부분(변수(매개변수 데이터타입))
is
v_avg_sal number; --선언부(변수명 데이터타입)
begin
select avg(sal) into v_avg_sal
from emp
where deptno = a;
dbms_output.put_line(round(v_avg_sal, 2));
end;
/
show errors
exec emp_avg_sal(10)
exec emp_avg_sal(30)
--emp_avg_sal 프로시져에 out 매개변수를 사용할 경우
--첫번째 문장
set serveroutput on --세션이 종료 된 후 다시 시작하면 무조건 On 해야함.
create or replace procedure emp_avg_sal(a in number, b out number) --a 들어오는 매개변수, b 나가는 매개변수
is
begin
select round(avg(sal), 2) into b
from emp
where deptno = a;
end;
/
show errors
--두번째 문장
create or replace procedure emp_sal_compare(a number)
is
v_sal emp.sal%type;
v_deptno emp.deptno%type;
v_avg_sal number;
begin
select sal, deptno into v_sal, v_deptno
from emp
where empno = a;
emp_avg_sal(v_deptno, v_avg_sal);
if v_sal > v_avg_sal then
dbms_output.put_line('소속부서 평균 급여보다 급여 큼');
elsif v_sal < v_avg_sal then
dbms_output.put_line('소속부서 평균 급여보다 급여 적음');
else
dbms_output.put_line('소속부서 평균 급여보다 급여 같음');
end if;
end;
/
--첫번째 문장과 두번째 문장을 활용
exec emp_sal_compare(7788)
exec emp_sal_compare(7900)
--emp_avg_sal 프로시져를 함수로 변경할 경우
drop procedure emp_avg_sal;
create or replace function emp_avg_sal (p_deptno emp.deptno%type)
return number
is
b number;
begin --함수는 begin과 end 안에 return이 필요
select round(avg(sal), 2) into b
from emp
where deptno = p_deptno;
return b;
end;
/
- function은 SQL에 포함시킬 수 있다는 점에서
procedure에 비해 유리한 점 있음
select deptno, emp_avg_sal(deptno) avg_sal
from dept;
create or replace procedure emp_sal_compare(a number)
is
v_sal emp.sal%type;
v_deptno emp.deptno%type;
begin
select sal, deptno into v_sal, v_deptno
from emp
where empno = a;
if v_sal > emp_avg_sal(v_deptno) then
dbms_output.put_line('소속 부서 평균 급여보다 급여 큼');
elsif v_sal < emp_avg_sal(v_deptno) then
dbms_output.put_line('소속 부서 평균 급여보다 급여 적음');
else
dbms_output.put_line('소속 부서 평균 급여보다 급여 같음');
end if;
end;
/
show errors
exec emp_sal_compare(7788)
exec emp_sal_compare(7900)
문제. 급여가 높은 사원의 사번을 출력하는 함수를 만드세요.
--함수
drop procedure emp_sal_compare;
create or replace function emp_sal_compare(p_first_empno emp.empno%type, p_second_empno emp.empno%type) --매개변수 앞에는 일반적으로 p_NAME
return emp.empno%type
is
v_first_sal emp.sal%type;
v_second_sal emp.sal%type;
begin
select sal into v_first_sal
from emp
where empno = p_first_empno;
select sal into v_second_sal
from emp
where empno = p_second_empno;
if v_first_sal > v_second_sal then
return p_first_empno;
elsif v_first_sal < v_second_sal then
return p_second_empno;
else
return 0;
end if;
end;
/
show error
--함수 테스트용 조인 문장
select w.empno, e.empno
from emp w, emp e
where w.empno = 7788 and e.empno != w.empno;
select w.empno, e.empno, emp_sal_compare(w.empno, e.empno) as winner
from emp w, emp e
where w.empno = 7788 and e.empno != w.empno;
--cf. 함수없이 그냥 SQL로 해결하면 이렇습니다.
select w.empno, e.empno, case when w.sal > e.sal then w.empno
when w.sal < e.sal then e.empno
else 0
end as winner
from emp w, emp e
where w.empno = 7788
and e.empno != w.empno;
할당 연산자 vs 비교 연산자
C, Java Basic, PowerScript Pascal, PL/SQL
할당 연산자 A = B A = B A := B
비교 연산자 A == B A = B A = B
DML을 PL/SQL 프로그램 Unit을 이용해서 구현
drop table t1 purge;
create table t1
as
select empno, ename, sal, job
from emp
where 1 = 2;
create or replace procedure t1_insert_proc(a number, b varchar2, c number, d varchar2)
is
begin
if c <= 1000 then
dbms_output.put_line('입력 실패! 급여를 확인하세요');
else
insert into t1
values(a, b, c, d);
end if;
end;
/
show errors --오타 발생시 이유를 알 수 있음
exec t1_insert_proc(1000, 'Tom', 200, 'MANAGER');
References
개발자님들 덕분에 많이 배울 수 있었습니다. 감사의 말씀 드립니다.