※ 이 글을 쓰는 사람은 SW 비전공자입니다.
※ 개인 공부를 위해 정리하는 글이며, 작성한 코드들은 효율성, 깔끔함(?) 등과는 거리가 멀 수 있습니다.
※ SQLite3 내용 정리 링크
1편 : 2021.03.10 - [코딩/DB] - SQLite3 - Database 파일 생성, Table 생성
2편 : 2021.03.12 - [코딩/DB] - SQLite3 - DB Browser for SQLite 설치 및 실행 정리
3편 ; 2021.03.13 - [코딩/DB] - SQLite3 - Table Data 삽입 정리(INSERT)
4편 : 2021.03.15 - [코딩/DB] - SQLite3 - Table Data 조회 방법 정리(SELECT)
5편 : 2021.03.18 - [코딩/DB] - SQLite3 - Table Data 수정 및 삭제 정리(UPDATE, DELETE)
이전 포스팅에서 파이썬에서 sqlite3을 import 하여 db 파일을 생성하고 data 삽입까지 해보았다. 이번 포스팅에서는 이전에 Table에 입력했던 Data를 조회하는 방법을 정리한다. 그전에 SQL에서 다루는 Data type에 대해 정리해보았다. 파이썬과 SQLite 쿼리문에서 다루는 Data type은 다르다.
※ SQL Data type 정리 (참고링크 : mmjourney.tistory.com/20)
SQL Data type |
설명 |
Null |
아무 것도 들어있지 않음 |
INTEGER |
정수형 값(=파이썬 int) |
REAL |
decimal 소수형 값(=파이썬 float) |
TEXT |
문자열(text) (=파이썬 str) |
BLOB |
파일, 이미지 저장하는 바이너리 데이터 (=파이썬 bytes) |
이번에는 새로운. db파일을 생성하려고 아래와 같이 코드를 작성하였다. 코드는 2월에 연습하려고 작성했던 코드여서 파일명에 210220이 붙어있다.
import sqlite3
#'210220_test.db" 파일 생성
con = sqlite3.connect("210220_test.db")
# .db파일에 대한 cursor 생성
cur = con.cursor()
# cursor 통해 table 생성하는 쿼리문 실행
cur.execute("CREATE TABLE IF NOT EXISTS 210220_test(id_num INTEGER, name TEXT, age INTEGER)")
<결과>
Traceback (most recent call last):
File "C:/Users/PycharmProjects/test01/SQlite_test.py", line 5, in <module>
cur.execute("CREATE TABLE IF NOT EXISTS 210220_test(id_num INTEGER, name TEXT, age INTEGER)")
sqlite3.OperationalError: unrecognized token: "210220_test"
sqlite3.OperationError : unrecognized token 에러가 발생했다. 210220_test라는 table 명을 인지하지 못한다는 메시지이다.
table명에 숫자가 들어가면 반드시 ' '를 넣어줘야 한다. 아래와 같이 코드를 작성하니 table이 생성되는 것을 확인하였다.
※ 참고사항 : sqlite3.OperationError : unrecognized token
CREATE table 명 양쪽에 ' '를 넣었는지 반드시 확인할 것!!
아래와 같이 전체 코드를 작성하였다. '210220_text'라는 Table을 생성하였고 test_list라는 튜플을 data를 입력하는 구문까지 실행했다. 입력된 data를 기반으로 조회하는 방법을 정리하였다.
import sqlite3
con = sqlite3.connect("210220_test.db")
cur = con.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS '210220_test'(id_num INTEGER, name TEXT, age INTEGER)")
#입력할 data를 튜플로 생성(튜플 요소는 리스트임)
test_list = (
[3025, 'A', '31'],
[3026, 'B', '34'],
[3027, 'C', '33']
)
#복수의 data이므로 executemany()를 활용
cur.executemany("INSERT INTO '210220_test'(id_num, name, age) VALUES(?,?,?)", test_list)
con.commit()
cur.close()
con.close()
1. Table에 입력 된 data를 1개씩 조회하고 싶을 때
-. 입력(INSERT)와 마찬가지로 Cursor를 활용해야 한다.
-. 위 코드에 아래 구문을 추가하여 입력하였다.
(executemany 함수의 경우 주석처리한다. primary key를 설정을 안 했기 때문에 실행이 data가 계속 추가된다.)
#data 삽입
#cur.executemany("INSERT INTO '210220_test'(id_num, name, age) VALUES(?,?,?)", test_list)
#data 조회
cur.execute("SELECT * FROM '210220_test'")
print('1개만 조회 ->', cur.fetchone())
print('1개만 조회 ->', cur.fetchone())
print('1개만 조회 ->', cur.fetchone())
-. 1개씩 조회 할 경우 fetchone() 함수를 사용한다.
- SELECT * FROM '210220_test'
▶ SELECT : 테이블에 입력된 data를 조회하는 SQL 쿼리 구문이다.(입력 시 INSERT가 있는 것처럼)
▶ 별표의 경우 Table의 모든 필드를 가져오겠다는 의미라고 한다.
▶ '210220_test' : 앞 과정에서 생성했던 db의 테이블 이름이다.
<결과>
- . fetchone() 함수를 3번 연속 사용하니 cursor가 자동으로 아래 data로 이동하여 출력하는 것을 확인 가능
-. 출력 data의 type은 튜플(tuple)이다.
1개만 조회 -> (3025, 'A', 31)
1개만 조회 -> (3026, 'B', 34)
1개만 조회 -> (3027, 'C', 33)
Process finished with exit code 0
2. Table에 입력된 data 전체를 한번에 출력하고 싶을 때
#첫 줄만 fetchall 함수로 변경
print('1개만 조회 ->', cur.fetchall())
print('1개만 조회 ->', cur.fetchone())
print('1개만 조회 ->', cur.fetchone())
-. 위 print를 첫줄만 fetchall() 함수로 변경하였다.
-. fetchall() 함수는 현 cursor 위치 기준으로 아래 모든 data를 출력한다.
<결과>
-. fetchall()함수에서 모두 출력했기 때문에 아래 fetchone() 함수 조회 결과는 None이다.
-. 출력 요소는 리스트이며, 내부요소는 튜플인 것으로 확인하였다.
1개만 조회 -> [(3025, 'A', 31), (3026, 'B', 34), (3027, 'C', 33)]
1개만 조회 -> None
1개만 조회 -> None
만약 첫번째줄이 아니라 두 번째 줄에 fetchall()을 넣으면 어떻게 될까?
#두번째 줄만 fetchall 함수로 변경
print('1개만 조회 ->', cur.fetchone())
print('1개만 조회 ->', cur.fetchall())
print('1개만 조회 ->', cur.fetchone())
<결과>
-. 만약 첫번재 줄이 아닌 두 번째 줄에 fetchall()을 넣으면 아래와 같이 출력된다.
-. 첫번재 줄에 fetchone()을 출력하고 다음 커서부터 모든 data가 출력된다.
-. 당연히 세번째 fechone()은 cursor가 다음 data를 찾을 수 없으므로 None을 출력한다.
-. 위 fetchall과 마찬가지로 출력 타입은 list이며 list의 내부 요소가 튜플(tuple)인 것을 확인할 수 있다.
1개만 조회 -> (3025, 'A', 31)
1개만 조회 -> [(3026, 'B', 34), (3027, 'C', 33)]
1개만 조회 -> None
※ 참고사항 : fetchone( ) vs fetchall( )
리턴결과가 다르다.
fetchone( )의 리턴 결과는 튜플(tuple)이다.
fetchall( )의 리턴 결과는 리스트(list)이다. 리스트 내부의 구성요소가 튜플(tuple)이다.
3. for문(loop) 통해 조회
위 fechall() 함수를 변수로 받아 루프 문을 통해 출력하는 것도 가능하다.
#data 조회
cur.execute("SELECT * FROM '210220_test'")
row_list = cur.fetchall()
print('row_list출력 ->' , row_list)
for i in row_list:
print('1개 출력 ->' , i)
<결과>
-. fechall 결과의 한 행의 data를 row_list로 받는다.(결과 중 첫 번째 줄)
-. 리스트를 for문을 통해 한줄씩 출력할 수 있다.
-. 출력 형태를 보니 튜플(tuple)로 확인된다.
row_num 출력 -> [(3025, 'A', 31), (3026, 'B', 34), (3027, 'C', 33)]
1개 출력 -> (3025, 'A', 31)
1개 출력 -> (3026, 'B', 34)
1개 출력 -> (3027, 'C', 33)
4. 원하는 개수를 순서대로 출력하고 싶은 경우
-. fetchmany()함수 사용
-. 마찬가지로 cursor object를 활용하기 때문에 출력한 개수 이후로는 출력이 안된다.
-. 아래 코드를 보면서 확인해보자.
print('1번째까지 -> ', cur.fetchmany(size=1))
print('그 다음부터 2번째 -> ', cur.fetchmany(size=2))
print('출력없음 -> ', cur.fetchmany(size=3))
<결과>
-. 첫줄의 size=1인 경우 table data 중 첫 번째까지 출력
-. 두번재줄의 size=2 구문의 경우 그다음 cursor부터 2개까지 출력
-. 세번재줄의 size=3 구문의 경우 cursor가 다음 data를 알 수 없으므로 결과는 None이다.
1번째까지 -> [(3025, 'A', 31)]
그 다음부터 2번째 -> [(3026, 'B', 34), (3027, 'C', 33)]
출력없음 -> []
5. 특정 조건의 data를 조회하고 싶은 경우
1) 1개 출력은 fetchone() 사용
-. SQL 구문의 WHERE을 사용하면 된다.
-. 아래와 같이 구문을 작성한다.
#data 조회
param1 = (3025,)
cur.execute("SELECT * FROM '210220_test' WHERE id_num=?", param1)
print('param1 -> ', cur.fetchone())
<결과>
-. param1 : 위 data 구성요소 중 첫 번째 요소가 '3025'인 data를 조회할 것
-. 쿼리 구문 중 WHERE id_num=? : 뒤 param1 변수가 된다.
param1 -> [(3025, 'A', 31), (3025, 'A', 31), (3025, 'A', 31), (3025, 'A', 31)]
2) 중복 data를 모두 출력하고 싶은 경우는 fetchall() 사용
-. table에 똑같은 data를 여러 개 더 추가하였다.
-. 위 1) 코드에서 fetchone( )을 fetchall() 함수로 바꾸면 아래와 같이 출력된다. (조건에 맞는 데이터 모두 출력)
<결과>
param1 -> [(3025, 'A', 31), (3025, 'A', 31), (3025, 'A', 31), (3025, 'A', 31)]
3) 한 가지 key가 아니라 2가지 key를 조회하고 싶은 경우는 아래와 같이 작성한다.
-. id_num이 '3025', '3026'인 것을 조회해보자
-. 여러 개를 조회하는 것이므로 fetchall() 함수를 사용한다.
param2 = (3025,3026)
cur.execute("SELECT * FROM '210220_test' WHERE id_num IN (?, ?)", param2)
print('param2 -> ', cur.fetchall())
<결과>
-. 3025, 3026 key를 가진 중복 data를 모두 확인할 수 있음.
param2 -> [(3025, 'A', 31), (3026, 'B', 34), (3025, 'A', 31), (3026, 'B', 34), (3025, 'A', 31), (3026, 'B', 34), (3025, 'A', 31), (3026, 'B', 34)]
※ 참고사항 : 조건 검새 WHERE을 활용한 쿼리 구문은 아래와 같이 작성하여도 똑같은 결과를 확인할 수 있다.
1) 단일 조건
cur.execute("SELECT * FROM '210220_test' WHERE id_num=:idn", {"idn":3025})
print('param1 -> ', cur.fetchall())
<결과>
param1 -> [(3025, 'A', 31), (3025, 'A', 31), (3025, 'A', 31), (3025, 'A', 31)]
2) 복수 조건
cur.execute("SELECT * FROM '210220_test' WHERE id_num=:idn1 OR id_num=:idn2 ", {"idn1":3025, "idn2":3026})
print('result -> ', cur.fetchall())
<결과>
param2 -> [(3025, 'A', 31), (3026, 'B', 34), (3025, 'A', 31), (3026, 'B', 34), (3025, 'A', 31), (3026, 'B', 34), (3025, 'A', 31), (3026, 'B', 34)]
※ 참고자료
'코딩 > DB' 카테고리의 다른 글
SQLite3 - Table Data 수정 및 삭제 정리(UPDATE, DELETE) (0) | 2021.03.18 |
---|---|
SQLite3 - Table Data 삽입 정리(INSERT) (0) | 2021.03.13 |
SQLite3 - DB Browser for SQLite 설치 및 실행 정리 (0) | 2021.03.12 |
SQLite3 - Database 파일 생성, Table 생성 (1) | 2021.03.10 |