zoukankan      html  css  js  c++  java
  • python与mysql交互

    import pymysql
    from pymysql.cursors import DictCursor  # 导入字典类型的游标对象
    
    # 连接数据库
    db = pymysql.connect(host='192.168.3.109',      # 数据库IP地址
                         port=3306,             # 数据库端口号
                         user='root',           # 数据库用户名
                         password='123456',     # 数据库用户密码
                         db='test')             # 连接的数据库名称
    
    
    # cursor() 方法可以创建一个游标对象
    # 如果不指定游标返回的数据,则返回的数据默认为元组类型
    # cursor = db.cursor()
    # 指定为dict类型游标,则返回的数据为字典类型
    cursor = db.cursor(DictCursor)
    
    
    # execute() 方法可以执行所有的原生SQL,成功执行则结果返回数字
    # 比如:创建表格,则返回0
    ret = cursor.execute("CREATE TABLE testsheet (name VARCHAR(20), gender CHAR(1),age int(2))")     # 创建表格
    print(F"创建表格:{ret}")
    
    # 比如:插入数据,则返回插入记录数
    ret = cursor.execute("INSERT INTO testsheet (name,gender,age) VALUES('张三', '男', 22),('三二一', '女', 22)")
    print(F"插入数据:{ret}")
    
    
    # 比如:查询数据,则返回记录数
    ret = cursor.execute("select * from testsheet")
    print(F"记录数:{ret}")
    
    # 比如:删除表格,则返回0
    ret = cursor.execute("DROP TABLE testsheet")
    print(F"删除表格:{ret}")
    
    
    # 使用fetchall()和fetchone()可以提取查询的数据,提取后数据删除
    # fetchall() 提取所有数据,如果查询的数据为空,则返空,比如(),[];一次查询,多次提取,则返空
    cursor.execute("select * from info")
    ret = cursor.fetchall()
    print(F"fetchall提取数据:{ret}")
    ret = cursor.fetchall()
    print(F"fetchall再次提取数据:{ret}")
    
    # fetchone() 提取第一条数据,如果查询的数据为空,则返回None;一次查询,多次提取,则返回提取后的第一条数据,直到提取完,则返None。
    cursor.execute("select * from info")
    ret = cursor.fetchone()
    print(ret)
    ret = cursor.fetchone()
    print(ret)
    
    
    # 强调:使用execute()执行有参数的sql语句时,如果sql语句直接使用字符串初始化的方法存在SQL注入风险;需要使用execute(sql, 参数)的方式执行,防止SQL注入
    # 比如查询ID为1的数据
    id = 1
    sql = "select * from info where id='%s'" % (id,)
    cursor.execute(sql)
    ret = cursor.fetchall()
    print(F"查询ID为1的数据结果:{ret}")
    
    # 如果传入的值被恶意修改成下面的值,那么数据就存在脱库的安全问题
    id = "1' or '1=1"
    sql = "select * from info where id='%s'" % (id,)
    cursor.execute(sql)
    ret = cursor.fetchall()
    print(F"SQL注入的查询结果:{ret}")
    
    # 防SQL注入的执行方式,如果使用上面的id参数,则会报SQL语句错误
    sql = "select * from info where id='%s'"
    try:
        cursor.execute(sql, (id,))
        ret = cursor.fetchall()
    except:
        ret = "执行报错"
    print(F"防SQL注入的查询结果:{ret}")
    
    # rollback() 回滚数据。只要没有commit,可以使用 rollback 回滚所有对数据库进行了修改的操作(增、删、改)
    # db.rollback()
    
    # 提交游标的操作到数据库。
    db.commit()
    
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    db.close()

    简单封装

    import pymysql
    from pymysql.cursors import DictCursor      # 导入游标类型对象
    
    
    class Mysql(object):
    
        def __init__(self, host, user, password, port, db):
            # 连接数据库
            self.database = pymysql.connect(host=host, user=user, password=password, port=port, db=db)
            print("连接数据库")
    
            # 获取游标对象
            self.cursor = self.database.cursor()  # 使用该游标返回的数据为元组类型
            print(self.cursor)
    
            self.cursor = self.database.cursor(DictCursor)  # 使用该游标返回的数据为字典类型
            print(self.cursor)
    
        def __del__(self):
            """对象销毁进行资源回收"""
            # 关闭游标
            self.cursor.close()
            # 关闭数据库连接
            self.database.close()
            print("__del__被执行")
    
        def execute(self, query, args=None, force=None):
            """
            执行SQL
            :param query: sql语句
            :param args: sql语句中的参数
            :param force: 是否跳过对sql语句"where"的检查
            :return:返回游标对象
            """
            # 对query传入的sql语句校验是否包含"where",若包含,args又没传参数则抛异常。校验的目的是防SQL注入
            if force is None:
                query = query.lower()
                if "where" in query and args is None:
                    raise("检查到SQL中包含条件语句,但args参数为空,存在SQL注入的风险,若仍要执行,请将参数force的值修改为True")
    
            self.cursor.execute(query, args)
    
            # 返回游标对象就可以采用 execute().fetchone()的方式获取值
            return self.cursor
    
        def commit(self):
            """提交数据,提交失败则回滚"""
            try:
                self.database.commit()
                return 0
            except Exception as e:
                self.database.rollback()
                return -1
    
    
    if __name__ == '__main__':
        db = Mysql(host="192.168.0.58", user='root', password='123456', port=3306, db="test")
        _id = "1 or 1=1"
        code = "000036"
        # SQL注入执行方式
        sql = "select * from info WHERE id=%s or code=%s" % (_id, code)
        # ret = db.execute(sql).fetchall()
        ret = db.execute(sql, force=True).fetchall()
        print(ret)
        print(F"SQL注入获取的数据数:{len(ret)}")
    
        # 防SQL注入的执行方式
        sql = "select * from info where id=%s or code=%s"
        ret = db.execute(sql, (_id, code)).fetchall()
        print(ret)
        print(F"防SQL注入获取的数据数:{len(ret)}")
        print("="*50)
    
        # 更新数据
        _id = 1
        code = "000011"
        sql = "UPDATE `d`.`info` SET `code` = %s WHERE `id` = %s"
        db.execute(sql, (code, _id))
    
        ret = db.commit()
        if ret == 0:
            print("数据更新成功")
        else:
            print("数据更新失败")
    
        # 获取指定字段值
        _id = 1
        sql = "select * from info where id=%s"
        ret = db.execute(sql, (_id,)).fetchone()
        print(f"获取id为{_id}的code字段值:{ret.get('code')}")

    执行结果

  • 相关阅读:
    微信公众平台开发者中心安全模式消息体加解密实现
    AES对称加密算法原理
    Token验证失败
    PaySignKey
    UVA 11732
    lua中的pairs和ipairs差别
    【shell学习笔记】curl命令总结
    视频监控系统:C/S & B/S
    Android app开发中用户协议(使用条款)文字自己主动换行
    uva 10154
  • 原文地址:https://www.cnblogs.com/testlearn/p/11775829.html
Copyright © 2011-2022 走看看