1. 程式人生 > 資料庫 >Python之pymysql的使用小結

Python之pymysql的使用小結

在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)

連線資料庫:

import pymysql

#連線資料庫
db = pymysql.connect("localhost","root","LBLB1212@@","dbforpymysql")

#使用cursor()方法建立一個遊標物件
cursor = db.cursor()

#使用execute()方法執行SQL語句
cursor.execute("SELECT * FROM userinfo")

#使用fetall()獲取全部資料
data = cursor.fetchall()

#列印獲取到的資料
print(data)

#關閉遊標和資料庫的連線
cursor.close()
db.close()

#執行結果
((1,'frank',(2,'rose',(3,'jeff','666'))

要完成一個MySQL資料的連線,在connect中可以接受以下引數:

def __init__(self,host=None,user=None,password="",database=None,port=0,unix_socket=None,charset='',sql_mode=None,read_default_file=None,conv=None,use_unicode=None,client_flag=0,cursorclass=Cursor,init_command=None,connect_timeout=10,ssl=None,read_default_group=None,compress=None,named_pipe=None,no_delay=None,autocommit=False,db=None,passwd=None,local_infile=False,max_allowed_packet=16*1024*1024,defer_connect=False,auth_plugin_map={},read_timeout=None,write_timeout=None,bind_address=None):
引數解釋:
host: Host where the database server is located  #主機名或者主機地址
user: Username to log in as  #使用者名稱
password: Password to use.  #密碼
database: Database to use,None to not use a particular one.  #指定的資料庫
port: MySQL port to use,default is usually OK. (default: 3306)  #埠,預設是3306
bind_address: When the client has multiple network interfaces,specify
  the interface from which to connect to the host. Argument can be
  a hostname or an IP address.  #當客戶端有多個網路介面的時候,指點連線到資料庫的介面,可以是一個主機名或者ip地址
unix_socket: Optionally,you can use a unix socket rather than TCP/IP.
charset: Charset you want to use.  #指定字元編碼
sql_mode: Default SQL_MODE to use. 
read_default_file:
  Specifies my.cnf file to read these parameters from under the [client] section.
conv:
  Conversion dictionary to use instead of the default one.
  This is used to provide custom marshalling and unmarshaling of types.
  See converters.
use_unicode:
  Whether or not to default to unicode strings.
  This option defaults to true for Py3k.
client_flag: Custom flags to send to MySQL. Find potential values in constants.CLIENT.
cursorclass: Custom cursor class to use.
init_command: Initial SQL statement to run when connection is established.
connect_timeout: Timeout before throwing an exception when connecting.
  (default: 10,min: 1,max: 31536000)
ssl:
  A dict of arguments similar to mysql_ssl_set()'s parameters.
  For now the capath and cipher arguments are not supported.
read_default_group: Group to read from in the configuration file.
compress; Not supported
named_pipe: Not supported
autocommit: Autocommit mode. None means use server default. (default: False)
local_infile: Boolean to enable the use of LOAD DATA LOCAL command. (default: False)
max_allowed_packet: Max size of packet sent to server in bytes. (default: 16MB)
  Only used to limit size of "LOAD LOCAL INFILE" data packet smaller than default (16KB).
defer_connect: Don't explicitly connect on contruction - wait for connect call.
  (default: False)
auth_plugin_map: A dict of plugin names to a class that processes that plugin.
  The class will take the Connection object as the argument to the constructor.
  The class needs an authenticate method taking an authentication packet as
  an argument. For the dialog plugin,a prompt(echo,prompt) method can be used
  (if no authenticate method) for returning a string from the user. (experimental)
db: Alias for database. (for compatibility to MySQLdb)
passwd: Alias for password. (for compatibility to MySQLdb)

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,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,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",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","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",%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",("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","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,'123')
(2,'321')

使用fetchall():

import pymysql
config={
  "host":"127.0.0.1","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,'666'),(5,'bob',(8,'jack',(10,'zed','123'))
()

可以看到,第二次獲取的時候,什麼資料都沒有獲取到,這個類似於檔案的讀取操作。

預設情況下,我們獲取到的返回值是元組,只能看到每行的資料,卻不知道每一列代表的是什麼,這個時候可以使用以下方式來返回字典,每一行的資料都會生成一個字典:

cursor = db.cursor(cursor=pymysql.cursors.DictCursor) #在例項化的時候,將屬性cursor設定為pymysql.cursors.DictCursor

使用fetchall獲取所有行的資料,每一行都被生成一個字典放在列表裡面:

import pymysql
config={
  "host":"127.0.0.1","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',{'id': 8,'username': 'jack',{'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,'passwd': '123'}]
[{'id': 1,'passwd': '123'}]

上下文管理器

在python的檔案操作中支援上下文管理器,在操作資料庫的時候也可以使用:

import pymysql
config={
  "host":"127.0.0.1","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,'passwd': '123'}
{'id': 5,'passwd': '123'}

上下文管理器可以使程式碼的可讀性更強。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。