MySQL

Posted Python

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL相关的知识,希望对你有一定的参考价值。

前言:

数据库相关的操作

1.SQL语句 *****(mysql(一)已经介绍

2.利用mysql内部提供的功能(视图、触发器、函数、存储过程

一、视图:

把经常使用的查询结果,做成临时视图表,保存方便反复使用;

1、创建视图:

CREATE VIEW zhanggen as  SELECT * FROM score;

2、查看视图:

SELECT * FROM zh;

3、删除视图

drop view zh

 

二、触发器

当对某张表做:增删改操作时,可以使用触发器自定义关联行为;

1.插入前触发器:

格式:创建触发器  名称  BEFORE INSERT(操作 前/后)  on 表   FOR EACH ROW(没插入一条数据触发器执行一次)


CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
...  触发器
END

 

2、插入后 触发器

格式:创建触发器  名称  AFTER INSERT(操作 前/后)  on 表   FOR EACH ROW(没插入一条数据触发器执行一次)


CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
...触发器
END

 

3、删除前触发器

格式:创建触发器  名称   BEFORE DELETE(操作 前/后)  on 表   FOR EACH ROW(没插入一条数据触发器执行一次)
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
BEGIN
...触发器
END

 

4、删除后触发器

格式:创建触发器  名称   AFTER DELETE (操作 前/后)  on 表   FOR EACH ROW(没插入一条数据触发器执行一次)
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
BEGIN
...
END

 

5、更新前触发器

格式:创建触发器  名称   BEFORE UPDATE  (操作 前/后)  on 表   FOR EACH ROW(没插入一条数据触发器执行一次)
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
BEGIN
...
END

 

6、更新后触发器

格式:创建触发器  名称   AFTER UPDATE(操作 前/后)  on 表   FOR EACH ROW(没插入一条数据触发器执行一次)

CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
BEGIN
...
END

 

7、

NEW,代指新数据 (更新)
OLD,代指老数据 (删除)

delimiter //:修改SQL语句的结束符

insert into tb (....)

delimiter //
create trigger t1 BEFORE INSERT on student for EACH ROW
BEGIN
INSERT into teacher(tname) values(NEW.sname);
INSERT into teacher(tname) values(NEW.sname);
INSERT into teacher(tname) values(NEW.sname);
INSERT into teacher(tname) values(NEW.sname);
END //
delimiter ;

insert into student(gender,class_id,sname) values(\'女\',1,\'陈涛\'),(\'女\',1,\'张根\');

 

三、函数

1、SQL语句的内置函数(max(),min(),count()...)

CHAR_LENGTH(str)
        返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算作一个单字符。
        对于一个包含五个二字节字符集, LENGTH()返回值为 10, 而CHAR_LENGTH()的返回值为5。

    CONCAT(str1,str2,...)
        字符串拼接
        如有任何一个参数为NULL ,则返回值为 NULL。
    CONCAT_WS(separator,str1,str2,...)
        字符串拼接(自定义连接符)
        CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。

    CONV(N,from_base,to_base)
        进制转换
        例如:
            SELECT CONV(\'a\',16,2); 表示将 a 由16进制转换为2进制字符串表示

    FORMAT(X,D)
        将数字X 的格式写为\'#,###,###.##\',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若  D 为 0, 则返回结果不带有小数点,或不含小数部分。
        例如:
            SELECT FORMAT(12332.1,4); 结果为: \'12,332.1000\'
    INSERT(str,pos,len,newstr)
        在str的指定位置插入字符串
            pos:要替换位置其实位置
            len:替换的长度
            newstr:新字符串
        特别的:
            如果pos超过原字符串长度,则返回原字符串
            如果len超过原字符串长度,则由新字符串完全替换
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一个出现位置。

    LEFT(str,len)
        返回字符串str 从开始的len位置的子序列字符。

    LOWER(str)
        变小写

    UPPER(str)
        变大写

    LTRIM(str)
        返回字符串 str ,其引导空格字符被删除。
    RTRIM(str)
        返回字符串 str ,结尾空格字符被删去。
    SUBSTRING(str,pos,len)
        获取字符串子序列

    LOCATE(substr,str,pos)
        获取子序列索引位置

    REPEAT(str,count)
        返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count 。
        若 count <= 0,则返回一个空字符串。
        若str 或 count 为 NULL,则返回 NULL 。
    REPLACE(str,from_str,to_str)
        返回字符串str 以及所有被字符串to_str替代的字符串from_str 。
    REVERSE(str)
        返回字符串 str ,顺序和字符顺序相反。
    RIGHT(str,len)
        从字符串str 开始,返回从后边开始len个字符组成的子序列

    SPACE(N)
        返回一个由N空格组成的字符串。

    SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
        不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。

        mysql> SELECT SUBSTRING(\'Quadratically\',5);
            -> \'ratically\'

        mysql> SELECT SUBSTRING(\'foobarbar\' FROM 4);
            -> \'barbar\'

        mysql> SELECT SUBSTRING(\'Quadratically\',5,6);
            -> \'ratica\'

        mysql> SELECT SUBSTRING(\'Sakila\', -3);
            -> \'ila\'

        mysql> SELECT SUBSTRING(\'Sakila\', -5, 3);
            -> \'aki\'

        mysql> SELECT SUBSTRING(\'Sakila\' FROM -4 FOR 2);
            -> \'ki\'

    TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str) TRIM(remstr FROM] str)
        返回字符串 str , 其中所有remstr 前缀和/或后缀都已被删除。若分类符BOTH、LEADIN或TRAILING中没有一个是给定的,则假设为BOTH 。 remstr 为可选项,在未指定情况下,可删除空格。

        mysql> SELECT TRIM(\'  bar   \');
                -> \'bar\'

        mysql> SELECT TRIM(LEADING \'x\' FROM \'xxxbarxxx\');
                -> \'barxxx\'

        mysql> SELECT TRIM(BOTH \'x\' FROM \'xxxbarxxx\');
                -> \'bar\'

        mysql> SELECT TRIM(TRAILING \'xyz\' FROM \'barxxyz\');
                -> \'barx\'

部分内置函数
View Code

 

 

需要记住:

SELECT CURDATE()查询当前时间;

 

data_format(ctime,"%Y-%m"):设置时间类型数据的格式;(在内存修改,不会改掉原数据;(通过月group by 就可设计博客园,每月博客统计的效果;)

 

 

2、自定义函数:

注意 1、函数必须有返回值 2、函数体不能出现select * from 表 

 自定义函数(有返回值):

 


delimiter \\\\

create function f1(
i1 int,
i2 int)
returns int
BEGIN
declare num int default 0;
set num = i1 + i2;
return(num);
END \\\\
delimiter ;

SELECT f1(1,100);

调用:SELECT f1(1,100);

 

3、调用函数

执行函数 select 函数名();

 

四、普通存储过程


1.什么是存储过程:

在数据库里保存别名 -------《封装一堆SQL语句操作》,开发人员直接调用别名,无需要程序里写SQL语句了;


2.功能:

替代程序员写SQL语句;


3.公司中常见的 数据库使用场景:

方式1:
在数据库里面:保存存储过程别名;
在程序里面: 直接调用 存储过程别名;

方式2:
在程序里面语句写 SQL

方式3:

在程序里写 类和对象;(通过程序中写好的库,转换成SQL语句)

 

4、存储过程的定义:


4.1. 简单无参数存储过程

create procedure p1()
BEGIN
select * from student;
INSERT into teacher(tname) values("ct");
END

call p1()
cursor.callproc(\'p1\')

4.2、带参数的存储过程

delimiter //
create procedure p3(
in n1 int,
inout n2 int
)
BEGIN
set n2 = 123123;
select * from student where sid > n1;
END //
delimiter ;

 

5、存储过程的调用:

5.1.在mysql端调用存储过程别名:

 

set @v1 = 10;(设置变量(session))在session级别创建变量:set @变量名

call p2(12,@v1) 调用存储过程,返回存储过程执行的结果集;

select @v1; 查看了out参数返回的值

5.2Python调用存储过程别名:

查看存储过程的结果集:

cursor.callproc(\'p3\',(12,2))
r1 = cursor.fetchall()
print(r1)

查看out参数返回的值:注意

cursor.execute(\'select @_p3_0,@_p3_1\')
r2 = cursor.fetchall()
print(r2) 

6、参数 in、out、inout参数的意义

in:普通值,给存储过程内部传值,在存存储过程外部无法获取;

out:变量,给存储过程外部输出值,在存储过程内部无法使用;

inout变量:既能在存储过程内部使,还可以有返回值;


7、大波课上一问:为什么有存储过程执行完了返回了结果集,还需要 out参数的返回值?

delimiter //
create procedure p3(
in n1 int,
out n2 int
out n3 int)

BEGIN
insert into vv(..) set n2= 1
insert into vv(..)
insert into vv(..)
insert into vv(..)
insert into vv(..)
insert into vv(..) set n3=6

END //
delimiter;

利用out返回值,判断存储过程的执行状态,n2=1 执行到了insert1 n3=6执行到了insert=6;

8、阿根课上一疑?存储过程封装了SQL语句,和TND上面说函数不是一样一样滴吗?

答:不是的

1、函数不可以封装 查询类型的SQL语句

3、参数不一样 存储过程的函数 分in/out/inout三类,函数没有

2、调用方式不一样(函数select,存储过程call)

 

五、支持事务的存储过程

delimiter //
            create procedure p4(
                out status int
            )
            BEGIN
                1. 声明如果出现异常则执行{
                    set status = 1;
                    rollback;
                }
                   
                开始事务
                    -- 由秦兵账户减去100
                    -- 方少伟账户加90
                    -- 张根账户加10
                    commit;
                结束
                
                set status = 2;
                
                
            END //
            delimiter ;
            
            ===============================
            delimiter \\\\
            create PROCEDURE p5(
                OUT p_return_code tinyint
            )
            BEGIN 
              DECLARE exit handler for sqlexception 
              BEGIN 
                -- ERROR 
                set p_return_code = 1; 
                rollback; 
              END; 
             
              START TRANSACTION; 
                DELETE from tb1;
                insert into tb2(name)values(\'seven\');
              COMMIT; 
             
              -- SUCCESS 
              set p_return_code = 2; 
             
              END\\\\
            delimiter ;
View Code

 

六. 游标+存储过程(相当于Python的for循环,对表中列,一一设置。)

delimiter //
            create procedure p6()
            begin 
                declare row_id int; -- 自定义变量1  
                declare row_num int; -- 自定义变量2 
                declare done INT DEFAULT FALSE;
                declare temp int;
                
                declare my_cursor CURSOR FOR select id,num from A;
                declare CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
                
                
                
                open my_cursor;
                    xxoo: LOOP
                        fetch my_cursor into row_id,row_num;
                        if done then 
                            leave xxoo;
                        END IF;
                        set temp = row_id + row_num;
                        insert into B(number) values(temp);
                    end loop xxoo;
                close my_cursor;
                
                
            end  //
            delimter
View Code

 

七. 存储过程+动态执行SQL(防SQL注入)

delimiter //
            create procedure p7(
                in tpl varchar(255),
                in arg int
            )
            begin 
                1. 预检测某个东西 SQL语句合法性
                2. SQL =格式化 tpl + arg 
                3. 执行SQL语句
                
                set @xo = arg;
                PREPARE xxx FROM \'select * from student where sid > ?\';
                EXECUTE xxx USING @xo;
                DEALLOCATE prepare prod; 
            end  //
            delimter ;
        
        
            
            call p7("select * from tb where id > ?",9)
        
            ===> 
    
            delimiter \\\\
            CREATE PROCEDURE p8 (
                in nid int
            )
            BEGIN
                set @nid = nid;
                PREPARE prod FROM \'select * from student where sid > ?\';
                EXECUTE prod USING @nid;
                DEALLOCATE prepare prod; 
            END\\\\
            delimiter ;
View Code

 

八、Python的操作MySQL (pymysql模块)

 

1、用户、密码在mysql,python实现用户登录

import pymysql
user=input("username:").strip()
pwd=input("password:").strip()
conn=pymysql.connect(host="192.168.182.128",user="eric",password="123123",database="day58") #数据库连接对象
cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)   #创建游标对象(打开数据库的小手)
                                                        # cursor=pymysql.cursors.DictCursor参数会把fetch到的结果变成,字典套元组的格式;
sql="select * from user_info where name= %s and passwd= %s"
cursor.execute(sql,[user,pwd])                          # pymysql的excute([参数1,参数2])方法,会自动帮我们做字符串拼接,并检查SQL注入
res=cursor.fetchone()
print(res)
print("登录成功") if  res else print("用户/密码错误")
cursor.close()
conn.close()
View Code

2、插入300W条数据

import  pymysql
conn=pymysql.connect(host="192.168.182.128",user="eric",password="123123",database="day61")
cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)
for i in range(3000000):
    i=str(i)
    name=i+\'alex\'
    gender="man"
    email=name+"@163.com"
    sql = "insert into user(name,gender,email)values(%s,%s,%s)"
    cursor.execute(sql,[name,gender,email])
    if cursor.lastrowid%500000==0:
        print(cursor.lastrowid)   # cursor.lastrowid 属性获取最后一条数据的自增ID
        conn.commit()    # 注意不要忘记:conn.commit()提交了事物,数据库中的数据才会更新;
else:print("插入完成!")
cursor.close()      # 最后记得:关闭游标、关闭连接
conn.close()
View Code

 

 

 

九、数据库操作总结

1、SQL语句(MySQL一博客)重要常用

2、利用mysql内部提供的功能(视图、触发器、函数、存储过程)

 

以上是关于MySQL的主要内容,如果未能解决你的问题,请参考以下文章

从mysql的片段中加载ListView

连接MySQL出现错误:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)(代码片段

使用 json rereiver php mysql 在片段中填充列表视图

关于mysql驱动版本报错解决,Cause: com.mysql.jdbc.exceptions.jdbc4Unknown system variable ‘query_cache_size(代码片段

修改MySQL密码报错“ERROR 1819 (HY000): Your password does not satisfy the current policy requirements“(代码片段

mysql查看版本的四种方法