Py数据库编程及应用(DB API、SQLite、MySQL、MongoDB、Redis)

# -*- coding: utf-8 -*-
'''
Py数据库编程及应用.py
(DB API、SQLite、MySQL、MongoDB、Redis)

深入:
一、详细系统化深入数据库Redis、MySQL、MongoDB

注意:


使用:

'''



# =============================================================================
# Py数据库API
# DB API 是一个规范,它定义了一系列必须的对象和数据库存取方式,以便为各种各样的底层数据库系统和多种多样的数据库接口程序提供一致的访问接口
# =============================================================================


##################
#全局变量
#DB API 的数据库模块都必须定义 3 个描述模块特性的全局变量。

'''
这 3 个全局变量分别是:

1、apilevel:       用于显示数据库模块的 API 版本号。
对于支持 DB API 2.0 版本的数据库模块来说,该变量值可能是 1.0 或 2.0。
如果这个变量不存在,则可能该数据库模块暂时不支持 2.0 版本的 API,读者就应该考虑选择使用支持该数据库的其他数据库模块。

2、threadsafety:   指定数据库模块的线程安全等级,
该等级值为 0~3 ,其中 3 代表该模块完全是线程安全的;1 表示该模块具有部分线程安全性,线程可以共享该模块,但不能共享连接;0 则表示线程完全不能共享该模块。

3、paramstyle:     该全局变量指定当 SQL 语句需要参数时,可以使用哪种风格的参数。
该变量可能返回如下变量值:
format:表示在 SQL 语句中使用 Python 标准的格式化字符串代表参数。例如,在程序中需要参数的地方使用 %s,接下来程序即可为这些参数指定参数值。
pyformat:表示在 SQL 语句中使用扩展的格式代码代表参数。比如使用 %(name),这样即可使用包含 key 为 name 的字典为该参数指定参数值。
qmark:表示在 SQL 语句中使用问号(?)代表参数。在 SQL 语句中有几个参数,全部用问号代替。
numeric:表示在 SQL 语句中使用数字占位符(:N)代表参数。例如:1 代表一个参数,:2 也表示一个参数,这些数字相当于参数名,因此它们不一定需要连续。
named:表示在 SQL 语句中使用命名占位符(:name)代表参数。例如 :name 代表一个参数,:age 也表示一个参数。
'''


##################
#链接数据库
# connect() 函数,该函数用于连接数据库,并返回数据库连接对象。

'''
数据库连接对象的方法和属性

方法或属性	             功能描述
cursor()	    	     打开游标。
commit()	             提交事务。
rollback()	             回滚事务。
close()	                 关闭数据库连接。
isolation_level	         返回或设置数据库连接中事务的隔离级别。
in_transaction	         判断当前是否处于事务中。
'''


#游标对象
#cursor()方法打开游标,然后返回一个游标对象。游标对象是 Python DB API 的核心对象,
#该对象主要用于执行各种 SQL 语句,包括 DDL、DML、select 查询语句等。
#使用游标执行不同的 SQL 语句返回不同的数据。

'''
数据库游标对象拥有的属性和方法

属性或方法	                            功能描述
execute(sql[, parameters])	            执行 SQL 语句。parameters 参数用于为 SQL 语句中的参数指定值。
executemany(sql, seq_of_parameters)	    重复执行 SQL 语句。可以通过 seq_of_parameters 序列为 SQL 语句中的参数指定值,该序列有多少个元素,SQL 语句被执行多少次。
executescript(sql_script)	            这不是 DB API 2.0 的标准方法。该方法可以直接执行包含多条 SQL 语句的 SQL 脚本。
fetchone()	                            获取查询结果集的下一行。如果没有下一行,则返回 None。
fetchmany(size=cursor.arraysize)    	返回查询结果集的下 N 行组成的列表。如果没有更多的数据行,则返回空列表。
fetchall()	                            返回查询结果集的全部行组成的列表。
close()	                                关闭游标。
rowcount	                            该只读属性返回受 SQL 语句影响的行数。对于 executemany() 方法,该方法所修改的记录条数也可通过该属性获取。
lastrowid	                            该只读属性可获取最后修改行的 rowid。
arraysize	                            用于设置或获取 fetchmany() 默认获取的记录条数,该属性默认为 1。有些数据库模块没有该属性。
description                         	该只读属性可获取最后一次查询返回的所有列的信息。
connection	                            该只读属性返回创建游标的数据库连接对象。有些数据库模块没有该属性。

'''


##################
#操作数据库的基本流程

'''
操作数据库的基本流程如下:
1、调用 connect() 方法打开数据库连接,该方法返回数据库连接对象。
2、通过数据库连接对象打开游标。
3、使用游标执行 SQL 语句(包括 DDL、DML、select 查询语句等)。如果执行的是查询语句,则处理查询数据。
4、关闭游标。
5、关闭数据库连接。
'''










# =============================================================================
# #SQLite数据库
# #SQLite数据库不是一个客户端 / 服务器结构的数据库引擎,而是一种嵌入式数据库,
# #SQLite数据库其实就是一个文件。SQLite 将整个数据库(包括定义、表、索引以及数据本身)作为一个单独的、可跨平台使用的文件存储在主机中。
# =============================================================================
'''
注意:
1、SQLite 内部只支持 NULL、INTEGER、REAL(浮点数)、TEXT(文本)和 BLOB(大二进制对象)这 5 种数据类型,
但实际上 SQLite 完全可以接受 varchar(n)、char(n)、decimal(p, s) 等数据类型,只不过 SQLite 会在运算或保存时将它们转换为上面 5 种数据类型中相应的类型。


使用:
一、SQLite数据库操作的基本流程如下:
#1、connect函数 打开/创建数据库;也可以使用特殊名::memory:代表创建内存中的数据库
#2、cursor方法 打开游标
#3、execute方法 执行DDL语句创建数据表
#4、关闭游标
#5、关闭数据库

'''

import sqlite3


####################
#探索模块

help(sqlite3)
sqlite3.__doc__
sqlite3.__path__
sqlite3.__file__
dir(sqlite3)


####################
#示例操作数据库的基本流程

#1、connect函数 打开/创建数据库,
#也可以使用特殊名 :memory: 来创建内存中的数据库
conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件

#2、cursor方法 打开游标
c=conn.cursor()                                         #打开获取游标

#3、execute方法 执行DDL语句创建数据表
#DDL语句中 数据列 后面 是类型声明。如 NULL、INTEGER、REAL(浮点数)、TEXT(文本)和 BLOB(大二进制对象)

#创建一个表单user_tb
c.execute('''
          create table user_tb(
          _id integer primary key autoincrement,
          name text,
          pass text,
          gender text
          )''')

#继续创建一个表单order_tb,
#其中有一个外键列引用 user_tb 表的 _id 主键列。
c.execute('''
          create table order_tb(
          _id integer primary key autoincrement,
          item_name text,
          item_price real,
          item_number real,
          user_id inteter,
          foreign key(user_id) references user_tb(id)
          )''')

#4、关闭游标
c.close()

#5、关闭数据库
conn.close()




####################
#示例1 
#execute()方法         执行一条语句
#executemany()方法     重复执行一条语句


##########
#execute()方法执行 insert 语句向数据库中插入数据
import sqlite3

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件
c=conn.cursor()                                         #打开获取游标

c.execute('insert into user_tb values(null,?,?,?)',
          ('孙悟空','123456','male'))
#继续执行 insert 语句,即可向数据表中插入数据。
c.execute('insert into order_tb values(null,?,?,?,?)',
          ('鼠标','34.2','3',1))                        
conn.commit()                                           #提交事务,否则对数据库的修改不会生效

c.close()
conn.close()



##########
#executemany() 方法,重复多次执行同一条 SQL 语句
#executemany() 重复执行一条 insert 语句,但调用该方法的第二个参数是一个元组,
#该元组参数的每个元素都代表执行该 insert 语句一次,在执行 insert 语句时这些元素负责为该语句中的“?”占位符赋值。
import sqlite3

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件
c=conn.cursor()                                         #打开获取游标

c.executemany('insert into user_tb values(null,?,?,?)',
          (('sun','123456','male'),
          ('bai','123456','male'),
          ('zhu','123456','male'),
          ('niu','123456','male'),
          ('tang','123456','male')
          ))
                      
conn.commit()                                           #提交事务,否则对数据库的修改不会生效

c.close()
conn.close()



##########
#executemany()方法也可以重复多次执行其他语句,如 update 语句或 delete 语句等。
#只要其第二个参数是一个序列,序列的每个元素都可对被执行 SQL 语句的参数赋值即可。
import sqlite3

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件
c=conn.cursor()                                         #打开获取游标

# executemany() 执行的 update 语句中包含两个参数,
#因此调用 executemany() 方法的第二个参数是一个元组,该元组中的每个元素只包含两个元素,
#这两个元素就用于为 update 语句中的两个“?”占位符赋值。
c.executemany('update user_tb set name=? where _id=?',
              (('小孙',2),
               ('小白',3),
               ('小猪',4),
               ('小牛',5),
               ('小唐',6)))
print('修改的记录条数:',c.rowcount)                     #使用游标的 rowcount 属性来获取 update 语句所修改的记录条数。
conn.commit()

c.close()
conn.close()





####################
#示例2
#description方法      获取最后一次查询返回的所有列的信息 即:列名
#description方法      获取最后一次查询返回的所有列的信息
#fetchmany()方法      获取查询结果的下N行组成的李彪

#executescript()方法  执行一段SQL脚本(此方法非标准API,为SQLite数据库方法)



##########
import sqlite3

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件
c=conn.cursor()                                         #打开获取游标

#execute方法执行语句
#select查询语句 查询数据
c.execute('select * from user_tb where _id >?',
          (2,))
print('查询返回的记录数:',c.rowcount)                    #返回查询的函数

#description方法  获取最后一次查询返回的所有列的信息
for col in (c.description):                             
    print(col[0],end='\t')                               #输出列名,定义输出结尾为制表符
print('\n------------------------------')                #输出分割线


#fetchone()方法  获取查询结果的下一行,每次获取一条记录
while True:
    row=c.fetchone()                                     #获取查询结果集的下一行,如果没有则返回None
    if not row:
        break
    print(row)                                           #输出下一行数据
    print(row[1] + '-->' + row[2])                       #输出下一行数据的美化内容

##fetchmany()方法  获取查询结果的下N行组成的李彪
#while True:
#    rows=c.fetchmany(3)
#    if not rows:
#        break
#    for r in rows:
#        print(r)

c.close()                                                #游标关闭
conn.close()                                             #数据库关闭



##########
import sqlite3

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件
c=conn.cursor()

#executescript()方法  执行一段SQL脚本(此方法非标准API,为SQLite数据库方法)
c.executescript('''
                insert into user_tb values(null,'武松','3444','male');
                insert into user_tb values(null,'林冲','44444','male');
                create table item_tb(_id integer primary key autoincrement,name,price);
                ''')
conn.commit()                                            #提交事务

c.close()                                                #游标关闭
conn.close()                                             #数据库关闭






####################
#示例3
#create_function(name, num_params, func)方法,数据库连接对象方法,用于注册自定义函数


##########
#create_function(name, num_params, func)方法,数据库连接对象方法,用于注册自定义函数

import sqlite3

#先定义一个普通函数,准备注册为 SQL 中的自定义函数
def reverse_ext(st):
    '''
    准备将 reverse_ext() 函数注册为自定义函数 enc,
    该函数用于模拟一个简单的加密功能:程序会对字符串反转,并在字符串前后添加方括号。
    '''
    return'['+ st[::-1] + ']'

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件

#create_function()方法  注册自定义函数
conn.create_function('enc',1,reverse_ext)               ##create_function()方法  注册自定义函数:enc

c=conn.cursor()                                         #打开获取游标

#execute方 执行单挑DLL语句
c.execute('insert into user_tb values(null,?,enc(?),?)',
          ('贾宝玉','123456','male'))
conn.commit()

c.close()
conn.close()



##########
#create_aggregate()方法  数据库连接对象方法,用于注册自定义聚集函数

import sqlite3

#先定义一个普通类,准备注册为 SQL 中的自定义聚集函数
class MinLen:
    def __init__(self):
        self.min_len=None
    def step(self,value):
        #如果self.min_len还没有赋值,则直接将当前value赋值给self.min_Len
        if self.min_len is None:
            self.min_len = value
            return
        #如果找到一个长度更短的value,则用value代替self.min_Len
        if len(self.min_len) > len(value):
            self.min_len = value
    def finalize(self):
        return self.min_len

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件

#create_aggregate()方法  注册自定义聚集函数
conn.create_aggregate('min_len',1,MinLen)

c=conn.cursor()                                         #打开获取游标

#execute()方法  执行单句 DLL语句
c.execute('select min_len(pass) from user_tb')          #执行查询语句select

#print(c.fetchone()[0])
print(c.fetchmany(3))

conn.commit()

c.close()
conn.close()



##########
#create_collation()方法  数据库连接对象方法,用于创建自定义比较函数
#在标准的 SQL 语句中提供了一个 order by 子句,该子句用于对查询结果进行排序,
#但这种排序只会按默认的排序规则进行,如果程序需要按业务相关规则进行排序,则需要创建自定义的比较函数。

import sqlite3

#线定义一个函数,准备注册为 自定义的比较函数
def my_collate(st1,st2):
    if st1[1:-1] == st2[1:-1]:
        return 0
    elif st1[1:-1] > st2[1:-1]:
        return 1
    else:
        return -1

conn=sqlite3.connect('测试文件\\testSQLite_First.db')    #创建或打开数据库文件 first.db 文件

#Create_collation()方法  注册自定义比较函数
conn.create_collation('sub_cmp',my_collate)

c=conn.cursor()

#execute()方法  执行单据 DLL语句
c.execute('select * from user_tb order by pass collate sub_cmp')

for row in c:
    print(row)

conn.commit()


c.close()
conn.close()











# =============================================================================
# #MySQL数据库
# =============================================================================
'''
注意:
1、与连接 SQLite 的程序相比,mysql.connector如果需要连接 localhost 主机上 3306 端口服务的 python 数据库,
那么必须先在本机的 MySQL 数据库服务器中创建一个 python 数据库。命令如:'create database pyhton;'注意最后的;分号不能省略


使用:
1、MySQL的安装和配置参考网址:
https://www.cnblogs.com/laumians-notes/p/9069498.html
https://www.runoob.com/mysql/mysql-install.html

2、安装MySQL的Py操作接口
pip install mysql-connector-python
pip install pymysql
'''


import mysql.connector

help(mysql.connector)
mysql.connector.__doc__
mysql.connector.__file__
mysql.connector.__all__
dir(mysql.connector)


###################
#检查接口模块的全局变量 标准API
print(mysql.connector.apilevel)        #显示数据库模块的 API 版本号。           
print(mysql.connector.paramstyle)      #该全局变量指定当 SQL 语句需要参数时,可以使用哪种风格的参数。



####################
#示例   
#mysql.connector操作MySQL数据库的5个基本流程

import mysql.connector

#connect方法  连接数据库
#连接数据库,需要数据库事先创建存在。
conn = conn = mysql.connector.connect(user='root', password='yangshujke5',
                                      host='localhost', port='3306',           #MySQL 数据库有服务器进程,默认通过 3306 端口对外提供服务。
                                      database='python', use_unicode=True)     #数据库需要先自行创建。命令如:'create database pyhton;'注意最后的;分号不能省略
#连接获取游标
c = conn.cursor()
#execte()方法  执行单条DLL语句
c.execute('''
          create table user_tb(
          user_id int primary key auto_increment,
          name varchar(255),
          pass varchar(255),
          gender varchar(255))
          ''')
#execte()方法  继续执行单条DLL语句
c.execute('''
          create table order_tb(
          order_id integer primary key auto_increment,
          item_name varchar(255),
          item_price double,
          item_number double,
          user_id int,
          foreign key(user_id) references user_tb(user_id))
          ''')
#游标关闭,数据库关闭
c.close()
conn.close()




####################
#示例
#execute()方法  执行单条DLL语句
#MySQL 数据库模块同样可以使用游标的 execute() 方法执行 DML 的 insert、update、delete 语句,
#对数据库进行插入、修改和删除数据操作。

import mysql.connector

#连接数据库,需要数据库事先创建存在。
conn=mysql.connector.connect(user='root',password='yangshujke5',
                             host='localhost',port='3306',
                             database='python',use_unicode=True)
#连接获取游标
c = conn.cursor()

#execute()方法  执行单条DLL语句
#insert语句插入操作
c.execute('insert into user_tb values(null, %s, %s, %s)',
    ('孙悟空', '123456', 'male'))
c.execute('insert into order_tb values(null, %s, %s, %s, %s)',
    ('鼠标', '34.2', '3', 1))
conn.commit()

c.close()
conn.close()



##########
#executemany()方法  重复执行DLL语句
#MySQL 数据库模块同样支持使用 executemany() 方法重复执行insert插入语句等其他SQL语句

import mysql.connector

#连接数据库,需要数据库事先创建存在。
conn=mysql.connector.connect(user='root',password='yangshujke5',
                             host='localhost',port='3306',
                             database='python',use_unicode=True)
#连接获取游标
c = conn.cursor()

#executemany()方法  重复执行insert插入语句,参数2位元组形式
c.executemany('insert into user_tb values(null, %s, %s, %s)',
    (('sun', '123456', 'male'),
    ('bai', '123456', 'female'),
    ('zhu', '123456', 'male'),
    ('niu', '123456', 'male'),
    ('tang', '123456', 'male')))
conn.commit()

c.close()
conn.close()



##########
#autocommit属性  自动提交事务
#MySQL 数据库模块中游标的 executemany() 方法同样可重复执行 update、delete 语句
#MySQL 数据库模块的连接对象 autocommit 属性,属性设为 True 则自动提交事务

import mysql.connector

#连接数据库,需要数据库事先创建存在。
conn=mysql.connector.connect(user='root',password='yangshujke5',
                             host='localhost',port='3306',
                             database='python',use_unicode=True)
#连接获取游标
c = conn.cursor()

#executemany()方法  重复执行update更新语句,参数2位元组形式
c.executemany('update user_tb set name=%s where user_id=%s',
    (('小孙', 2),
    ('小白', 3),
    ('小猪', 4),
    ('小牛', 5),
    ('小唐', 6)))

#autocommit属性  自动提交事务
conn.autocommit = True

# 通过rowcount获取被修改的记录条数
print('修改的记录条数:', c.rowcount)
#conn.commit()

c.close()
conn.close()




###################
#示例
# MySQL 数据库模块执行查询语句,与使用 SQLite 数据库模块执行查询语句基本相似,
#只需注意 SQL 语句中的占位符的差别即可。

import mysql.connector

#连接数据库,需要数据库事先创建存在。
conn=mysql.connector.connect(user='root',password='yangshujke5',
                             host='localhost',port='3306',
                             database='python',use_unicode=True)
#连接获取游标
c = conn.cursor()

#execute()方法  执行单条DLL语句 select查询语句。
c.execute('select * from user_tb where user_id > %s', (2,))

# 通过游标的description属性获取列信息
for col in (c.description):
    print(col[0], end='\t')
print('\n--------------------------------')

# 直接使用for循环来遍历游标中的结果集
for row in c:
    print(row)
    print(row[1] + '-->' + row[2])
    
c.close()
conn.close()



##########
#MySQL 数据库模块的游标对象同样支持 fetchone()、fetchmany()、fetchall() 方法,
#fetchmany() 方法每次获取 N 条记录:

import mysql.connector

#连接数据库,需要数据库事先创建存在。
conn=mysql.connector.connect(user='root',password='yangshujke5',
                             host='localhost',port='3306',
                             database='python',use_unicode=True)
#连接获取游标
c = conn.cursor()

#execute()方法  执行单条DLL语句 select查询语句
c.execute('select * from user_tb where user_id > %s', (2,))

# 通过游标的description属性获取列信息
for col in (c.description):
    print(col[0], end='\t')
print('\n--------------------------------')

while True:
    # 每次抓取3条记录,该方法返回一个多个元组组成的列表
    rows = c.fetchmany(3)
    # 如果抓取的row为None,退出循环
    if not rows :
        break
    # 再次使用循环遍历获取的列表
    for r in rows:
        print(r)

c.close()
conn.close()




####################
#MySQL 数据库模块 游标对象提供了一个非标准的 callproc(self, procname, args=()) 方法,
#该方法用于调用数据库存储过程,其中procname 参数代表存储过程的名字,而 args 参数则用于为存储过程传入参数。

#参考网址:
#http://c.biancheng.net/view/2598.html













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值