- SQL로 노가다(?)해야할 일들 ---> PL/SQL 로 자동화
- Slow SQL을 튜닝하는 방법---> PL/SQL 의 함수 사용
dba 업무 자동화 : PL/SQL + 파이썬 + 리눅스 쉘스크립트
dba 업무를 위의 3가지를 이용해서 어떻게 편하게 할 수 있는 건가 ?
사례1.
오늘밤 11시에 우리회사 db에 특정 테이블에 데이터를 입력
해야합니다. 어떻게 해야할까요? 남아할까요 ?
자동화 사례1
: 데이터 입력 작업을 프로시져로 만들고 dbms_job
패키지를 이용해서 프로시져를 밤 11시에 자동으로
돌게 합니다.
1. 오늘 날짜와 현재시간을 확인하기
2. sysdate를 다시 출력하는데 시분초를 잘라버리고 00:00:00 가 되게 하시오!
select trunc(sysdate)
from dual;
3. 오늘밤 10시를 위의 SQL을 이용해서 출력하시오!
select trunc(sysdate) + 22/24
from dual;
4. 오늘 오전 11시가 출력되게 하시오!
5. 오늘 오전 10시 30분이 출력되게 하시오
select trunc(sysdate) + 10/24 + 30/60/24
from dual;
✅ 1 / 24
: 는 한시간이다.
✅ 30/60/24
: 한시간은 60분이니까, 60을 쓰고 한시간을 반으로 나누면 30 이니까
6. 위 SQL을 이용해서 아래와 같이 결과가 출력되게 하시오
23/08/01 11:01:00
select trunc(sysdate) + 11/24 + 1/60/24
from dual;
- job_test라는 테이블 생성한다.
- seq1 라는 시퀀스 생성한다.
- job_test_proc라는 프로시저를 생성한다.
- dbms_job 패키지를 이용해서 job_test_proc 프로시저가 밤 10시에 자동 수행되게 한다.
- job이 잘 등록되었는지 확인한다.
✏️ 구현실습
1. job_test라는 테이블 생성한다.
create table job_test
(seq number(10),
insert_date date);
2. seq1 라는 시퀀스 생성한다.
create sequence seq1
start with 1
increment by 1
maxvalue 100;
3. job_test_proc라는 프로시저를 생성한다.
create or replace procedure job_test_proc
is
vn_next_seq number := seq1.nextval; -- 시퀀스를 바로 가져올 수 있다.
begin
insert into job_test values (vn_next_seq, sysdate);
commit;
exception when others then
rollback;
dbms_output.put_line(SQLERRM);
end;
/
-------------------------------------------
exec job_test_proc;
select * from job_test;
4. dbms_job 패키지를 이용해서 job_test_proc 프로시저가 밤 10시에 자동 수행되게 한다.
declare
v_job_no number;
begin
dbms_job.submit (job => v_job_no,
what => 'job_test_proc;', -- 프로시저 이름. 세미콜론확인
next_date => trunc(sysdate) + 22/24,
interval => null -- 맨날안할거임. 할거면 위 코드 써주기
);
end;
/
5. job이 잘 등록되었는지 확인한다.
select job, last_date, last_sec, next_sec, broken, interval, failures, what
from user_jobs;
6. 등록된 잡을 중지시키기
select job
from user_jobs;
begin
dbms_job.broken(1,true);
end;
/
✅ 1번은 잡 번호, true쓰면 잡이 중지되고 false를 쓰면 잡이 다시 재개된다.
7. 아래의 스크립트를 수정해서 job_test_proc 프로시저가 오늘 오전 10시 35분에 자동으로 수행되게 하시오!
declare
v_job_no number;
begin
dbms_job.submit (job => v_job_no,
what => 'job_test_proc;',
next_date => trunc(sysdate) + 10/24 + 35/60/24,
interval => null
);
end;
/
➡️ 지금까지 배운 PL/SQL에 파이썬을 더해서 프로시저와 파이썬을 연동하여 조금 더 풍부한 DB 작업 자동화를 구현하는것이 이 수업의 목표 !
아나콘다 설치!
💡 아나콘다를 설치하면 파이썬 기본 엔진 + 유용한 파이썬 패키지들을 동시에 설치할 수 있어서 파이썬 설치가 아닌 아나콘다를 설치할 것이다.
✅ 오라클 디비와 연동해서 파이썬으로 디비작업 자동화가 목적이므로 다음의 환경에서 파이썬을 수행합니다.
🤔 변수란? 어떤값을 임시로 저장하는 메모리 공간을 변수라고 합니다. 비어있는 박스를 연상하면 된다.
❗변수 이름을 지을 때 주의할 사항!!
_
)문제 8. 파이썬의 예약어가 무엇이있는지 출력하기
import keyword
print(keyword.kwlist)
'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'
문제 9. 위 예약어 중 하나를 파이썬 변수로 사용하면 어떻게 되는지 확인해보기
오라클 : v_num number(10) := 7;
파이썬 : v_num = 7
➡️ v_num으로 변수를 정했을 때 잘 되는것을 확인했다. 그렇지만 예약어인 True 를 넣으면 문법에러가 남!
오라클에서의 할당 연산자는 := 이었는데 파이썬은 = 이다.
등호인 같다는 == 임!
PL/SQL vs 파이썬
declare v_num = 7
v_num number := 7; print(v_num)
begin
dbms_output.put_line(v_num) v_str = 'scott'
end; print(v_str)
/
문제 10. 아래의 PL/SQL 을 파이썬으로 구현하기
set serveroutput on
declare
v_ename emp.ename%type := 'scott';
begin
dbms_output.put_line(v_ename)
end;
/
v_ename = 'scott' print(v_ename)
✅ 코드가 엄청 심플하다 !
문제 11. 파이썬의 철학 확인
import this
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
프로그램에 주석 부분은 인터프리터에 의해 무시되는 텍스트의 한 부분입니다.
🤔 인터프리터란? 파이썬 코드 실행하는 프로세서
1. 한줄 주석 : #
import this #this 라는 모듈을 임포트 합니다.
"""
"""
""" dba 작업을 편하게 하는 파이썬 자동화 스크립트 입니다.
다음의 코드를 실행해서 db작업을 수행하세요! """
import this
문자형
: 문자를 표현하는 자료형a = 'scott'
숫자형
: 숫자를 표현하는 자료형b = 1
리스트형
: 대괄호 [ ] 안에 임의 객체를 순서있게 나열한 자료형c = [1, 2, 3]
튜플형
: 소괄호 ( ) 안에 임의 객체를 순서있게 나열한 자료형d = (1, 2, 3)
➡️튜플은 리스트와 달리 한번 만들면 안의 요소를 변경할 수 없다.
변경할 수 없다는 것은 구성된 데이터에 대해서 상당한 신뢰감을 줄 수 있다.
사전형
: 중활호 { } 안에 키값으로 이뤄진 쌍이 요소로 구성된 순서가 없는 자료형
중활호 { } 안에 임의 객체를 순서있게 나열한 자료형e = {'I': '나는', 'am' : '입니다', 'boy': '소년'}
문제 12. 주사위를 파이썬으로 만드시오
dice = [1, 2, 3, 4, 5, 6]
print(dice)
문제 13. 위 주사위를 한번 던져보기
import random # 랜덤 모듈을 임폴트 합니다.
dice = [1, 2, 3, 4, 5, 6] # 숫자 1 ~ 6까지의 숫자를 담는 dice리스트 생성
print(random.choice(dice)) # 랜덤 모듈에 choice함수를 이용하여
# dice 리스트에서 요소를 하나 랜덤 추출합니다.
🤔 모듈이란? 특정 목적을 가지고 만든 프로그램 코드의 모음
문제 14. 동전을 만들고, 동전을 던져서 '앞면'
또는 '뒷면'
나오게 하기
import random coin = ['앞면', '뒷면'] print(random.choice(coin))
문제 15. 아래의 dice리스트의 첫번째 요소를 9로 변경하기
dice = [1, 2, 3, 4, 5, 6]
dice[0] = 9
dice
🚨 리스트와 튜플의 차이 !
✅ 리스트는 요소를 변경할 수 있고, 튜플은 요소를 변경할 수 없다.
dice = (1, 2, 3, 4, 5, 6)
dice[0] = 9
dice
파이썬에서는 실행코드 부분을 묶어주는 괄호가 없다.
괄호 대신 들여쓰기를 사용한다. 실행영역을 들여쓰기로 구분!
예제. 숫자 1부터 10까지 반복문으로 출력
for i in range(1, 11): # 숫자 1번부터 11 미만까지.
print(i)
✅ 4칸 들여쓰기꼭 지켜주기 ! 공백 없으면 에러난다
문제 17. 숫자 21번부터 100번까지 출력하기
for i in range(21, 101):
print(i)
문제 18. 주사위를 10번 던지기
import random
dice = [1,2,3,4,5,6]
for i in range (1 , 11): # i 는 별 의미가 없다.
print(random.choice(dice))
✅ 파이썬은 들여쓰기로 실행문을 구분한다. for 반복문의 실행문을 작성할때는 for문 바로 아래에 들여쓰기 4칸하고 실행문을 작성합니다.
문제 19. 동전을 10번 던지시오!
import random coin = ['앞','뒤'] for i in range (1 , 11): print(i , '번째는', random.choice(coin), '이(가) 나왔습니다.')
✍🏻 문법
if 조건 :
실행문
else :
실행문
✍🏻 예제
a = 1
b = 2
if a > b :
print(a, '는', b, '보다 큽니다.')
else :
print(a, '는', b, '보다 작습니다.')
✅ 콜론(구분자 같은것) 있으면 그다음 네칸 들여쓰고 실행문!
책의 쉼표같은 역할을 한다.
문제 20. 두개의 숫자를 각각 물어보게하고 두개의 숫자를 출력하기
a = int(input('첫번째 숫자를 입력하시오')
b = int(input('두번째 숫자를 입력하시오')
print(a)
print(b)
✅ input은 PLSQL의 aceept와 같은 것. int는 SQL의 to_number 같은 것이다. input은 뭔가 받으면 문자로 받기때문에 숫자로 바꿔준것 ! 만약 int를 쓰지 않았다면 문자로 출력이된다.
문제 21. 두개의 숫자를 각각 물어보게하고, 두개의 숫자를 입력하면 두 숫자를 비교해서 다음과 같이 결과가 출력되게 하세요
첫번째 숫자를 입력하시오 -> 7
첫번째 숫자를 입력하시오 -> 6
7(은/는) 6보다 큽니다.
a = int(input('첫번째 숫자를 입력하시오') ) b = int(input('두번째 숫자를 입력하시오') ) if a > b : print(a, '(은/는)', b, '보다 큽니다.') else : print(a, '(은/는)', b, '보다 작습니다.')
✍🏻 문법
if 조건 :
실행문
elif 조건 :
실행문
elif 조건 :
실행문
else :
실행문
✍🏻 예제
a = 5
b = 2
if a > b :
print(a, '(은/는)', b, '보다 큽니다.')
elif a < b :
print(a, '(은/는)', b, '보다 작습니다.')
else :
print(a, '(와/과)', b, '는 같습니다.')
문제 22. 다음과 같이 2개의 숫자를 각각 물어보게하고, 숫자의 크기를 비교하시오!
첫번째 숫자를 입력하시오 -> 7
첫번째 숫자를 입력하시오 -> 6
7(은/는) 6보다 큽니다.
똑같이 7을 넣었다면 7은 7과 같습니다 출력!
a = int(input('첫번째 숫자를 입력하시오') ) b = int(input('두번째 숫자를 입력하시오') ) if a > b : print(a, '(은/는)', b, '보다 큽니다.') elif a < b : print(a, '(은/는)', b, '보다 작습니다.') else : print(a, '(와/과)', b, '는 같습니다.')
✍🏻 문법
for i in 범위:
실행문 # 범위만큼 반복시킨다.
✍🏻 예제
# 1. range 없이
for i in [1,2,3,4,5,6,7]:
print(i)
# 2. range 사용
for i in range(1, 8):
print(i)
# 3. i 대신 언더바 사용
for _ in range(1, 8):
print('기계를 자동화하자') # 메세지가 8번 출력
뮨제 23. 구구단 2단을 출력하기
2 x 1 = 2
2 x 2 = 4
.
.
for i in range(1, 10): print('2x', i, '=', 2*i)
문제 24. 다음과 같이 단을 물어보게 하고, 단을 입력하면 해당 구구단 출력
dan = int(input('단을 입력하시오') ) for a in range(1,10): print(dan,'x', a, '=', dan*a)
✍🏻 문법
for i in range(1,11): # i를 1부터 10까지 반복하는데
if i == 4: # i가 4일때는
continue # continue 아래의 코드를 실행하지 말아라
print(i)
🚨 주의 ! 같다인 등호 ( == ) 헷갈리지말기.
컨티뉴는 pl/sql은 무시하고 다른거 해라 ! -> 프린트해.
지금 if문, print가 같은줄에 맞춰져있다. 만약 줄이 다르다면 실행이 안된다.
✅ 4가 없는것을 확인. i == 4일때 아무것도 실행하지 않는다. 무시한다! 그다음 5일때, 6일때,,,
문제 25. 구구단 2단을 출력하는데, 2 x 6 = 12 만 나오지 않도록 하기!
for i in range(1, 10): if i == 6: continue print('2x', i, '=', 2*i)
✍🏻 문법
for i in 범위:
if 조건:
실행문
else:
실행문
✍🏻 예제1
for i in range(1, 11):
if i in [2, 4, 6, 8, 10]:
print(i,'는 짝수입니다.')
else:
print(i,'는 홀수입니다.')
💡파이썬 연산자
1. 산술연산자: * / + -
2. 비교연산자: >, <, >=, <=, ==, !=
3. 논리연산자: and, or, not
💡계산하는 연산자
1. 제곱 : **
ex) 2의 3승 -> 2**3
ex) 10을 2로나눈 나머지값을 구하기 -> 10%2
문제 26. 아래의 코드를 % 연산자 이용해서 똑같이 출력되도록 코드를 수정하기
for i in range(1, 11):
if i in [2, 4, 6, 8, 10]: # 여기 수정!
print(i,'는 짝수입니다.')
else:
print(i,'는 홀수입니다.')
for i in range(1, 11): if i%2 == 0 : print(i,'는 짝수입니다.') else: print(i,'는 홀수입니다.')
문제 27. 주사위를 10번 던져서, 다음과 같이 출력되게 하세용
import random # 랜덤모듈 임포트
dice = [1,2,3,4,5,6] # 주사위를 반복문 들어가기 전에 만들기
for i in range (1 , 11): # 10번 반복
a = random.choice(dice) # dice 리스트에서 랜덤으로 요소 추출해서 변수 a 에 할당
if a%2 == 0 : # 만약 a를 2로 나눈 나머지값이 0이면
print(a, '는/은 짝수입니다.') # 짝수입니다를 출력
else: # 그렇지 않으면
print(a,'는/은 홀수입니다.') # 홀수입니다 출력!
문제 28. (마지막 문제) 동전을 10번 던지고 다음과 같이 출력
import random coin = ['앞면', '뒷면'] for i in range (1 , 11): print(random.choice(coin),'이 나왔습니다.')