在[上一講](https://github.com/qiwsir/ITArticles/blob/master/BasicPython/302.md)中已經連接了數據庫。就數據庫而言,連接之后就要對其操作。但是,目前那個名字叫做qiwsirtest的數據僅僅是空架子,沒有什么可操作的,要操作它,就必須在里面建立“表”,什么是數據庫的表呢?下面摘抄自維基百科對數據庫表的簡要解釋,要想詳細了解,需要看官在找一些有關數據庫的教程和書籍來看看。
> 在關系數據庫中,**數據庫表**是一系列二維數組的集合,用來代表和儲存數據對象之間的關系。它由縱向的列和橫向的行組成,例如一個有關作者信息的名為 authors 的表中,每個列包含的是所有作者的某個特定類型的信息,比如“姓氏”,而每行則包含了某個特定作者的所有信息:姓、名、住址等等。
>
> 對于特定的數據庫表,列的數目一般事先固定,各列之間可以由列名來識別。而行的數目可以隨時、動態變化,每行通常都可以根據某個(或某幾個)列中的數據來識別,稱為候選鍵。
我打算在qiwsirtest中建立一個存儲用戶名、用戶密碼、用戶郵箱的表,其結構用二維表格表現如下:
| username | password | email |
| --- | --- | --- |
| qiwsir | 123123 | [qiwsir@gmail.com](mailto:qiwsir@gmail.com) |
特別說明,這里為了簡化細節,突出重點,對密碼不加密,直接明文保存,雖然這種方式是很不安全的。但是,有不少網站還都這么做的,這么做的目的是比較可惡的。就讓我在這里,僅僅在這里可惡一次。
## 建數據庫表并插入數據
為了在數據庫中建立這個表,需要進入到`mysql>`交互模式中操作。道理在于,如果qiwsirtest這個屋子里面沒有類似家具的各種數據庫表,即使進了屋子也沒有什么好操作的東西,因此需要先到`mysql>`模式下在屋子里面擺家具。
進入數據庫交互模式:
~~~
qw@qw-Latitude-E4300:~$ mysql -u root -p
Enter password:
~~~
調用已經建立的數據庫:qiwsirtest
~~~
mysql> use qiwsirtest;
Database changed
mysql> show tables;
Empty set (0.00 sec)
~~~
用`show tables`命令顯示這個數據庫中是否有數據表了。查詢結果顯示為空。
下面就用如下命令建立一個數據表,這個數據表的內容就是上面所說明的。
~~~
mysql> create table users(id int(2) not null primary key auto_increment,username varchar(40),password text,email text)default charset=utf8;
Query OK, 0 rows affected (0.12 sec)
~~~
建立的這個數據表名稱是:users,其中包含上述字段,可以用下面的方式看一看這個數據表的結構。
~~~
mysql> show tables;
+----------------------+
| Tables_in_qiwsirtest |
+----------------------+
| users |
+----------------------+
1 row in set (0.00 sec)
~~~
查詢顯示,在qiwsirtest這個數據庫中,已經有一個表,它的名字是:users。
~~~
mysql> desc users;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(2) | NO | PRI | NULL | auto_increment |
| username | varchar(40) | YES | | NULL | |
| password | text | YES | | NULL | |
| email | text | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
~~~
顯示表users的結構:
* id:每增加一個用戶,id號自動增加一個。
* username:存儲用戶名,類型是varchar(40)
* password:存儲用戶密碼,類型是text
* email:存儲用戶的郵箱,類型是text
特別提醒:在這里,我沒有對每個字段做注入不得為空等設置,在真正的開發中,或許必須讓username和password不得為空。
這個結構和上面所期望的結構是一樣的,只不過這個表中還沒有任何數據,是一個空表。可以查詢一下看看:
~~~
mysql> select * from users;
Empty set (0.01 sec)
~~~
目前表是空的,為了能夠在后面用python操作這個數據表,需要向里面插入點信息,就只插入一條吧。
~~~
mysql> insert into users(username,password,email) values("qiwsir","123123","qiwsir@gmail.com");
Query OK, 1 row affected (0.05 sec)
mysql> select * from users;
+----+----------+----------+------------------+
| id | username | password | email |
+----+----------+----------+------------------+
| 1 | qiwsir | 123123 | qiwsir@gmail.com |
+----+----------+----------+------------------+
1 row in set (0.00 sec)
~~~
到目前為止,在`mysql>`中的工作已經完成了,接下來就是用python操作了。
## python操作數據庫
要對數據庫進行操作,需要先連接它。上一講看官連接過了,但是,隨后你關閉了python的交互模式,所以還要從新連接。這也是交互模式的缺點。不過在這里操作直觀,所以暫且忍受一下,后面就會講解如何在程序中自動完成了。
~~~
>>> import MySQLdb
>>> conn = MySQLdb.connect(host="localhost",user="root",passwd="123123",db="qiwsirtest",charset="utf8")
~~~
完成連接的過程,其實是建立了一個`MySQLdb.connect()`的實例對象conn,那么這個對象有哪些屬性呢?
* commit():如果數據庫表進行了修改,提交保存當前的數據。當然,如果此用戶沒有權限就作罷了,什么也不會發生。
* rollback():如果有權限,就取消當前的操作,否則報錯。
* cursor([cursorclass]):游標指針。下面詳解。
連接成功之后,開始操作。注意:MySQLdb用游標(指針)cursor的方式操作數據庫,就是這樣:
~~~
>>> cur = conn.cursor()
~~~
因該模塊底層其實是調用CAPI的,所以,需要先得到當前指向數據庫的指針。這也就提醒我們,在操作數據庫的時候,指針會移動,如果移動到數據庫最后一條了,再查,就查不出什么來了。看后面的例子就明白了。
下面用cursor()提供的方法來進行操作,方法主要是:
1. 執行命令
2. 接收結果
### cursor執行命令的方法:
* execute(query, args):執行單條sql語句。query為sql語句本身,args為參數值的列表。執行后返回值為受影響的行數。
* executemany(query, args):執行單條sql語句,但是重復執行參數列表里的參數,返回值為受影響的行數
例如,要在數據表users中插入一條記錄,使得:username="python",password="123456",email="[python@gmail.com](mailto:python@gmail.com)",這樣做:
~~~
>>> cur.execute("insert into users (username,password,email) values (%s,%s,%s)",("python","123456","python@gmail.com"))
1L
~~~
沒有報錯,并且返回一個"1L"結果,說明有一行記錄操作成功。不妨用"mysql>"交互方式查看一下:
~~~
mysql> select * from users;
+----+----------+----------+------------------+
| id | username | password | email |
+----+----------+----------+------------------+
| 1 | qiwsir | 123123 | qiwsir@gmail.com |
+----+----------+----------+------------------+
1 row in set (0.00 sec)
~~~
咦,奇怪呀。怎么沒有看到增加的那一條呢?哪里錯了?可是上面也沒有報錯呀。
在這里,特別請列位看官注意,通過"cur.execute()"對數據庫進行操作之后,沒有報錯,完全正確,但是不等于數據就已經提交到數據庫中了,還必須要用到"MySQLdb.connect"的一個屬性:commit(),將數據提交上去,也就是進行了"cur.execute()"操作,要將數據提交,必須執行:
~~~
>>> conn.commit()
~~~
在到"mysql>"中運行"select * from users"試一試:
~~~
mysql> select * from users;
+----+----------+----------+------------------+
| id | username | password | email |
+----+----------+----------+------------------+
| 1 | qiwsir | 123123 | qiwsir@gmail.com |
| 2 | python | 123456 | python@gmail.com |
+----+----------+----------+------------------+
2 rows in set (0.00 sec)
~~~
good,very good。果然如此。這就如同編寫一個文本一樣,將文字寫到文本上,并不等于文字已經保留在文本文件中了,必須執行"CTRL-S"才能保存。也就是在通過python操作數據庫的時候,以"execute()"執行各種sql語句之后,要讓已經執行的效果保存,必須運行"commit()",還要提醒,這個屬性是"MySQLdb.connect()"實例的。
再嘗試一下插入多條的那個命令"executemany(query,args)".
~~~
>>> cur.executemany("insert into users (username,password,email) values (%s,%s,%s)",(("google","111222","g@gmail.com"),("facebook","222333","f@face.book"),("github","333444","git@hub.com"),("docker","444555","doc@ker.com")))
4L
>>> conn.commit()
~~~
到"mysql>"里面看結果:
~~~
mysql> select * from users;
+----+----------+----------+------------------+
| id | username | password | email |
+----+----------+----------+------------------+
| 1 | qiwsir | 123123 | qiwsir@gmail.com |
| 2 | python | 123456 | python@gmail.com |
| 3 | google | 111222 | g@gmail.com |
| 4 | facebook | 222333 | f@face.book |
| 5 | github | 333444 | git@hub.com |
| 6 | docker | 444555 | doc@ker.com |
+----+----------+----------+------------------+
6 rows in set (0.00 sec)
~~~
成功插入了多條記錄。特別請列位注意的是,在"executemany(query,args)"中,query還是一條sql語句,但是args這時候是一個tuple,這個tuple里面的元素也是tuple,每個tuple分別對應sql語句中的字段列表。這句話其實被執行多次。只不過執行過程不顯示給我們看罷了。
已經會插入了,然后就可以有更多動作。且看下一講吧。
- 第零部分 獨上高樓,望盡天涯路
- 嘮叨一些關于Python的事情
- 為什么要開設本欄目
- 第一部分 積小流,至江海
- Python環境安裝
- 集成開發環境(IDE)
- 數的類型和四則運算
- 啰嗦的除法
- 開始真正編程
- 初識永遠強大的函數
- 玩轉字符串(1):基本概念、字符轉義、字符串連接、變量與字符串關系
- 玩轉字符串(2)
- 玩轉字符串(3)
- 眼花繚亂的運算符
- 從if開始語句的征程
- 一個免費的實驗室
- 有容乃大的list(1)
- 有容乃大的list(2)
- 有容乃大的list(3)
- 有容乃大的list(4)
- list和str比較
- 畫圈還不簡單嗎
- 再深點,更懂list
- 字典,你還記得嗎?
- 字典的操作方法
- 有點簡約的元組
- 一二三,集合了
- 集合的關系
- Python數據類型總結
- 深入變量和引用對象
- 賦值,簡單也不簡單
- 坑爹的字符編碼
- 做一個小游戲
- 不要紅頭文件(1): open, write, close
- 不要紅頭文件(2): os.stat, closed, mode, read, readlines, readline
- 第二部分 窮千里目,上一層樓
- 正規地說一句話
- print能干的事情
- 從格式化表達式到方法
- 復習if語句
- 用while來循環
- 難以想象的for
- 關于循環的小伎倆
- 讓人歡喜讓人憂的迭代
- 大話題小函數(1)
- 大話題小函數(2)
- python文檔
- 重回函數
- 變量和參數
- 總結參數的傳遞
- 傳說中的函數條規
- 關于類的基本認識
- 編寫類之一創建實例
- 編寫類之二方法
- 編寫類之三子類
- 編寫類之四再論繼承
- 命名空間
- 類的細節
- Import 模塊
- 模塊的加載
- 私有和專有
- 折騰一下目錄: os.path.<attribute>
- 第三部分 昨夜西風,亭臺誰登
- 網站的結構:網站組成、MySQL數據庫的安裝和配置、MySQL的運行
- 通過Python連接數據庫:安裝python-MySQLdb,連接MySQL
- 用Pyton操作數據庫(1):建立連接和游標,并insert and commit
- 用Python操作數據庫(2)
- 用Python操作數據庫(3)
- python開發框架:框架介紹、Tornado安裝
- Hello,第一個網頁分析:tornado網站的基本結構剖析:improt模塊、RequestHandler, HTTPServer, Application, IOLoop
- 實例分析get和post:get()通過URL得到數據和post()通過get_argument()獲取數據
- 問候世界:利用GAE建立tornado框架網站
- 使用表單和模板:tornado模板self.render和模板變量傳遞
- 模板中的語法:tornado模板中的for,if,set等語法
- 靜態文件以及一個項目框架
- 模板轉義
- 第四部分 暮然回首,燈火闌珊處
- requests庫
- 比較json/dictionary的庫
- defaultdict 模塊和 namedtuple 模塊
- 第五部分 Python備忘錄
- 基本的(字面量)值
- 運算符
- 常用的內建函數
- 擴展閱讀(來自網絡文章)
- 人生苦短,我用Python