• python-study-41


    pymysql

    #pip3 install pymysql 先安装第三方模块
    
    #本质:套接字客户端
    
    import pymysql #模块
    
    #发起连接拿到套接字对象
    client=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='egon123',
        database='db6',  #服务端必须先创建好数据库
        charset='utf8'
    )
    
    #拿到一个能提交sql语句的游标对象
    #游标 接收用户传入的sql语句  send发给服务端
    #底层就是send
    cursor=client.cursor()
    
    sql='insert into t1 values(1,"egon");' #一条sql语句
    try: #捕获异常 和mysql的事务一样
        res=cursor.execute(sql) #给游标提交语句execute   提交但没执行,此时数据库看不到插入的数据
        print(res) #cursor提交是有返回值的  返回值是影响的行数
        # cursor.execute(sql)
        # cursor.execute(sql)
        # cursor.execute(sql)
        client.commit() #真正执行(增删改行为必须要commit),无法回退了,防止异常的
    except Exception:
        client.rollback() #捕获到异常 回滚到没执行的状态 应用在转账交易操作方面
    
    cursor.close()  #关闭游标
    client.close() #关闭链接 回收资源
    pymysql介绍
    #pip3 install pymysql  第三方模块 先安装
    import pymysql
    
    client=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='egon123',
        database='db6',
        charset='utf8'
    )
    
    cursor=client.cursor()
    
    #1
    # sql='insert into t1 values(3,"alex"),(4,"lxx");' 批量写入数据库 这是一种方式 但是写死了
    
    #2
    #多个用户写入数据库的方法
    # userinfo=[
    #     (3,"alex"),
    #     (4,"lxx"),
    #     (5,"yxx")
    # ]
    # for user in userinfo: 遍历写入用execute这种麻烦   可以用executemany 一样的功能
    #     sql='insert into t1 values(%s,"%s");' %(user[0],user[1])  注意加引号
    #     # print(sql)
    #     cursor.execute(sql)
    
    #3
    # userinfo=[
    #     (3,"alex"),
    #     (4,"lxx"),
    #     (5,"yxx")
    # ]
    # sql='insert into t1 values(%s,%s);' 批量
    # cursor.executemany(sql,userinfo) 本质就是for循环  注意插入的个数要一一对应
    
    cursor.execute('delete from t1 where id=3;')  #删除操作
    
    client.commit()
    
    cursor.close()
    client.close()
    基于pymysql的增删改
    # 提交查询语句并且拿到查询结果
    import pymysql
    
    client=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='egon123',
        database='db6',
        charset='utf8'
    )
    
    #如果不加的话 从管道中拿的是元组 加上就会有标题 变成字典列表形式
    cursor=client.cursor(pymysql.cursors.DictCursor)
    #查询
    
    sql='select * from user where id > 3'
    rows=cursor.execute(sql) #异步 sql语句传给服务端 就取执行其他事情
    # print(rows)
    # print(cursor.fetchall()) #从管道中拿到执行的结果 拿完
    # print(cursor.fetchall())
    
    # print(cursor.fetchone())  #拿一条
    # print(cursor.fetchone())
    # print(cursor.fetchone())
    
    # print(cursor.fetchmany(2)) #拿指定的条数
    # print(cursor.fetchone())
    
    
    
    #类似指针的概念 scroll
    # print(cursor.fetchall())
    # # cursor.scroll(0,mode='absolute') # 绝对位置移动 指针移动到头部 从头再查一遍
    # # cursor.scroll(1,mode='absolute') # 绝对位置移动 指针移动到下一条
    # print(cursor.fetchall())
    
    
    # print(cursor.fetchone())
    # cursor.scroll(2,mode='relative') # 相对当前位置移动 跳过两条
    # print(cursor.fetchone())
    
    cursor.close()
    client.close()
    基于pymysql模块的查找
    #pip3 install pymysql
    import pymysql
    
    client=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='egon123',
        database='db5',
        charset='utf8'
    )
    
    cursor=client.cursor(pymysql.cursors.DictCursor)  #返回值以列表中字典形式返回,sql语句的执行结果
    
    #mysql中写好存储过程在python程序中调用 参数一个给n一个给res
    res=cursor.callproc('p4',(3,111)) #set @_p4_0 = 3; set @_p4_1 = 111
    
    # print(res)  返回值就是参数 没什么用
    
    #fetchall 类似于从管道中取值 一次取完 指针移动到末尾
    print(cursor.fetchall())
    
    cursor.execute('select @_p4_1;') #提交查看标识的sql语句
    print(cursor.fetchone()) #查看最后的执行的结果
    
    cursor.close()
    client.close()
    在python中调用存储过程
    # #pip3 install pymysql
    # import pymysql
    #
    # client=pymysql.connect(
    #     host='127.0.0.1',
    #     port=3306,
    #     user='root',
    #     password='egon123',
    #     database='db6',
    #     charset='utf8'
    # )
    #
    # cursor=client.cursor()
    
    #思路:1 输入用户名、密码 2、拼接sql  3、是否有返回值 判断是否验证成功
    # #查询 不需要commit  登录验证 从数据库拿数据验证 登录
    # inp_user=input('输入账号名: ').strip()
    # inp_pwd=input('输入密码: ').strip()
    #
    #注意传入密码 要用密文  一般数据库中存的都是密文 所以明文对不上
    # 密文长度很长 注意设计表的时候要建好长度 不然会超过限制 密文存不全
    
    # # sql='select id from user where name = "%s" and pwd = password("%s");' %(inp_user,inp_pwd)
    # sql='select id from user where name = "%s" and pwd = "%s";' %(inp_user,inp_pwd)
    # print(sql)
    # rows=cursor.execute(sql) #如果name pwd都正确的话 就会返回一个值
    # if rows: 如果返回了id值 说明用户名 密码都正确
    #     print('33[45m登陆成功33[0m')
    # else:
    #     print('33[46m用户名或密码错误33[0m')
    #
    # cursor.close()
    # client.close()
    #
    
    
    #sql注入:通过mysql的一些特殊的符号,来改变sql语句的运行逻辑,从而不需要账号密码 都能登录
    
    #小知识 -- mysql中的注释
    
    #问题1:egon" -- xxxx 密码不用输入 也能登录成功
    #'select id from user where name = "%s" and pwd = password("%s");' %(inp_user,inp_pwd)
    #'select id from user where name = "egon" -- xxxx" and pwd = password("%s");' %(inp_user,inp_pwd)
    
    #问题2:xxx" or 1=1 -- hello  密码不写 也能登录
    #'select id from user where name = "xxx" or 1=1 -- hello" and pwd = password("%s");' %(inp_user,inp_pwd)
    
    
    #解决方法:早期的网站很多这种问题,现在的网站一般都不允许用特殊符号了,就是为了避免这种问题
    #1 前端检测,不允许带特殊符号,全部过滤掉,就不会改变sql的逻辑执行 发给应用程序
    # pymysql已经解决这个问题了 看后面
    #2 不用前端浏览器,跳过检测,所以应用程序也要检测一遍
    
    
    # 解决 sql注入问题 不自己拼接sql语句了
    #pip3 install pymysql
    # import pymysql
    #
    # client=pymysql.connect(
    #     host='127.0.0.1',
    #     port=3306,
    #     user='root',
    #     password='egon123',
    #     database='db6',
    #     charset='utf8'
    # )
    #
    # cursor=client.cursor()
    # #查询
    # inp_user=input('输入账号名: ').strip()
    # inp_pwd=input('输入密码: ').strip()
    #
    # sql='select id from user where name = %s and pwd = %s;'
    # rows=cursor.execute(sql,(inp_user,inp_pwd)) #这一步就自动过滤掉了
    # if rows:
    #     print('33[45m登陆成功33[0m')
    # else:
    #     print('33[46m用户名或密码错误33[0m')
    #
    # cursor.close()
    # client.close()
    sql注入问题

    navicat

    一个桌面版的连接服务端的软件
    解压即可使用
    View Code

    mysql服务端的功能

    开发中用不到,面试要用,需要了解一下
    
    这里面的功能在python程序里都可以实现。
    
    mysql是想把应用程序解放出来
    
    实际应用中还是在程序中实现较多
    View Code
    # 强调
    #1、字段名不能重复
    #2、视图是为了简化查询的sql语句,不应该修改视图中的记录
    create view emp2dep as select emp.*,dep.name as dep_name from emp inner join dep on emp.dep_id = dep.id;
    
    视图就是虚拟表 从多个表中查出来的
    视图保存:只有一张表,没有数据,相当于存储的sql语句   数据来自于其他表
    视图
    增删改没有查会触发触发器的执行
    
    CREATE TABLE cmd (
        id INT PRIMARY KEY auto_increment,
        USER CHAR (32),
        priv CHAR (10),
        cmd CHAR (64),
        sub_time datetime, #提交时间
        success enum ('yes', 'no') #0代表执行失败
    );
    
    CREATE TABLE errlog (
        id INT PRIMARY KEY auto_increment,
        err_id int
    );
    
    
    #创建触发器 检测写入的记录 如果有错的 就向errlog中也写入一份记录
    
    delimiter $$   (也可以用//)   #改变sql的结束符 让分号变成无意义
    CREATE TRIGGER tri_after_insert_cmd AFTER INSERT ON cmd FOR EACH ROW
    BEGIN
        if NEW.success = 'no' then  #NEW: cmd新的记录被封装成了对象
            insert into errlog(err_id) values(NEW.id); #满足条件就插入到另外一张表
        end if;
    END $$ 结束
    delimiter ; #还原成分号作为结束符
    
    INSERT INTO cmd (
        USER,
        priv,
        cmd,
        sub_time,
        success
    )
    VALUES
        ('egon','0755','ls -l /etc',NOW(),'yes'),
        ('egon','0755','cat /etc/passwd',NOW(),'no'),
        ('egon','0755','useradd xxx',NOW(),'no'),
        ('egon','0755','ps aux',NOW(),'yes');
    触发器
    #transaction:事务,交易中使用
    # 事务可以包含一系列的sql语句,事务的执行具有原子性
    #1、原子性:
    #包含多条sql语句要么都执行成功,要么都执行不成功
    #2、回滚
    
    create table user(
    id int primary key auto_increment,
    name char(32),
    balance int
    );
    
    insert into user(name,balance)
    values
    ('wsb',1000),
    ('egon',1000),
    ('ysb',1000);
    
    
    #创建事务 回滚
    start transaction;
    try:
        update user set balance=900 where id=1;
        update user set balance=1010 where id=2;
        update user set balance=1090 where id=3;
        commit; #只要commit就不可逆了 在这之前都可以rollback回滚
    except Exception:
        rollback;
    
    #pymysql 模块默认开启事务
    #mysql 也可以实现事务
    事务
     创建在某个库下面
    
    # 无参
    delimiter $$
    create procedure p1()
    BEGIN
        select * from blog;
    END $$
    delimiter ;
    
    create table s1(
    id int,
    name varchar(20),
    gender char(6),
    email varchar(50)
    );
    
    mysql中调用:call p1();
    
    delimiter $$
    create procedure p2()
    BEGIN
        declare n int default 1; --声明一个变量
        while (n < 100) do
            insert into s1 values(n,concat('egon',n),'male',concat('egon',n,'@163.com'));
            set n=n+1; --自增
        end while;
    END $$
    delimiter ;
    
    mysql:call p2(); 调用
    
    # 有参
    delimiter $$
    create procedure p3(
        in n int,    接收外部传入的值
        out res int  用来返回的
        #inout x int  这种既能接收也能返回
    )
    BEGIN
        select * from blog where id > n;
        set res = 0; 返回值 用来标识执行成功与否
    END $$
    delimiter ;
    
    # 直接在mysql中调用存储过程: 有参的调用
    mysql> set @x=111; 设置变量
    mysql> call p3(3,@x); x传给res
    mysql> select @x; 查询变量
    +------+
    | @x   |
    +------+
    |    0 |
    +------+
    1 row in set (0.00 sec)
    
    
    # 在python中调用:
    cursor.callproc('p4',(3,111)) #set @_p4_0 = 3; set @_p4_1 = 111
    print(cursor.fetchall())
    cursor.execute('select @_p4_1;')
    print(cursor.fetchone())
    存储过程
    date_formate(sub_time,'%Y-%m')
    
    切割时间
    
    函数要和sql语句结合使用,不能单独调用
    函数
    1 条件语句
    if
    2 循环语句
    while
    repeat
    loop
    流程控制
    应用程序与数据库的结合开发方案:
    方案一: 配两个人 一个人写应用程序 一个写sql 但是人之间的沟通成本问题 扩展问题等
        应用程序:
        mysql:编写存储过程
    
    方案二:
        应用程序:原生sql
        mysql:
    
    方案三:
        应用程序:ORM(类/对象 --->原生sql) 类-表 对象-记录
        mysql:
    
    
    
    执行效率:
        方案一 > 方案二 -> 方案三
    
    开发效率:
        方案一 > 方案三 -> 方案二
    
    我们以后用方案三
    存储过程:把视图,触发器,流程控制,等功能 分装成接口提供给应用程序使用
    python与mysql的开发方案
  • 相关阅读:
    C语言格式化字符串细节 --- %*s %*c %*.*s
    ROC曲线与AUC计算总结
    python 数字列表排序,输出对应的索引 | 转载
    python 类间的有趣调用
    Linux下以16进制形式显示文件内容的方法
    一些书签
    椭圆曲线算数原理与实现
    中国剩余定理来解密RSA密文
    在GridView控件内文本框实现TextChanged事件,勾选复选框时 :textbox文本框可编辑,编辑文本框的数字后 总金额会重新计算并统计
    关于RDLC子报表添加参数 错误“本地报表处理期间出错 。值不能为空。 参数名:value” 错误解决方法
  • 原文地址:https://www.cnblogs.com/xujinjin18/p/9368379.html
Copyright © 2020-2023  润新知