第23章.単純データベース
データベースの基礎
データベースの概念
日常生活では、ニュースやネット、SNSなどでデータベースという言葉に触れることが多い.データベースは、モバイル、サーバコンピュータ、ネットワーク環境に不可欠な要素です.
Pythonが作成したプログラムのデータはファイルに保存できますが、いくつかの限界があります.例えば,1人で登録したサイト,支払い金額,ID,Passwordなどのデータが存在し,数千個のデータをファイルとして管理することは限られている.この問題を解決したのはデータベースです.
データベース管理システム(DBMS)は、前述した様々な形式の、持続的、大量のデータを管理するために登場する.データベースは、大量のデータをシステム的に格納するように簡単に定義することができ、データベースは複数のユーザまたはシステムによって共有される必要がある.
データベース管理システムは、これらのデータベースを管理するシステムです.
Pythonプログラミングを熟知するために、Pythonソフトウェアをインストールした後、データベースを熟知するために、データベースソフトウェアをインストールする必要があります.データベースソフトウェアは、データベース管理システム(DBMS)とも呼ばれます.これらのDBMS製品は、現在最もよく使用されているOracleからSQL Server、MySQL、Access、SQLiteなど様々です.
リレーショナル・データベース
DBMSは、大別して階層型DBMS、網状DBMS、リレーショナルDBMS、オブジェクト向けDBMS、オブジェクトリレーショナルDBMSなどに分けられる.
リレーショナルDBMSの使用が最も多く、一部のマルチメディア分野では、オブジェクト向けまたはオブジェクトリレーショナルDBMSのトレンドが使用されています.
先のOracle、SQL Server、Access、MySQLなどは、いずれもリレーショナルDBMS(RDBMS)と言えます.
RDBMSの最大の欠点は大量のシステム資源を占有し、全体の速度が遅いことである.しかし、ハードウェアの発展により、以前よりずっとよくなりました.
データベース用語
建物を建てるには、まず設計図を作成し、データベースの構築はまずデータベースモデリングから始まります.データベースモデリングは、現実世界で使用されているデータをDBMSに転送する方法を決定するプロセスです.
例えば、ポータルサイトに会員登録する場合は、DBMSに「会員」の情報をどのように入れるかを考えるべきである.すなわち,メンバ自体をコンピュータに入れることができないため,メンバを表すことができる特性(属性)を抽出し,その特性をDBMSに入れる必要がある.すなわち、名前、生年月日、電子メールアドレス、連絡先などの情報をDBMSに記憶しなければならない.
これらの情報は表形式のフレームワークで入れるべきです.
以下は、画像による簡単なデータベース関連用語です.
用語表データJohn,John Bann,[email protected]などの断片的な情報を指す.表会員データは表形式で表現されています.現在,NAVERデータベースを実現するために会員情報を保存する会員表が作成されている.データベース・テーブル・リポジトリ.主に円柱状に表示されます.上の図にはNAVER、A、Bデータベースがあり、各データベースに一意の名前が必要です.DBMSデータベースを管理するシステムまたはソフトウェア.SQLiteソフトウェアはそうです.カラム(カラムまたはフィールド)各テーブルは、1つ以上のカラムで構成されます.会員表は、身分、会員名、電子メール、生年月日の4つから構成されています.カラム名は、各カラムを区別する名前です.カラム名は各テーブルで繰り返すことはできません.データ型カラムのデータ型を使用してテーブルを作成する場合は、カラム名とともに入力するデータ型を指定する必要があります.「たとえば、出生年の資料型はintであるべきです.」「はや94」と同じ値段では使えないからです.行の実際のデータ、john/johnbann/[email protected]/1990は1行のデータです.SQL(構造化クエリー言語)DBMS(SQLite)でアクションを実行する場合は、DBMSに従って指示する必要があります.SQLはDBMSの言語です.
データベースの構築
1-SQLiteを実行します。
データベースを作成するには、まずSQLiteに接続します.図に示すように、ファイルブラウザではsqlite 3が使用されます.exeを実行すると、コマンドプロンプトウィンドウが開き、splite>として表示されます.
2-SQLの作成
1.データベースの作成
データベースを作成または開くには、次の手順に従います.
データベース名を開く
データベースが存在する場合はコマンドを開き、存在しない場合はコマンドを再作成します.次の図に示すように、作成コマンドはNAVERデータベース(名前:naverDB)を生成します.
2.テーブルの作成
naverDBにテーブルを作成する必要があります.このため、SQL文のフォーマットは次のとおりです.
CREATE TABLEテーブル名(カラム名1データ型、カラム名2データ型、...);
3.入力データ
生成された「メンバーテーブル」(UserTable)に行データを入力する必要があります.形態は以下の通り.
INSERT INTOテーブル名VALES(値1、値2、...);
行データの削除と変更は次のとおりです.
削除行データ:「DELETE FROMテーブル名WHEREカラム名=値;
修正フォームデータ:「UPDATEテーブル名SET修正するデータの列名=新規値、WHERE条件列名=値」
4.データの照会と利用
データを検索して使用するSQL文はSELECTです.
SELECT列名称FROM表名称;
データのロード時に条件を追加する場合は、WHEREを後ろに貼り付けます.
SELECT列名1、列名2...FROM表名WHERE条件;
データをソートする場合は、ORDER BYを使用します.
SELECT列名1、列名2...FROMテーブル名ORDER BY列名;sqlite> SELECT id, birthYear FROM userTable WHERE birthYear<=1990;
john 1990
lee 1988
park 1980
sqlite) SELECT * FROM userTable WHERE id = ‘lee’;
lee Lee Pal lee@paran.com 1998
sqlite> SELECT * FROM userTable ORDER BY birthyear;
park Park Su park@gmail.com 1980
lee Lee Pal lee@paran.com 1988
john John Bannijohn@naver.com 1990
kim Kim Chi kim@daum.net 1992
sqlite>.quit
SQLite簡単なコマンドクリーンアップ
コマンドの説明tableは、現在のデータベースのテーブルのリストを表示します.schemaテーブル名テーブルのカラムやデータ型などの情報が表示されます.ヘッダーonSELECT文出力時にヘッダーが表示されます.モードcolumnSELECT文出力の場合、columnモードで出力します.quitSQLiteを終了します.DROP TABLEテーブル名で生成されたテーブルを削除します.
Pythonとsqlite 3モジュール
Pythonからデータの符号化順を入力
1-SQLiteを実行します。
データベースを作成するには、まずSQLiteに接続します.図に示すように、ファイルブラウザではsqlite 3が使用されます.exeを実行すると、コマンドプロンプトウィンドウが開き、splite>として表示されます.
2-SQLの作成
1.データベースの作成
データベースを作成または開くには、次の手順に従います.
データベース名を開く
データベースが存在する場合はコマンドを開き、存在しない場合はコマンドを再作成します.次の図に示すように、作成コマンドはNAVERデータベース(名前:naverDB)を生成します.
2.テーブルの作成
naverDBにテーブルを作成する必要があります.このため、SQL文のフォーマットは次のとおりです.
CREATE TABLEテーブル名(カラム名1データ型、カラム名2データ型、...);
3.入力データ
生成された「メンバーテーブル」(UserTable)に行データを入力する必要があります.形態は以下の通り.
INSERT INTOテーブル名VALES(値1、値2、...);
行データの削除と変更は次のとおりです.
削除行データ:「DELETE FROMテーブル名WHEREカラム名=値;
修正フォームデータ:「UPDATEテーブル名SET修正するデータの列名=新規値、WHERE条件列名=値」
4.データの照会と利用
データを検索して使用するSQL文はSELECTです.
SELECT列名称FROM表名称;
データのロード時に条件を追加する場合は、WHEREを後ろに貼り付けます.
SELECT列名1、列名2...FROM表名WHERE条件;
データをソートする場合は、ORDER BYを使用します.
SELECT列名1、列名2...FROMテーブル名ORDER BY列名;
sqlite> SELECT id, birthYear FROM userTable WHERE birthYear<=1990;
john 1990
lee 1988
park 1980
sqlite) SELECT * FROM userTable WHERE id = ‘lee’;
lee Lee Pal lee@paran.com 1998
sqlite> SELECT * FROM userTable ORDER BY birthyear;
park Park Su park@gmail.com 1980
lee Lee Pal lee@paran.com 1988
john John Bannijohn@naver.com 1990
kim Kim Chi kim@daum.net 1992
sqlite>.quit
SQLite簡単なコマンドクリーンアップ
コマンドの説明tableは、現在のデータベースのテーブルのリストを表示します.schemaテーブル名テーブルのカラムやデータ型などの情報が表示されます.ヘッダーonSELECT文出力時にヘッダーが表示されます.モードcolumnSELECT文出力の場合、columnモードで出力します.quitSQLiteを終了します.DROP TABLEテーブル名で生成されたテーブルを削除します.
Pythonとsqlite 3モジュール
Pythonからデータの符号化順を入力
PythonでSQLiteを使用する場合は、sqlite 3モジュールを有効にする必要があります.そしてsqlite 3データベースにconnt(「DB名」)で接続する必要があります.データベースが存在する場合は接続、存在しない場合は生成されます.
import sqlite3
con = sqlite3.connect("C:/PythonDB/naverDB") # 소스 코드가 저장된 폴더에 생성
출력 결과:
아무것도 나오지 않음
上のコードでは,naverDBは前のSQLiteを用いて生成したnaverDBとは異なる.カーソル(Cursor)は、データベースでSQL文を実行したり、実行結果を返したりするチャネルに似ています.
前に作成したコネクタconにカーソルを作成する必要があります.
cur = con.cursor()
출력 결과:
아무것도 나오지 않음
表を作成するSQL文のカーソル名.execute()関数のパラメータに渡されると、SQL文はデータベースで実行されます.
cur.execute("CREATE TABLE userTable (id char(4), userName char(15), email char(15), birthYear int)")
출력 결과:
<sqlite3.Cursor object at 개체번호)
入力データの入力は、execute()関数を使用して、データ入力SQL文をパラメータに渡すこともできます.
cur.execute("INSERT INTO userTable VALUES('john', 'John Bann', '[email protected]', 1990)")
cur.execute("INSERT INTO userTable VALUES('kim', 'Kim Chi', '[email protected]', 1992)")
cur.execute("INSERT INTO userTable VALUES('lee', 'Lee Pal', '[email protected]', 1988)")
cur.execute("INSERT INTO userTable VALUES('park', 'Park Su', '[email protected]', 1980)")
출력 결과:
sqlite3.Cursor object at 개체번호)가 각각 4회 출력됨
4番のデータ入力は、データベースに完全に格納されているのではなく、一時的に格納されています.コミット(commit)に正確に渡します.
con.commit()
출력 결과:
아무것도 나오지 않음
データベースもリソースであり、使用が完了したら閉じる必要があります.
con.close()
출력 결과:
아무것도 나오지 않음
次のコードは、データを受信してデータベースに格納するコードです.# 사용자로부터 데이터를 입력받아서 DB에 저장하는 실습
import sqlite3
# 전역 변수 선언
con, cur = None, None # 연결자, 커서를 저장하는 변수 초기화
id, userName, email, birthYear = "","","",""
# 메인 코드 부분
if __name__ == '__main__':
con = sqlite3.connect("C:/PythonDB/naverDB")
cur = con.cursor()
# 무한 루프를 돌면서 사용자로부터 데이터를 입력받는 코드
while True:
id = input("사용자 ID 기입: ")
# 무한 루프의 탈출
# 사용자가 입력을 하지않고 엔터키를 입력한 경우 루프를 빠져나온다.
if id == "":
break
userName = input("사용자 이름 기입: ")
email = input("사용자 이메일 기입: ")
birthYear = (input("사용자 출생년도 기입: "))
# 사용자가 입력한 데이터를 이용하여 쿼리문 작성하는 코드
# 1번 statement 식의 insert into 방식
# sql = "insert into userTable values('"+id+"','"+userName+"','"+email+"',"+ birthYear+")"
# 2번 preparedStatement 식의 insert into 방식(와일드 카드 사용 방식)
# print(sql)
# statement 식을 이용하는 것보다 가독성이 좋다. 그리고 혼란을 야기하지 않는다.
# 와일드 카드의 개수를 헤아려서 그에 맞는 저장할 데이터를 제공시켜주면된다.
cur.execute("insert into userTable (id, userName, email, birthYear) values(?,?,?,?)",(id,userName,email,birthYear))
con.commit()
# 데이터 조회
# cur.execute("select * from userTable")
# while True:
# row = cur.fetchone()
# if row == None:
# break
# id = row[0]
# userName = row[1]
# email = row[2]
# birthYear = row[3]
# print("%5s %5s %5s %5d" %(id, userName, email, birthYear))
con.close()
Pythonでのデータの符号化順序の照会
上図の3番目の手順では、SELECT文でexecuteのSQL文でデータを問合せます.このとき、カーソルクエリの内容はすべてカーソルに保存されます(メモリが格納されます).
次にカーソル名です.fetchone()を使用してデータを取得します.(fetchall()すべてのデータを取得します.)この操作を繰り返して、すべてのデータを出力します.入力、変更データではないため、commit()を使用する必要はありません.
import sqlite3
# 전역변수 선언
con, cur = None, None
id, userName, email, birthYear = "","","",""
row = None # 한 행을 가져와서 저장할 전역변수
rows = None # 전체 행을 가져와서 저장할 전역변수
if __name__ == '__main__':
# DB 연결
con = sqlite3.connect("c:/PythonDB/naverDB")
# 커서 생성
cur = con.cursor()
cur.execute("select * from userTable") # 조회된 데이터 전부 저장됨
# cur.execute("select * from userTable where birthYear>=1990")
# 아래 쿼리는 출생연도 컬럼을 기준으로 오름차순 정렬을 하는 쿼리이다.
# 단, 기본값이 asc 이기 때문에 asc는 생략이 가능하다.
# cur.execute("select * from userTable order by birthYear")
# 아래 쿼리는 출생연도 컬럼을 기준으로 내림차순 정렬을 하는 쿼리이다.
# 단, 기본값이 asc 이기 때문에 asc는 생략이 가능하다. 하지만 내림차순을 하는
# desc 생략은 불가하다
# cur.execute("select * from userTable order by birthYear desc")
# 아래는 한 조건에 의해 출력하는 쿼리문이다.
# cur.execute("select * from userTable where id = 'park'")
print("사용자ID 사용자이름 이메일 출생년도")
print('--------------------------------------------')
# row = cur.fetchone() # 튜플형태로 행의 값을 리턴해준다
# print(row) # 튜플형태로 행의 값을 리턴해준다.
# 무한루프를 돌면서 1행씩 가져와서 출력을 한다.
while True:
row = cur.fetchone() # 행을 하나씩 가져온다.
if row == None: # 더이상 가져올 데이터가 없다면 탈출
break
# 한 행에 있는 데이터를 각각 전역변수에 저장후 출력
id = row[0]
userName = row[1]
email = row[2]
birthYear = row[3]
print("%5s %15s %15s %5d" %(id, userName, email, birthYear))
# print('전체 행을 한번에 가져오는 fetchall() 함수 사용')
# fetchall() 함수를 사용하면 튜플리스트 혀여태로 전체 행을 반환해준디.
# rows = cur.fetchall()
# for data in rows:
# print(data)
# DB연결 해제
con.close()
출력 결과:
사용자ID 사용자이름 이메일 출생년도
--------------------------------------------
xi xi jinping china@naver.com 1990
chirs chris pan chirs@google.com 1949
moon moon jaein moon@daum.com 1911
park kinhae park@korea.com 1998
aaa aaaa aaa@naver.com 1999
例。GUIとデータの入力と表示
# GUI(tkinter 모듈 이용) 환경을 만들어서 데이터를 입력, 출력해주는 프로그램 실습
import sqlite3
from tkinter import *
from tkinter import messagebox
# 전역 변수 선언 및 초기화
con, cur = None, None
id, userName, email, birthYear = "", "", "", ""
# "저장"버튼을 클릭했을 때, 처리하는 이벤트 핸들러 함수 insertData() 선언 및 구현
def insertData():
con = sqlite3.connect("c:/PythonDB/naverDB")
cur = con.cursor()
id = edit1.get()
userName = edit2.get()
email = edit3.get()
birthYear = edit4.get()
try:
cur.execute("insert into userTable(id, userName, email, birthYear) values(?, ?, ?, ?)",
(id, userName, email, birthYear))
except:
messagebox.showerror("오류발생","데이터 입력 오류 발생")
else:
messagebox.showinfo("저장 완료","데이터 저장 완료")
con.commit()
con.close()
def selectData():
strData1 = []; strData2 = []; strData3 = []; strData4 = []
con = sqlite3.connect("c:/PythonDB/naverDB")
cur = con.cursor()
cur.execute("select * from userTable")
# 위의 strData1 ~ 4까지의 초기화되어진 리스트에 데이터를 추가함
strData1.append("사용자 ID"); strData2.append("사용자 이름")
strData3.append("이메일"); strData4.append("출생연도")
strData1.append("----------"); strData2.append("----------")
strData3.append("----------"); strData4.append("----------")
while True:
row = cur.fetchone()
if row == None:
break
strData1.append(row[0]); strData2.append(row[1])
strData3.append(row[2]); strData4.append(row[3])
# 조회를 재차 클릭을 했을 때 리스트 박스의 내용을 전체 삭제 후 내용 출력하게끔 함.
listData1.delete(0, listData1.size()-1); listData2.delete(0, listData2.size()-1)
listData3.delete(0, listData3.size()-1); listData4.delete(0, listData4.size() - 1)
# zip() 함수는 여러 개의 순회 가능한(iterable) 객체를 인자로 받고, 각 해당 객체가 담고 있는
# 요소를 차례로 접근할 수 있게끔 반복자(iterator)를 반환한다.
# 루프를 돌면서 각각의 해당하는 요소들의 값들을 ListBox 에 추가하고 있다.
for id, userName, email, birthYear in zip(strData1, strData2, strData3, strData4):
listData1.insert(END, id); listData2.insert(END, userName)
listData3.insert(END, email); listData4.insert(END, birthYear)
con.close()
if __name__ == "__main__":
window = Tk() # 윈도우 생성
window.geometry("600x300") # 화면크기 설정
window.title("GUI 데이터 입출력") # 윈도우의 제목 설정
editFrame = Frame(window) # Frame 컨네이너를 윈도우에 생성함
# pack()는 기본 값으로 side 매개변수에 TOP 값을 가진다.하여 위로 정렬시키면서
# Frame 컨테이너 속의 위젯들을 중앙 배치를 해준다.
editFrame.pack()
# 조회결과를 출력할 Frame 컨테이너를 윈도우에 생성함.
listFrame = Frame(window)
listFrame.pack(side=BOTTOM, fill=BOTH, expand=1)
# 위젯들 배치(editFrame 배치)
# Entry 위젯에서 width 속성은 픽셀값이 아니고, 텍스트 단위임을 상기하자.
edit1 = Entry(editFrame, width=10); edit1.pack(side=LEFT, padx=10, pady=10)
edit2 = Entry(editFrame, width=10); edit2.pack(side=LEFT, padx=10, pady=10)
edit3 = Entry(editFrame, width=10); edit3.pack(side=LEFT, padx=10, pady=10)
edit4 = Entry(editFrame, width=10); edit4.pack(side=LEFT, padx=10, pady=10)
# 데이터를 저장하는 버튼이며 insertData()를 이벤트 핸들러로 등록함.
btnInsert = Button(editFrame, text="저장", command=insertData)
btnInsert.pack(side=LEFT, padx=10, pady=10)
# 데이터를 조회하는 버튼이며 selectData()를 이벤트 핸들러로 등록함.
btnSelect = Button(editFrame, text="조회", command=selectData)
btnSelect.pack(side=LEFT, padx=10, pady=10)
# listFrame 컨테이너에 ListBox 위젯을 만들어서 레이아웃 배치를 한다.
# 리스트 박스는 여러 문자열을 위에서 아래로 나열할 때 사용하는 위젯이다.
listData1 = Listbox(listFrame, bg="yellow")
# pack()는 기본 값으로 side 매개변수에 LEFT 값을 주어 왼쪽 기준 정렬이 되며,
# 할당된 공간 양쪽을 다 채우고, 할당되지 않은 미사용 공간을 현재 위젯의 할당된
# 공간으로 변경한다.
listData1.pack(side=LEFT, fill=BOTH, expand=1)
listData2 = Listbox(listFrame, bg="yellow")
listData2.pack(side=LEFT, fill=BOTH, expand=1)
listData3 = Listbox(listFrame, bg="yellow")
listData3.pack(side=LEFT, fill=BOTH, expand=1)
listData4 = Listbox(listFrame, bg="yellow")
listData4.pack(side=LEFT, fill=BOTH, expand=1)
window.mainloop()
Reference
この問題について(第23章.単純データベース), 我々は、より多くの情報をここで見つけました https://velog.io/@raed123456/23장.-간단한-데이터베이스テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol