Language/Python

231128 Python_Oracle 접속, conda 설치, 바인드변수, create_engin, 정규표현식, 메타문자

잇꼬 2023. 11. 28. 17:19
728x90
반응형
SMALL

설치

Anaconda Prompt 

conda install -c anaconda cx_oracle

 

(base) C:\Users\ITWILL>lsnrctl status : 상태정보 

 

import pandas as pd
from pandas import Series, DataFrame

emp = pd.read_csv('c:/data/emp.csv')
dept = pd.read_csv('c:/data/dept.csv')


■ 파이썬에서 오라클 접속

import cx_Oracle


오라클 접속

                        # 계정명, 비번, HOST명:PORT번호/serviece이름, encoding
conn = cx_Oracle.connect("hr","hr","DESKTOP-E88DR0D:1521/xe",encoding="UTF-8")
cursor = conn.cursor()
cursor.execute("select * from employees")
data = cursor.fetchall()
data


# 컬럼 정보는 숫자로 표현

df = DataFrame(data)
df


# 컬럼 확인

select column_name 
from user_tab_columns 
where table_name = 'EMPLOYEES';
cursor.execute (""" select column_name 
                    from user_tab_columns 
                    where table_name = 'EMPLOYEES'
                """)
col = cursor.fetchall() 
col


# 튜플타입을 list 타입으로 변형
# for문 + for문

[j for i in col for j in i ]

col_new = [j for i in col for j in i ]
col_new


# 컬럼명 수정

df.columns = col_new
df


# 테이블 생성

cursor.execute("""create table insa(id number, name varchar2(30), day date)""")
cursor.execute("""insert into insa(id, name, day) values(1, '홍길동', sysdate)""")
cursor.execute("""select * from insa""")
cursor.fetchall()

cursor.execute("commit") # select * from insa;


# rollback

cursor.execute("""insert into insa(id, name, day) values(2, '박찬호', sysdate)""")
cursor.execute("""select * from insa""")
cursor.fetchall()
cursor.execute("rollback")
cursor.execute("""select * from insa""")
cursor.fetchall()


# 변수로 data 로드하기

v_id = 2
v_name = '박찬호'
v_day = pd.Timestamp.now().date() # sysdate 는 sql 함수여서 사용X 

cursor.execute("""insert into insa(id, name, day) 
                  values(:b_id, :b_name, :b_day)""", # 바인드변수명으로 위치표현 지정
                  (v_id, v_name, v_day))
cursor.execute("commit")
cursor.execute("""select * from insa""")
cursor.fetchall()


# sql 쿼리문으로 별로의 변수로 지정

sql = """insert into insa(id, name, day) values(:b_id, :b_name, :b_day)"""
cursor.execute(sql,[3, '손흥민', pd.Timestamp.now()]) # 변수로 작성해도 무방
cursor.execute("commit")
cursor.execute("""select * from insa""")
cursor.fetchall()


# 바인드변수에 값을 지정

cursor.execute(sql, b_id=4, b_name='나얼', b_day=pd.Timestamp.now()) 
cursor.execute("commit")
cursor.execute("""select * from insa""")
cursor.fetchall()


# dict 형태로 값을 지정

data = dict(b_id=5, b_name='윤건', b_day=pd.Timestamp.now())
data
cursor.execute(sql,data) 
cursor.execute("commit")
cursor.execute("""select * from insa""")
cursor.fetchall()


# 문제점) select 문 실행 → 동일한 실행계획을 생성

cursor.execute("""select * from insa where id = 1""")
cursor.fetchone()

cursor.execute("""select * from insa where id = 2""")
cursor.fetchone()

cursor.execute("""select * from insa where id = 3""")
cursor.fetchone()


Q) SQL문에 변수 처리하는 이유?
#- 실행계획을 공유하기 위한 목적(CPU, 메모리 사용을 줄일 수 있다.)

# 바인드변수 처리 

cursor.execute("""select * from insa where id = :b_id""", 1) # 오류발생
cursor.fetchone()

cursor.execute("""select * from insa where id = :b_id""", [1]) # list 형식
cursor.fetchone()
cursor.execute("""select * from insa where id = :b_id""", (1,)) # 튜플형식
cursor.fetchone()


# 변수명

v_id = 1
cursor.execute("""select * from insa where id = :b_id""", [v_id])
cursor.fetchone()
cursor.execute("""select * from insa where id = :b_id""", (v_id,))
cursor.fetchone()
cursor.execute("""select * from insa where id = :b_id""", b_id = v_id)
cursor.fetchone()


# update 문

cursor.execute("""update insa set name = '제임스' where id = 2""")
cursor.execute("""select * from insa""")
cursor.fetchall()
cursor.execute("rollback")


# 변수 처리

v_id = 2
v_name = '제임스'
cursor.execute("""update insa set name = :b_name where id = :b_id""", b_name=v_name, b_id= v_id)
cursor.execute("""select * from insa""")
cursor.fetchall()
cursor.execute("rollback")


# delete 문

v_id = 2
cursor.execute("""delete from insa where id = :b_id""", b_id= v_id)
cursor.execute("""select * from insa""")
cursor.fetchall()
cursor.execute("rollback")


<<pandas datafram 을 오라클로 이관작업>>

from sqlalchemy.engine import create_engine

 

db_sw = 'oracle'
sql_driver = 'cx_oracle'
# 실무적으로 변경작업되는 부분
username = 'hr'
password = 'hr'
host = 'DESKTOP-E88DR0D'
port = 1521
service = 'xe'

 

# 오라클 연결 하는 작업을 변수처리해서 연결

(직접 코드 작성해도 가능하다!)

path = db_sw+'+'+sql_driver+'://'+username+':'+password+'@'+host+':'+str(port)+'/?service_name='+service
# oracle+cx_oracle://hr:hr@DESKTOP-E88DR0D:1521/?service_name=xe
path

engine = create_engine(path)

emp.to_sql('emp_new', engine, schema='hr', index=False) # 이관작업
emp.info()


<< 오라클에서 clob column 변경작업 >>

alter table emp_new modify commission_pct number;
alter table emp_new modify manager_id number;
alter table emp_new modify department_id number;

desc emp_new
select * from emp_new;

 


# FIRST_NAME CLOB : 타입이 변경이 되지 않음, 오류발생

alter table emp_new modify first_name varchar2(30);

# clob 을 varchar2(4000), char(2000) 수정할 수 없다.

# 기존 용량보다 초과되어 있다면, 조각해서 출력

select dbms_lob.substr(first_name, 4000, 1), dbms_lob.substr(first_name, 4000, 4001)
from emp_new;


#1. 새로운 컬럼을 생성 

alter table emp_new add new_column varchar2(30);
desc emp_new


#2. clob의 컬럼을 varchar2 컬럼으로 수정 작업

update emp_new
set new_column = dbms_lob.substr(first_name, 4000, 1);

commit;
select * from emp_new;


#3. clob 컬럼 삭제 

alter table emp_new drop column first_name;
desc emp_new
select * from emp_new;


#4. 새로운 컬럼이름을 기존 컬럼 이름 수정

alter table emp_new rename column new_column to first_name;
desc emp_new


■ 정규표현식(Regular Expression)
    # 특정패턴과 일치하는 문자열 검색, 치환, 제거하는 기능을 제공한다.

■ 메타문자(meta characters)
    # [A-Za-z]: [] 메타문자를 표현, - 범위를 표현
    # 원래 문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자

[A-Za-z]  []사이의 문자들과 매치
[0-9]  숫자 패턴
[sql] s 또는 q 또는 l
[가-힣ㄱ-ㅎㅏ-ㅣ]  한글, 자모음

  

# 가장 많이 사용되는 메타문자

a.b . 위치에 모든 문자를 의미(줄바꿈은 제외)
a\.b .을 문자로 인식
a[.]b

 

a*b  * 바로 앞의 문자가 0 번 이상을 찾는다.   b, ab, aaab
a+b + 바로 앞의 문자가 1 번 이상을 찾는다.  ab, aab, aaab
ab?c ? 바로 앞의 문자가 0 번, 1번을 찾는다. ac, abc

 

a{2}b  {n} 바로 앞의 문자가 n 번 반복을 찾는다. aab
a{2, 3}b  {n, m} 바로 앞의 문자가 n 번 또는 m번 반복을 찾는다. aab, aaab
a{2,}b  {n,} 바로 앞의 문자가 n 번 이상을 찾는다. aab, aaab, aaaab
a|b a 또는 b
[^a] [^] not 을 제외 
(a 제외)
^ 시작
$ 종료

 

\d [0-9]
숫자 패턴을 찾을 때
\D [^0-9]
숫자가 아닌 패턴을 찾을 때
\s [ \t\n\r\f\v] 
공백문자
\S [^ \t\n\r\f\v] 
공백문자가 아닌 패턴
\w  [a-zA-Z가-힣0-9]
문자 또는 숫자 패턴을 찾을 때
\W [^a-zA-Z가-힣0-9]
문자, 숫자가 아닌 패턴을 찾을 때

 

import re


# re.match : 문자열의 처음부터 정규식과 매치되는지 찾는 함수

re.match('\w','a')
bool(re.match('\w','a'))

re.match('\w','100')
bool(re.match('\w','100'))

re.match('\w','_')
bool(re.match('\w','_'))

re.match('\w','python')
bool(re.match('\w','python'))

re.match('\w','-python')
bool(re.match('\w','-python'))

re.match('\W','-python')
bool(re.match('\W','-python'))

bool(re.match('[-]','-python'))
bool(re.match('[-]','py-thon'))

re.match('c*a','cat')
bool(re.match('c*a','cat'))

re.match('c*a','ccat')
bool(re.match('c*a','ccat'))

re.match('c+a','cat')
bool(re.match('c+a','cat'))

re.match('c+a','ccat')
bool(re.match('c+a','ccat'))

bool(re.match('c+a','at'))

re.match('c?a','cat')
bool(re.match('c?a','cat'))

re.match('c?a','at')
bool(re.match('c?a','at'))

re.match('c{2}a','cat')
bool(re.match('c{2}a','cat'))

re.match('c{2}a','ccat')
bool(re.match('c{2}a','ccat'))

re.match('c{2,3}a','ccccat')
bool(re.match('c{2,3}a','cccccat'))

re.match('c|a','at')
bool(re.match('c|a','at'))
bool(re.match('c|a','ct'))
bool(re.match('c|a','bat'))

bool(re.match('[0-9]th','21th'))
bool(re.match('[0-9][0-9]th','21th'))
bool(re.match('[0-9]{2}th','21th'))
bool(re.match('[0-9]*th','21th'))
bool(re.match('[0-9]+th','21th'))
bool(re.match('[0-9]?th','21th'))
bool(re.match('\d\dth','21th'))
bool(re.match('\d{2}th','21th'))


# 대소문자 구분

re.match('Or','Oracle engineer')
re.match('or','Oracle engineer')

 

#re.I 대소문자 구분

re.match('or','Oracle engineer',re.I) 
m = re.match('Oracle','Oracle engineer')
m.group() # 매치된 문자열 리턴 
m.span() # 매치된 문자열의 (시작, 끝)
m.start() # 매치된 문자열 시작위치
m.end() # 매치된 문자열 끝

'Oracle engineer'[m.start():m.end()]


# re.search() : 해당하는 문자열에서 어디서든지 찾는다.

re.match('engineer','Oracle engineer')
re.search('engineer','Oracle engineer')

m = re.search('engineer','Oracle engineer')
m.group()
m.span()
m.start()
m.end()


# re.findall() : 일치하는 문자열 전부를 리스트로 반환한다.

re.search('engineer','Oracle engineer Oracle engineer')
re.findall('engineer','Oracle engineer Oracle engineer')


# re.sub() : 패턴을 치환하는 함수

source = 'oracle engin'
source.replace('engin', 'engineer')
re.sub('engin', 'engineer', source)


# re.split() : 패턴을 이용해서 문자열 분리

'python.programming'.split('.')
re.split('\.', 'python.programming')
re.split('[.]', 'python.programming')
re.split('[.:]', 'python.programming:PLSQL')
re.split('[.: ]', 'python.programming:PLSQL SQL')
re.split('[.:\s]', 'python.programming:PLSQL SQL')
728x90
반응형
LIST