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\' 部分内置函数
需要记住:
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 ;
六. 游标+存储过程(相当于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
七. 存储过程+动态执行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 ;
八、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()
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()
九、数据库操作总结:
1、SQL语句(MySQL一博客)重要常用
2、利用mysql内部提供的功能(视图、触发器、函数、存储过程)
以上是关于MySQL的主要内容,如果未能解决你的问题,请参考以下文章
连接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“(代码片段