mysql-2:python操作mysql


https://www.cnblogs.com/UncleYong/p/10938993.html
Python使用MySQL數據庫的方法以及一個實例:
https://www.cnblogs.com/itdyb/p/5700614.html
https://www.cnblogs.com/xichenHome/p/11622143.html#python連接數據庫

1、python操作mysql

安裝MySQL-Python的包:

pip install pymysql——import pymysql
# pip install MySQLClient——import MySQLdb


# 注意:MySQLdb和pymysql區別
    MySQLdb是用於python連接Mysql數據庫的接口,它實現了python數據庫API規范V2.0,基於 MySQL C API 上建立的。
MySQLdb只支持Python2.,還不支持3.可以用PyMySQL代替。安裝方法:pip install PyMySQL
然后在需要的項目中,把 init.py中添加兩行:
import pymysql
pymysql.install_as_MySQLdb()
就可以用 import MySQLdb了。
  • python數據庫接口支持非常多的數據庫,可以選擇適合你項目的數據庫:
    MySQL,PostgreSQL,Microsoft SQL Server 2000,Oracle,Sybase
    具體查看:https://wiki.python.org/moin/DatabaseInterfaces

  • python安裝插件Database Navigator插件查看數據庫,

windows版本,改時區,python連接成功:
show variables like '%time_zone%';
set global time_zone='+8:00';
  • MySQLdb._exceptions.IntegrityError: (1062, "Duplicate entry '1' for key 'PRIMARY'")
    是因為對於鍵xxxxx已經存在一個值為“xx”了,所以當插入重復的值時就會提示該錯誤。一般是由於字段設置了unique導致的。我自己更改:在客戶端右鍵-設計表,主鍵,再次執行代碼后,刷新表就OK。

  • mysql中插入數據時Duplicate entry '' for key 'PRIMARY'的解決方案:https://blog.csdn.net/zhangyr_student/article/details/80119238
    REPLACE INTO Table_name() VALUES(1,1),(2,2),(3,3)

2、方法說明

(1)Connection支持的方法:

    方法名 說明 
    cursor() 創建並且返回游標 
    commit() 提交當前事物 
    rollback() 回滾當前事物 
    close() 關閉Connection 


# 1、cursor用來執行命令的方法:
callproc(self, procname, args):用來執行存儲過程,接收的參數為存儲過程名和參數列表,返回值為受影響的行數
execute(self, query, args):執行單條sql語句,接收的參數為sql語句本身和使用的參數列表,返回值為受影響的行數
executemany(self, query, args):執行單挑sql語句,但是重復執行參數列表里的參數,返回值為受影響的行數
nextset(self):移動到下一個結果集

(2)獲取Cursor游標對象,用於執行查詢和獲取結果,它支持的方法如下:

# cursor用來接收返回值的方法:
    方法名 說明 
    execute() 用於執行一個數據庫的查詢命令, 將一個結果從數據庫獲取到客戶端
    fetch*(),移動rownumber,返回數據。

    fetchall() 獲取結果集中剩下的所有行
    fetchone() 返回一條結果行
    fetchmany(size)獲取結果集中的下(size)行 
     
    rowcount 最近一次execute返回數據/影響的行數 
    close() 關閉游標 

    cursor.scroll(2,mode='relative')移動指針到某一行。
# 如果mode='relative',則表示從當前所在行移動value條,
# 如果 mode='absolute',則表示從結果集的第一行移動value條.

3、具體操作

說明:

  • 創建Connection,創建了Python客戶端與數據庫之間的網絡通路。類型string,db是數據庫名,charset連接字符集

(0)格式

import pymysql
from pymysql.cursors import DictCursor<br data-filtered="filtered"> 

1、建立數據庫連接對象 conn
conn = pymysql.connect(host='192.168.199.128',port=3306,user='root',passwd='123456',db='2019-1229',charset='utf8')

2、獲取游標:通過coon.cursor() 創建操作sql的 游標對象
# 注:游標不設置參數,查詢的結果就是“數據元組”,數據沒有標識性;
# 設置pymysql.cursors.DictCursor,查詢的結果是“字典”,key是表的字段
cursor=coon.cursor() 
cursor=coon.cursor(DictCursor)   # 建立游標,指定游標類型,返回字典
cursor=conn.cursor(pymysql.cursors.DictCursor)

3、編寫sql交給 cursor 執行;——————更改3 該部分就可以
# 如果是查詢,通過 cursor對象 獲取結果
# sql = 'create table t1(id int, x int, y int)' # 使用sql語句創建表
sql='select * from ch0;'
# sql='select * from ch0 limit 2;'  # 操作語句,只查詢前兩行

rows=cursor.execute(sql)  # 返回結果是受影響的行數
res = cursor.fetchall()   # 獲取查詢的所有結果
print(res)                # 打印結果


4、
conn.commit()     # 提交
cursor.close()    # 關閉游標
conn.close()      # 關閉連接

# 判斷是否連接成功
if rows >= 0:
    print('連接數據庫成功')
else:
    print('連接數據庫失敗')  

(1)插入數據:單條,多條,大批量

1、增加數據:單條和多條
# 注意都可以定義成一個變量:cursor.execute(sql, value)
sql='insert into test(id,name) values(%s,%s)'
rows=cursor.execute(sql, ('4', 'qzcsbj4'))    # 插入單條
rows=cursor.executemany(sql,[('5','qzcsbj5'),('6','qzcsbj6'),('7','qzcsbj7')]) # 插入多條

2、大批量新增,執行sql語句
#cursor=conn.cursor(pymysql.cursors.DictCursor)
values=[]
for i in range(100, 110):
    values.append((i, 'qzcsbj'+str(i)))
sql='insert into ch0(id,name) values(%s,%s)'
rows=cursor.executemany(sql,values)

(2)修改數據,更新操作

# 刪除上面大批量????
delete from test where id>=100;  

sql='update test set name = %s where id = %s'
# 單條
rows=cursor.execute(sql,('qzcsbj','7'))
# 多條
rows=cursor.executemany(sql,[('全棧測試筆記5','5'),('全棧測試筆記6','6')])

(3)刪除數據????

sql='delete from test where id = %s'
# 單條
rows=cursor.execute(sql,('1',)) 
???對比測試,cursor.execute(sql,1)
# 多條
rows=cursor.executemany(sql,[('2'),('3')]) 

(4)查詢數據???

  • fetchone,有點像從管道中取一個,如果再來一個fetchone,會又取下一個,如果取完了再取,就返回None。
    每條記錄為元組格式
  • fetchmany
一、查看t1表里的所有數據
sql = 'select * from t1'
row = cursor.execute(sql)  # 返回值是受影響的行
print(row)

二、如果是查詢,通過 cursor對象 獲取結果
# 1.fetchone() 偏移一條取出
sql = 'select * from t1'
row = cursor.execute(sql)
r1 = cursor.fetchone()
print(r1)

    1、fetchone
    # 執行sql語句,每條記錄為字典
    rows=cursor.execute('select * from test;')
    print(cursor.fetchone())   # 運行結果:(7, 'qzcsbj')
    print(cursor.fetchone())   # 若是最后結束,None
    # 每條記錄為字典格式
    cursor=conn.cursor(pymysql.cursors.DictCursor)
    rows=cursor.execute('select * from test;')
    print(cursor.fetchone())   # 運行結果:{'id': 7, 'name': 'qzcsbj'}
    
# 2.fetchmany(n) 偏移n條取出  
  
    2、fetchmany
    print(cursor.fetchmany(2)) 
    # 運行結果:[{'id': 4, 'name': 'qzcsbj4'}, {'id': 5, 'name': '全棧測試筆記5'}] 
 
# 3.fetchall() 偏移剩余全部  

    3、fetchall
    print(cursor.fetchall())
    print(cursor.fetchall())
    # 運行結果:[{'id': 4, 'name': 'qzcsbj4'}, {'id': 5, 'name': '全棧測試筆記5'}, {'id': 6, 'name': '全棧測試筆記6'}, {'id': 7, 'name': 'qzcsbj'}]
    #[] ,因為后面沒有記錄了,所以取出來是空的列表

(5)游標操作

    (1)相對絕對位置移動,從頭開始跳過n個
    cursor.scroll(3,mode='absolute')
    print(cursor.fetchone())
    # 運行結果:{'id': 7, 'name': 'qzcsbj'}
    
    (2)相對當前位置移動,
    rows=cursor.execute('select * from test;')
    print(cursor.fetchone())
    cursor.scroll(2,mode='relative')
    print(cursor.fetchone())
    # 運行結果:{'id': 4, 'name': 'qzcsbj4'}
    # {'id': 7, 'name': 'qzcsbj'} 


row = cursor.execute(sql)
if row:
    r1 = cursor.fetchmany(2)
    print(r1)

    # 操作游標
    # cursor.scroll(0, 'absolute')  # absolute絕對偏移,游標重置,從頭開始偏移
    cursor.scroll(-2, 'relative')  # relative相對偏移,游標在當前位置進行左右偏移

    r2 = cursor.fetchone()
    print(r2)

4、實踐:建立數據庫,進行一些簡單操作

  • 1、Select操作:簡單的創建一個ch2表,並且插入一些數據,只有兩個字段:userid和username。
  • 2、數據的更新,即:insert、update、delete操作。
    注意:是否數據發生異常,如果數據沒有發生異常,我們便可以直接使用commit()進行提交(注:如沒有使用commit,則數據庫不會發生任何變化)。但是如果出現了異常,那么就需要使用rollback()進行回滾。
    import pymysql
    coon = pymysql.connect(host='192.168.199.128',port=3306,user='root',passwd='123456',db='2019-1229',charset='utf8')  
    cur = coon.cursor()  
    
    cur.execute("""
    create table if not EXISTS ch2
    (
      userid int(11) PRIMARY KEY,
      username VARCHAR(20)
    )
    """)  
    
    # 0、用Navicat打開數據庫,查看一下結果,成功創建表,並且插入了十個數據。每次執行該句都會增10條記錄
    for i in range(1,10):
        cur.execute("REPLACE into ch2(userid,username) values('%d','%s')" %(int(i),'name'+str(i)))     
    
    # 1、Select操作,操作一下Cursor里面的一些方法    
    sql='select * from ch2;'
    cur.execute(sql)  
    
    print(cur.rowcount)  # 或其他方法,cur.fetchone(),cur.fetchmany(3),
    rs=cur.fetchone()
    print(rs)
    
    res=cur.fetchall()
    for row in res:
        print('userid=%s,userna=%s' %row)
    
    # 2、insert、update、delete:在寫增刪改查操作時,最好把操作放入一個try控制塊中,來避免一些不必要的錯誤。
    sql_insert = 'insert into ch3(userid,username) values(10,"name10")'
    sql_update = 'update ch3 set username="name91" where userid=9'
    sql_delete = 'delete from ch3 where userid=3'
    
    try:
        cur.execute(sql_insert)
        print(cur.rowcount)
        cur.execute(sql_update)
        print(cur.rowcount)
        cur.execute(sql_delete)
        print(cur.rowcount)
    except Exception as e:
        print(e)
        coon.rollback()    # rollback()的作用數據沒有任何改變。
    
        
    coon.commit()
    cur.close()  
    coon.close()  

5、銀行轉賬的實例

#-*-encoding:utf-8 -*- 
coon = pymysql.connect(host='192.168.199.128',port=3306,user='root',passwd='123456',db='2019-1229',charset='utf8') 
cur = coon.cursor() 

# 創建數據表
cur.execute("""
create table if not EXISTS account(
  accid int(10) PRIMARY KEY ,
  money int(10)
)
""")
# 插入兩行數據
cur.execute('insert into account(accid,money) VALUES (1,110)')
cur.execute('insert into account(accid,money) VALUES (2,10)')

coon.commit() 
cur.close()
coon.close()

import sys
import MySQLdb
 
class TransferMoney(object):
    def __init__(self,conn):
        self.conn=conn
    def check_acct_available(self,accid):
        cursor=self.conn.cursor()    # 游標,self
        try:
            sql='select * from account where accid=%s' %accid
            cursor.execute(sql)
            print('check_acct_available'+sql)
            rs=cursor.fetchall()
            if len(rs)!=1:
                raise Exception('賬號%s 不存在' %accid)
        finally:
            cursor.close()
    def has_enough_money(self,accid,money):
        cursor=self.conn.cursor()
        try:
            sql='select * from account where accid=%s and money>%s' %(accid,money)
            cursor.execute(sql)
            print('check_money_available'+sql)
            rs=cursor.fetchall()
            if len(rs)!=1:
                raise Exception('賬號%s 沒有足夠錢' %accid)
        finally:
            cursor.close()
    def reduce_money(self,accid,money):
        cursor=self.conn.cursor()
        try:
            sql='update account set money=money-%s where accid=%s' %(money,accid)
            cursor.execute(sql)
            print('reduce money'+sql)
            rs=cursor.fetchall()
            if cursor.rowcount!=1:
                raise Exception('賬號%s 減款失敗' %accid)
        finally:
            cursor.close()
    def add_money(self,accid,money):
        cursor=self.conn.cursor()
        try:
            sql='update account set money=money+%s where accid=%s' %(money,accid)
            cursor.execute(sql)
            print('reduce money'+sql)
            rs=cursor.fetchall()
            if cursor.rowcount!=1:
                raise Exception('賬號%s 加款失敗' %accid)
        finally:
            cursor.close()
    def transfer(self,source_accid,target_accid,money):
        ###檢測兩個賬號是否可用
        try:
            self.check_acct_available(source_accid)
            self.check_acct_available(target_accid)
            ####檢測付款人是否有足夠的錢
            self.has_enough_money(source_accid,money)
            self.reduce_money(source_accid,money)
            self.add_money(target_accid,money)
            self.conn.commit()
        except Exception as e:
            self.conn.rollback()
            raise e  
 
if __name__=='__main__':
    source_accid=sys.argv[1]
    target_accid=sys.argv[2]
    money=sys.argv[3] 
    conn = pymysql.connect(host='192.168.199.128',port=3306,user='root',passwd='123456',db='2019-1229',charset='utf8') 
    tr_money=TransferMoney(conn)
 
    try:
        tr_money.transfer(source_accid,target_accid,money)
    except Exception as e:
        print('出現問題'+str(e))
    finally:
        conn.close()

6、

try:
    # cur.execute('create database if not exists python')
    # conn.select_db('python')
    sql = 'create table t2(id int, name char(4), money int)'
    row = cursor.execute(sql)
    print(row)
except:
    print('表已創建')
    pass

# 空表才插入
row = cursor.execute('select * from t2')
if not row:
    sql = 'insert into t2 values(%s,%s,%s)'
    row = cursor.executemany(sql, [(1, 'tom', 10), (2, 'Bob', 10)])
    conn.commit()

1、pymysql事務

# 可能會出現異常的sql
try:
    sql1 = 'update t2 set money=money-1 where name="tom"'
    r1 = cursor.execute(sql1)
    sql2 = 'update t2 set money=money+1 where name="ruakei"'  # 轉入的人不存在
    r2 = cursor.execute(sql2)
except:
    print('轉賬執行異常')
    conn.rollback()
else:
    print('轉賬沒有異常')
    if r1 == 1 and r2 == 1:
        print('轉賬成功')
        conn.commit()
    else:
        conn.rollback()

2、SQL注入問題

# 用戶登錄
usr = input('usr: ')
pwd = input('pwd: ')

# 自己拼接參數一定有sql注入,將數據的占位填充交給pymysql
sql = 'select * from user where name=%s and password=%s'
row = cursor.execute(sql, (usr, pwd))
if row:
    print('登錄成功')
else:
    print('登錄失敗')


# 知道用戶名時
# 輸入用戶時:
#   tom => select * from user where name="tom" and password="%s"
#   tom" # => select * from user where name="tom" #" and password="%s"

# 不自定義用戶名時
#   " or 1=1 # => select * from user where name="" or 1=1 #" and password="%s"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM