Python中pymssql 的使用操作
在python3.x中,可以使用pymysql來MySQL數據庫的連接,並實現數據庫的各種操作,本次博客主要介紹了pymysql的安裝和使用方法。
PyMySQL的安裝
一、.windows上的安裝方法:
在python3.6中,自帶pip3,所以在python3中可以直接使用pip3去安裝所需的模塊:
pip3 install pymysql -i https://pypi.douban.com/simple
二、.linux下安裝方法:
1.tar包下載及解壓
下載tar包
wget https://pypi.python.org/packages/29/f8/919a28976bf0557b7819fd6935bfd839118aff913407ca58346e14fa6c86/PyMySQL-0.7.11.tar.gz#md5=167f28514f4c20cbc6b1ddf831ade772
解壓並展開tar包
tar xf PyMySQL-0.7.11.tar.gz
2.安裝
[root@localhost PyMySQL-0.7.11]# python36 setup.py install
數據庫的連接
本次測試創建的數據及表:
#創建數據庫及表,然后插入數據
mysql> create database dbforpymysql;
mysql> create table userinfo(id int not null auto_increment primary key,username varchar(10),passwd varchar(10))engine=innodb default charset=utf8;
mysql> insert into userinfo(username,passwd) values('frank','123'),('rose','321'),('jeff',666);
#查看表內容
mysql> select * from userinfo;
+----+----------+--------+
| id | username | passwd |
+----+----------+--------+
| 1 | frank | 123 |
| 2 | rose | 321 |
| 3 | jeff | 666 |
+----+----------+--------+
3 rows in set (0.00 sec)
連接數據庫:
# -*- coding: utf-8 -*-
import pymysql #連接數據庫db = pymysql.connect("localhost","root","LBLB1212@@","dbforpymysql",,charset='cp936')#使用cursor()方法創建一個游標對象cursor = db.cursor() SQL = 'SELECT * FROM userinfo'#使用execute()方法執行SQL語句cursor.execute(sql.encode('cp936'))
#使用fetall()獲取全部數據data = cursor.fetchall() #打印獲取到的數據print(data) #關閉游標和數據庫的連接cursor.close()db.close() #運行結果((1, 'frank', '123'), (2, 'rose', '321'), (3, 'jeff', '666'))
要完成一個MySQL數據的連接,在connect中可以接受以下參數:
參數
cursor其實是調用了cursors模塊下的Cursor的類,這個模塊主要的作用就是用來和數據庫交互的,當你實例化了一個對象的時候,你就可以調用對象下面的各種綁定方法:
class Cursor(object):
"""
This is the object you use to interact with the database.
"""
def close(self):
"""
Closing a cursor just exhausts all remaining data.
"""
def setinputsizes(self, *args):
"""Does nothing, required by DB API."""
def setoutputsizes(self, *args):
"""Does nothing, required by DB API."""
def execute(self, query, args=None):
"""Execute a query
:param str query: Query to execute.
:param args: parameters used with query. (optional)
:type args: tuple, list or dict
:return: Number of affected rows
:rtype: int
If args is a list or tuple, %s can be used as a placeholder in the query.
If args is a dict, %(name)s can be used as a placeholder in the query.
"""
def executemany(self, query, args):
# type: (str, list) -> int
"""Run several data against one query
:param query: query to execute on server
:param args: Sequence of sequences or mappings. It is used as parameter.
:return: Number of rows affected, if any.
This method improves performance on multiple-row INSERT and
REPLACE. Otherwise it is equivalent to looping over args with
execute().
"""
def fetchone(self):
"""Fetch the next row"""
def fetchmany(self, size=None):
"""Fetch several rows"""
def fetchall(self):
"""Fetch all the rows"""
......
數據庫操作
一、數據庫增刪改操作
commit()方法:在數據庫里增、刪、改的時候,必須要進行提交,否則插入的數據不生效。
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES('jack','123')"
cursor.execute(sql)
db.commit() #提交數據
cursor.close()
db.close()
或者在execute提供插入的數據
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES(%s,%s)"
cursor.execute(sql,("bob","123"))
db.commit() #提交數據
cursor.close()
db.close()
小知識點,mysql的注入問題:
在mysql中使用"--"代表注釋,比如現在來實現一個用戶登錄的小程序:
用戶名和密碼都存在表userinfo中,表內容如下:
mysql> select * from userinfo;
+----+----------+--------+
| id | username | passwd |
+----+----------+--------+
| 1 | frank | 123 |
| 2 | rose | 321 |
| 3 | jeff | 666 |
+----+----------+--------+
3 rows in set (0.00 sec)
小程序代碼如下:
import pymysql
user = input("username:")
pwd = input("password:")
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
sql = "select * from userinfo where username='%s' and passwd='%s'" %(user,pwd)
result=cursor.execute(sql)
cursor.close()
db.close()
if result:
print('登錄成功')
else:
print('登錄失敗')
#正確登錄的運行結果
username:frank
password:123
result: 1
登錄成功
#錯誤登錄的運行結果
username:frank
password:1231231
result: 0
登錄失敗
看起來沒有什么問題,但是試試下面的方式吧
----------------------------------------------
username:' or 1=1 --
password:123
result: 3
登錄成功
----------------------------------------------
咦~也登錄成功了.
為什么呢?可以看一下現在的執行的sql語句:
select * from userinfo where username='' or 1=1 -- ' and passwd='123'
這里--后面的會被注釋,所以where一定會成功,這里等於查看了所有行的內容,返回值也不等於0,所以就登錄成功了。
解決方法就是將變量或者實參直接寫到execute中即可:
result=cursor.execute(sql,(user,pwd))
在鍵入類似' or 1=1 -- 的時候就不會登錄成功了。
executemany():用來同時插入多條數據:
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES(%s,%s)"
cursor.executemany(sql,[("tom","123"),("alex",'321')])
db.commit() #提交數據
cursor.close()
db.close()
execute()和executemany()都會返回受影響的行數:
sql = "delete from userinfo where username=%s"
res = cursor.executemany(sql,("jack",))
print("res=",res)
#運行結果
res= 1
當表中有自增的主鍵的時候,可以使用lastrowid來獲取最后一次自增的ID:
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES(%s,%s)"
cursor.execute(sql,("zed","123"))
print("the last rowid is ",cursor.lastrowid)
db.commit() #提交數據
cursor.close()
db.close()
#運行結果
the last rowid is 10
二、數據庫的查詢操作
這里主要介紹三個綁定方法:
fetchone():獲取下一行數據,第一次為首行;
fetchall():獲取所有行數據源
fetchmany(4):獲取下4行數據
先來查看表的內容:
mysql> select * from userinfo;
+----+----------+--------+
| id | username | passwd |
+----+----------+--------+
| 1 | frank | 123 |
| 2 | rose | 321 |
| 3 | jeff | 666 |
| 5 | bob | 123 |
| 8 | jack | 123 |
| 10 | zed | 123 |
+----+----------+--------+
6 rows in set (0.00 sec)
使用fetchone():
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchone() #第一次執行
print(res)
res = cursor.fetchone() #第二次執行
print(res)
cursor.close()
db.close()
#運行結果
(1, 'frank', '123')
(2, 'rose', '321')
使用fetchall():
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchall() #第一次執行
print(res)
res = cursor.fetchall() #第二次執行
print(res)
cursor.close()
db.close()
#運行結果
((1, 'frank', '123'), (2, 'rose', '321'), (3, 'jeff', '666'), (5, 'bob', '123'), (8, 'jack', '123'), (10, 'zed', '123'))
()
可以看到,第二次獲取的時候,什么數據都沒有獲取到,這個類似於文件的讀取操作。
默認情況下,我們獲取到的返回值是元組,只能看到每行的數據,卻不知道每一列代表的是什么,這個時候可以使用以下方式來返回字典,每一行的數據都會生成一個字典:
cursor = db.cursor(cursor=pymysql.cursors.DictCursor) #在實例化的時候,將屬性cursor設置為pymysql.cursors.DictCursor
使用fetchall獲取所有行的數據,每一行都被生成一個字典放在列表里面:
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchall()
print(res)
cursor.close()
db.close()
#運行結果
[{'id': 1, 'username': 'frank', 'passwd': '123'}, {'id': 2, 'username': 'rose', 'passwd': '321'}, {'id': 3, 'username': 'jeff', 'passwd': '666'}, {'id': 5, 'username': 'bob', 'passwd': '123'}, {'id': 8, 'username': 'jack', 'passwd': '123'}, {'id': 10, 'username': 'zed', 'passwd': '123'}]
這樣獲取到的內容就能夠容易被理解和使用了!
在獲取行數據的時候,可以理解開始的時候,有一個行指針指着第一行的上方,獲取一行,它就向下移動一行,所以當行指針到最后一行的時候,就不能再獲取到行的內容,所以我們可以使用如下方法來移動行指針:
cursor.scroll(1,mode='relative') # 相對當前位置移動
cursor.scroll(2,mode='absolute') # 相對絕對位置移動
第一個值為移動的行數,整數為向下移動,負數為向上移動,mode指定了是相對當前位置移動,還是相對於首行移動
例如:
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchall()
print(res)
cursor.scroll(0,mode='absolute') #相對首行移動了0,就是把行指針移動到了首行
res = cursor.fetchall() #第二次獲取到的內容
print(res)
#運行結果
[{'id': 1, 'username': 'frank', 'passwd': '123'}, {'id': 2, 'username': 'rose', 'passwd': '321'}, {'id': 3, 'username': 'jeff', 'passwd': '666'}, {'id': 5, 'username': 'bob', 'passwd': '123'}, {'id': 8, 'username': 'jack', 'passwd': '123'}, {'id': 10, 'username': 'zed', 'passwd': '123'}]
[{'id': 1, 'username': 'frank', 'passwd': '123'}, {'id': 2, 'username': 'rose', 'passwd': '321'}, {'id': 3, 'username': 'jeff', 'passwd': '666'}, {'id': 5, 'username': 'bob', 'passwd': '123'}, {'id': 8, 'username': 'jack', 'passwd': '123'}, {'id': 10, 'username': 'zed', 'passwd': '123'}]
上下文管理器
在python的文件操作中支持上下文管理器,在操作數據庫的時候也可以使用:
import pymysql
config={
"host":"127.0.0.1",
"user":"root",
"password":"LBLB1212@@",
"database":"dbforpymysql"
}
db = pymysql.connect(**config)
with db.cursor(cursor=pymysql.cursors.DictCursor) as cursor: #獲取數據庫連接的對象
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchone()
print(res)
cursor.scroll(2,mode='relative')
res = cursor.fetchone()
print(res)
cursor.close()
db.close()
#運行結果
{'id': 1, 'username': 'frank', 'passwd': '123'}
{'id': 5, 'username': 'bob', 'passwd': '123'}
上下文管理器可以使代碼的可讀性更強。