黑马程序员---pymysql的使用

一:安装pymysql:

sudo pip3 install pymysql

二:基本的执行流程:
1:导包:import pymysql
2:使用pymysql.connect()获取连接,返回连接对象。
3:使用连接对象获取游标对象. cur =conn.cursor().
4: 使用游标对象的execute()方法执行SQL语句,返回一个影响的记录数
5:使用游标对象的fetchone()或者fetchall()方法得到游标缓存中的数据。
6:关闭游标,然后,关闭连接。

案例一:事务查询goods表的所有内容:

import pymysql

def main():
    #1:获取连接
    conn = pymysql.connect(host="localhost",port=3306,user="root",password="123456",database="jing_dong",charset="utf8")
    # 2:获取游标对象
    cur = conn.cursor()
    # 3:查询sql语句
    sql_str = "select * from goods"
    count = cur.execute(sql_str)
    print("受影响的行数是:",count)

    # 4:查询出所有的信息
    content_tuple = cur.fetchall()

    # 5:循环遍历元祖的信息
    for i in content_tuple:
        print(i)

    # 6:关闭连接和游标
    cur.close()
    conn.close()
    
if __name__ == '__main__':
    main()

案例二:事务完成增删改:

import pymysql

def main():
    # 1:创建连接
    conn = pymysql.connect(host="localhost",port=3306,user="root",password="123456",database="jing_dong",charset="utf8")

    # 2:创建游标对象
    cur = conn.cursor()

    try:
        # 3:增加增删改
        # my_sql = "insert into goods values(0,'火星人笔记本牛逼',5,4,2000,default,default)"

        # 4:修改
        # my_sql = "update goods set goods.price = 3000 where id = 22"

        # 5:删除
        my_sql = "delete from goods where id = 22"
        row_count= cur.execute(my_sql)
        print("影响的行数是:%d" % row_count)
        conn.commit()

    except BaseException as e:
        print(e)
        conn.rollback()

    finally:
        cur.close()
        conn.close()

if __name__ == '__main__':
    main()

三:细节:
1:调用pymysql模块中的connect()函数来创建连接对象,代码如下:

conn=connect(参数列表)

 * 参数host:连接的mysql主机,如果本机是'localhost'
 * 参数port:连接的mysql主机的端口,默认是3306
 * 参数user:连接的用户名
 * 参数password:连接的密码
 * 参数database:数据库的名称
 * 参数charset:通信采用的编码方式,推荐使用utf8

连接对象操作说明:

关闭连接 conn.close()
提交数据 conn.commit()
撤销数据 conn.rollback()

2:游标操作说明:

使用游标执行SQL语句: execute(operation [parameters ]) 执行SQL语句,返回受影响的行数,主要用于执行insert、update、delete、select等语句
获取查询结果集中的一条数据:cur.fetchone()返回一个元组,(1,'张三')
获取查询结果集中的所有数据: cur.fetchall()返回一个元组,((1,'张三'),(2,'李四'))
关闭游标: cur.close(),表示和数据库操作完成

四:SQL注入问题:
1:什么是SQL注入?
用户提交带有恶意的数据与SQL语句进行字符串方式的拼接,从而影响了SQL语句的语义,最终产生数据泄露的现象。
2:解决方法:
SQL语句参数化
SQL语言中的参数使用%s来占位,此处不是python中的字符串格式化操作
将SQL语句中%s占位所需要的参数存在一个列表中,把参数列表传递给execute方法中第二个参数
演练:

import pymysql

def main():
    #1:获取连接
    conn = pymysql.connect(host="localhost",port=3306,user="root",password="123456",database="jing_dong",charset="utf8")
    # 2:获取游标对象
    cur = conn.cursor()
    # 3:查询sql语句

    my_str = input("请输入您要查询的名字:")
    sql_str = "select * from goods where name = '%s'" % my_str
    count = cur.execute(sql_str)
    print("受影响的行数是:",count)

    # 4:查询出所有的信息
    content_tuple = cur.fetchall()

    # 5:循环遍历元祖的信息
    for i in content_tuple:
        print(i)

    # 6:关闭连接和游标
    cur.close()
    conn.close()


if __name__ == '__main__':
    main()

正常结果:

请输入您要查询的名字:商务双肩背包
受影响的行数是: 2
(19, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00')
(21, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00')

如果输入'or 1=1 or'
结果就是查询条件变成查询:因为外面一队单引号,里面右增加一队引号 ,所以最后是查询"" or 1=1 or ""的结果,由于中间是恒成立,所以这个绝对成立。select语句中的这个单引号引号必须存在,因为正常输入需要name=‘值’,这种格式。

请输入您要查询的名字:'or 1=1 or'
受影响的行数是: 21
(1, 'r510vc 15.6英寸笔记本', 5, 2, Decimal('3399.000'), b'\x01', b'\x00')
(2, 'y400n 14.0英寸笔记本电脑', 5, 7, Decimal('4999.000'), b'\x01', b'\x00')
(3, 'g150th 15.6英寸游戏本', 4, 9, Decimal('8499.000'), b'\x01', b'\x00')
(4, 'x550cc 15.6英寸笔记本', 5, 2, Decimal('2799.000'), b'\x01', b'\x00')
(5, 'x240 超极本', 7, 7, Decimal('4880.000'), b'\x01', b'\x00')
(6, 'u330p 13.3英寸超极本', 7, 7, Decimal('4299.000'), b'\x01', b'\x00')
(7, 'svp13226scb 触控超极本', 7, 6, Decimal('7999.000'), b'\x01', b'\x00')
(8, 'ipad mini 7.9英寸平板电脑', 2, 8, Decimal('1998.000'), b'\x01', b'\x00')
(9, 'ipad air 9.7英寸平板电脑', 2, 8, Decimal('3388.000'), b'\x01', b'\x00')
(10, 'ipad mini 配备 retina 显示屏', 2, 8, Decimal('2788.000'), b'\x01', b'\x00')
(11, 'ideacentre c340 20英寸一体电脑 ', 1, 7, Decimal('3499.000'), b'\x01', b'\x00')
(12, 'vostro 3800-r1206 台式电脑', 1, 5, Decimal('2899.000'), b'\x01', b'\x00')
(13, 'imac me086ch/a 21.5英寸一体电脑', 1, 8, Decimal('9188.000'), b'\x01', b'\x00')
(14, 'at7-7414lp 台式电脑 linux )', 1, 3, Decimal('3699.000'), b'\x01', b'\x00')
(15, 'z220sff f4f06pa工作站', 3, 4, Decimal('4288.000'), b'\x01', b'\x00')
(16, 'poweredge ii服务器', 3, 5, Decimal('5388.000'), b'\x01', b'\x00')
(17, 'mac pro专业级台式电脑', 3, 8, Decimal('28888.000'), b'\x01', b'\x00')
(18, 'hmz-t3w 头戴显示设备', 6, 6, Decimal('6999.000'), b'\x01', b'\x00')
(19, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00')
(20, 'x3250 m4机架式服务器', 3, 1, Decimal('6888.000'), b'\x01', b'\x00')
(21, '商务双肩背包', 6, 6, Decimal('99.000'), b'\x01', b'\x00')

防止sql 注入:这个地方要注意两点,第一:execute方法中的 %s 占位不需要带引号?第二execute函数传递两个参数,第一个是sql语句,第二个是参数数组。execute会将参数数组避免sql注入的方式进行拼接。

import pymysql

def main():
    #1:获取连接
    conn = pymysql.connect(host="localhost",port=3306,user="root",password="123456",database="jing_dong",charset="utf8")
    # 2:获取游标对象
    cur = conn.cursor()
    # 3:查询sql语句

    my_str = input("请输入您要查询的名字:")
    sql_str = "select * from goods where name = %s"
    sql_list = [my_str]
    count = cur.execute(sql_str,sql_list)
    print("受影响的行数是:",count)

    # 4:查询出所有的信息
    content_tuple = cur.fetchall()

    # 5:循环遍历元祖的信息
    for i in content_tuple:
        print(i)

    # 6:关闭连接和游标
    cur.close()
    conn.close()


if __name__ == '__main__':
    main()

你可能感兴趣的:(删库到跑路)