python数据库编程

在这里插入图片描述
从图中可以看出,在 Python 中操作数据库,要经过五个步骤,分别是连接数据库,获取游标,数据库操作,关闭游标,关闭数据库连接。

在 Pyhton 中,使用 Pymysql 模块来对数据库进行编程。

数据库资源

1.导入模块
from pymysql import connect
2.Connection 对象 目的:用于建立代码与数据库的连接

使用这三个创建连接都可以
connect = Connection = Connect
前两个对后一个函数进行引用

创建连接对象 conn=connect(参数列表)

  • 参数host:连接的mysql主机,如果本机是’localhost’
  • 参数port:连接的mysql主机的端口,默认是3306
  • 参数database:数据库的名称
  • 参数user:连接的用户名
  • 参数password:连接的密码
  • 参数charset:通信采用的编码方式,推荐使用utf8
    3.关闭连接 conn.close()

4.提交数据 conn.commit()

5.撤销数据 conn.rollback()

6.通过连接获取游标 cur = conn.cursor()返回Cursor对象,用于执行sql语句并获得结果

7.Cursor游标对象 目的: 执行sql语句

8.获取Cursor对象 cur = conn.cursor()

9.使用游标执行SQL语句 cur.execute(operation , [parameters])

10.执行SQL语句,返回受影响的行数,主要用于执行insert、update、delete语句

11.获取结果集中的一条 cur.fetchone() 返回一个元组 如 (1,‘妲己’,18)

12.获取结果集中的一条 cur.fetchmany(2) 返回一个元组 如 ((1,‘妲己’,18),2,‘公孙离’,20))

13.获取结果集中的所有 cur.fetchall() 执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回. 如((1,‘妲己’,18),(2,‘公孙离’,20),(3,‘姜子牙’,28))

14.关闭游标 cur.close()

使用 pymsql 完成数据查询

  1. 准备数据`在这里插入代码片
 -- 创建数据库
 create database python_db charset=utf8;

 -- 使用数据库
 use python_db;

 -- students表
 create table students(
     id int unsigned primary key auto_increment not null,
     name varchar(20) default '',
     age tinyint unsigned default 0,
     height decimal(5,2),
     gender enum('男','女','中性','保密') default '保密',
     cls_id int unsigned default 0,
     is_delete int default 0
 );

 -- classes表
 create table classes (
     id int unsigned auto_increment primary key not null,
     name varchar(30) not null
 );

 -- 向students表中插入数据
 insert into students values
 (0,'小明',18,180.00,2,1,0),
 (0,'小月月',18,180.00,2,2,1),
 (0,'彭于晏',29,185.00,1,1,0),
 (0,'刘德华',59,175.00,1,2,1),
 (0,'黄蓉',38,160.00,2,1,0),
 (0,'凤姐',28,150.00,4,2,1),
 (0,'王祖贤',18,172.00,2,1,1),
 (0,'周杰伦',36,NULL,1,1,0),
 (0,'程坤',27,181.00,1,2,0),
 (0,'刘亦菲',25,166.00,2,2,0),
 (0,'金星',33,162.00,3,3,1),
 (0,'静香',12,180.00,2,4,0),
 (0,'郭靖',12,170.00,1,4,0),
 (0,'周杰',34,176.00,2,5,0);

 -- 向classes表中插入数据
 insert into classes values (0, "python_01期"), (0, "python_02期");
  1. 查询数据
# 导入模块
 from pymysql import connect
 # 连接数据库
 conn = connect(host='localhost', port=3306, database='python_db', user='root', password='123123',charset='utf8')
 # 获取游标
 cur = conn.cursor()
 # 以字符串形式书写SQL语句,因为SQL语句中也会出现字符串,所以建议使用 ```引号形式将SQL诗句引起来
 sql_str = '''select * from students;'''
 # 执行SQL语句
 row_count = cur.execute(sql_str)
 # 显示执行 SQL 语句影响的行数
 print(row_count)
 # 获取一条记录
 row_one = cur.fetchone()
 # 显示获取的记录
 print(row_one)
 # 获取多条记录
 row_many = cur.fetchmany(4)
 # 遍历输出所有的结果
 for t in  row_many:
     print(t)
 # 获取所有的数据
 row_all = cur.fetchall()
 # 遍历输出所有的结果
 for t in  row_all:
     print(t)
 # 关闭游标
 cur.close()
 # 关闭数据库
 conn.close()

注意:因为在获取数据时,游标是移动的,所以前面取过的数据,后面不会再取了。

  1. 增删改
# 导入模块
 from pymysql import connect
 # 连接数据库
 conn = connect(host='localhost', port=3306, database='python_db', user='root', password='123123',charset='utf8')
 # 获取游标
 cur = conn.cursor()
 # 以字符串形式书写SQL语句
 # sql_str = '''insert into students values(0,'新来的',20,180,'男',1,1)'''
 # sql_str = '''update students set name = '王钢蛋' where name = '新来的'; '''
 sql_str = '''delete from students where name='王钢蛋'; '''
 # 执行SQL语句
 row_count = cur.execute(sql_str)
 # 在执行增删改操作时,需要向数据库提交操作,否则操作不成功
 conn.commit()
 # 关闭游标
 cur.close()
 # 关闭数据库
 conn.close()
  1. 回滚(取消操作)
# 导入模块
 from pymysql import connect
 # 连接数据库
 conn = connect(host='localhost', port=3306, database='python_db', user='root', password='123123',charset='utf8')
 # conn.autocommit(True)
 # 获取游标
 cur = conn.cursor()
 # 以字符串形式书写SQL语句
 sql_str = '''insert into students values(0,'新来的',20,180,'男',1,1)'''
 #插入10条数据
 for i in range(10):
     # 执行SQL语句
     row_count = cur.execute(sql_str)
 # 在执行增删改操作时,如果不想提交前面的修改操作,可以使用 rollback 回滚取消操作
 conn.rollback()
 # 关闭游标
 cur.close()
 # 关闭数据库
 conn.close()

数据库编程练习

  • 准备工作
  create database JDDB charset=utf8;
  use JDDB
  source JDDB.sql
  • 实现
import pymysql


class JD(object):
    def __init__(self):
        self.dic = {0: self.__close,
                    1: self.__fetch_all_info,
                    2: self.__fetch_cate,
                    3: self.__fetch_brand,
                    4: self.__add_info,
                    5: self.__find_info,
                    6: self.__find_info_safe
                    }
         # user,和password换成你的root和密码
        self.__conn = pymysql.Connect(host="localhost",
                                      port=3306,
                                      database="JDDB",
                                      user="demouser",
                                      password="demopassword",
                                      charset="utf8")
        self.__cur = self.__conn.cursor()

    def __show_result(self, result):
        # print(type(result))   # <cass 'tuple'>
        for r in result:
            print(r)

    # 查询所有商品信息
    def __fetch_all_info(self):
        sql = ''' select * from goods '''
        affected = self.__cur.execute(sql)
        print("influenced %d row" % affected)
        self.__show_result(self.__cur.fetchall())

    # 查询种类信息
    def __fetch_cate(self):
        sql = ''' select * from goods_cates '''
        self.__cur.execute(sql)
        self.__show_result(self.__cur.fetchall())

    # 查询品牌信息
    def __fetch_brand(self):
        sql = ''' select * from goods_brands '''
        self.__cur.execute(sql)
        self.__show_result(self.__cur.fetchall())

    # 添加一个商品类型
    def __add_info(self):
        goods_type = input("please input a new goods type: ")
        sql = ''' insert into  goods_cates(name) values ("%s") '''
        self.__cur.execute(sql, goods_type)
        self.__conn.commit()

    # 通过ID 查找商品
    def __find_info(self):
        # 当输入 "id or True" 时会发生sql注入,看到本不该看到的东西
        goods_type = input("please input a ID of cates: ")
        sql = ''' select * from goods where id=%s''' % goods_type
        self.__cur.execute(sql)
        self.__show_result(self.__cur.fetchall())

    # 通过ID 查找商品 防SQL注入
    def __find_info_safe(self):
        goods_type = input("please input a ID of cates: ")
        # 此处不同于python的字符串格式化,必须全部使用%s占位
        sql = ''' select * from goods where id=%s'''
        # 通过参数化列表(元组)防止这种攻击,但是会产生一个warning,可以直接存储到日志log中
        self.__cur.execute(sql, (goods_type,))
        self.__show_result(self.__cur.fetchall())
	# 关闭连接,退出
    def __close(self):
        self.__cur.close()
        self.__conn.close()
        exit()

    def run(self):
        while True:
            print('*' * 50)
            print("1查询所有商品信息")
            print("2查询所有商品在种类信息")
            print("3查询所有商品在品牌信息")
            print("4添加商品种类")
            print("5根据id查询商品信息")
            print("6根据id查询商品信息安全方式")
            print("0退出")
            print('*' * 50)

            option = int(input("please input your option: "))
            try:
                self.dic[option]()
                # string()  # eval()
            except KeyError:
                print("enter is error! ")


def main():
    jd = JD()
    jd.run()


if __name__ == '__main__':
    main()

什么是SQL注入?

产生原因: 后台对用户提交的带有恶意的数据和 SQL 进行字符串方式的拼接,得到了脱离原意的 SQL 语句,从而影响了 SQL 语句的语义,最终产生数据泄露的现象。

如何防止: SQL 语句的参数化, 将 SQL 语句的所有数据参数存在一个列表中传递给 execute 函数的第二个参数

Logo

更多推荐