当前位置: 首页 > article >正文

mysql的高级进阶

之前我们学了mysql的查询与高级查询和存储过程今天我们来学习mysql的高级进阶

mysql的进阶操作就是多个表进行互相关联的查询操作,首先准备多个数据表。

建多个表

DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `caption` varchar(32) NOT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=innoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

# innoDB 有外键约束   myisam 注释的作用
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) NOT NULL,
  `teacher_id` int(11) NOT NULL,
  PRIMARY KEY (`cid`),
  KEY `fk_course_teacher` (`teacher_id`),
  CONSTRAINT `fk_course_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`tid`)
) ENGINE=innoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) NOT NULL,
  `course_id` int(11) NOT NULL,
  `num` int(11) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_score_student` (`student_id`),
  KEY `fk_score_course` (`course_id`),
  CONSTRAINT `fk_score_course` FOREIGN KEY (`course_id`) REFERENCES `course` (`cid`),
  CONSTRAINT `fk_score_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`sid`)
) ENGINE=innoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `gender` char(1) NOT NULL,
  `class_id` int(11) NOT NULL,
  `sname` varchar(32) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_class` (`class_id`),
  CONSTRAINT `fk_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`cid`)
) ENGINE=innoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `tname` varchar(32) NOT NULL,
  PRIMARY KEY (`tid`)
) ENGINE=innoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

正则表达式

选项匹配说明例子匹配值
^文本开始字符'^b'匹配以字母b开头的字符串book, big,banana,bike
.任何单个字符'b.t'匹配任何b和t之间有一个字符bit, bat,but, bite
*0个或多个在它前面的字符'f*n'匹配字符n前面有任意n个字符ffn, fan,faan, abcn
+前面的字符一次或多次'ba+'匹配以b开头后面紧跟至少一个aba, bay,bare, battle
字符串包含指定字符串的文本'fa'fan, afa,faad
[字符集合]字符集合中的任一个字符'[xz]'匹配x或者zdizzy,zebra, x-ray, extra
[^]不在括号中的任何字符'[^abc]'匹配任何不包含a、b或c的字符串desk, fox,f8ke
字符串{n}前面的字符串至少n次b{2}匹配2个或更多的bbbb, bbbb,bbbbbb
字符串{n,m}前面的字符串至少n次,至多m次b{2,4}匹配最少2个,最多4个bbb, bbb,bbbb
SELECT * FROM `teacher` WHERE `tname` REGEXP '^yang';

视图

视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。其内容由查询定义。用来创建视图的表叫基表,通过视图,可以展现基表的部分数据。视图数据来自定义视图的查询中使用的表,使用视图动态生成。

视图的优点

  1. 简单。使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
  2. 安全。使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。
  3. 数据独立。一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

视图的作用

  1. 可复用,减少重复语句书写,类似程序中函数的作用。
  2. 重构代码,分表。假如因为某种需求,需要将 user 拆成表 usera 和表userb,如果应用程序使用 sql 语句:select * from user那就会提示该表不存在;若此时创建视图 create view user as select a.name,a.age,b.sex from usera as a, userb as b where a.name=b.name;,则只需要更改数据库结构,而不需要更改应用程序。
  3. 逻辑更清晰,屏蔽查询细节,关注数据返回。
  4. 权限控制,某些表对用户屏蔽,但是可以给该用户通过视图来对该表操作。
CREATE VIEW <视图名> AS <SELECT语句>
-- 创建视图
-- 查询 1 课程比 2 课程成绩高的所有学生的学
号;
CREATE VIEW view_test1 AS SELECT
A.student_id
FROM
  (
    SELECT
      student_id,
      num
    FROM
      score
    WHERE
      course_id = 1
  ) AS A -- 12
LEFT JOIN (
  SELECT
    student_id,
    num
  FROM
    score
  WHERE
    course_id = 2
) AS B -- 11
ON A.student_id = B.student_id
WHERE
  A.num >
IF (isnull(B.num), 0, B.num);

 

流程控制

  • IF 语句
IF condition THEN
  ...
ELSEIF condition THEN
  ...
ELSE
  ...
END IF
  • CASE 语句
-- 相当于switch语句
CASE value
  WHEN value THEN ...
  WHEN value THEN ...
  ELSE ...
END CASE
  • WHILE 语句
WHILE condition DO
...
END WHILE;
  • LEAVE 语句
-- 相当于break
LEAVE label;

使用例子如下:

-- LEAVE语句退出循环或程序块,只能和BEGIN ... END,LOOP,REPEAT,WHILE语句配合使用
-- 创建存储过程
DELIMITER //
CREATE PROCEDURE example_leave(OUT sum INT)
BEGIN
  DECLARE i INT DEFAULT 1;
  DECLARE s INT DEFAULT 0;

  while_label:WHILE i<=100 DO
    SET s = s+i;
    SET i = i+1;
    IF i=50 THEN
      -- 退出WHILE循环
      LEAVE while_label;
       END IF;
  END WHILE;

  SET sum = s;
END
//
DELIMITER ;
-- 调用存储过程
CALL example_leave(@sum);
SELECT @sum;
  • ITERATE语句
-- 相当于 continue
ITERATE label
  • LOOP 语句
-- 相当于 while(true) {...}
LOOP
  ...
END LOOP
-- 可以通过LEAVE语句退出循环

使用例子如下:

-- 创建存储过程
DELIMITER
CREATE PROCEDURE example_loop(OUT sum INT)
BEGIN
  DECLARE i INT DEFAULT 1;
  DECLARE s INT DEFAULT 0;

  loop_label:LOOP
    SET s = s+i;
    SET i = i+1;

    IF i>100 THEN
      -- 退出LOOP循环
      LEAVE loop_label;  
    END IF;
  END LOOP;

  SET sum = s;
END

DELIMITER ;
-- 调用存储过程
CALL example_loop(@sum);
SELECT @sum;
  • REPEAT 语句
-- 相当于 do .. while(condition)
REPEAT
  ...
  UNTIL condition
END REPEAT

使用例子如下:

DELIMITER
CREATE PROCEDURE example_repeat(OUT sum INT)
BEGIN
  DECLARE i INT DEFAULT 1;
  DECLARE s INT DEFAULT 0;

  REPEAT
    SET s = s+i;
    SET i = i+1;
    UNTIL i > 100
  END REPEAT;

  SET sum = s;
END

DELIMITER ;
-- 调用存储过程
CALL example_repeat(@sum);
SELECT @sum;

触发器

触发器(trigger)是 MySQL 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程。它的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行 DML 操作(insert,delete,update)时就会激活它执行。

构成触发器的4要素如下:

  1. 监视对象:table
  2. 监视事件:insert、update、delete
  3. 触发时间:before ,after
  4. 触发事件:insert、update、delete
CREATE TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
  [trigger_order]
trigger_body -- 此处写执行语句

-- trigger_body: 可以一个语句,也可以是多个语句;多个语句写在 BEGIN ... END 间
-- trigger_time: { BEFORE | AFTER }
-- trigger_event: { INSERT | UPDATE | DELETE }
-- trigger_order: { FOLLOWS | PRECEDES } other_trigger_name

使用例子如下:

CREATE TABLE `work` (
  `id` INT PRIMARY KEY auto_increment,
  `address` VARCHAR (32)
) DEFAULT charset = utf8 ENGINE = innoDB;
CREATE TABLE `time` (
  `id` INT PRIMARY KEY auto_increment,
  `time` DATETIME
) DEFAULT charset = utf8 ENGINE = innoDB;
-- 创建触发器
CREATE TRIGGER trig_test1 AFTER INSERT
ON `work` FOR EACH ROW
INSERT INTO `time` VALUES(NULL,NOW());

触发器的 NEW 和 OLD

在 INSERT 型触发器中,NEW 用来表示将要(BEFORE)或已经(AFTER)插入的新数据。

在 DELETE 型触发器中,OLD 用来表示将要或已经被删除的原数据。

在 UPDATE 型触发器中,OLD 用来表示将要或已经被修改的原数据,NEW 用来表示将要或已经修改为的新数据。

NEW.columnName (columnName为相应数据表某一列名)
OLD.columnName (columnName为相应数据表某一列名)

触发器的使用案例

CREATE TABLE `goods` (
  `id` INT PRIMARY KEY auto_increment,
  `name` VARCHAR (32),
  `num` SMALLINT DEFAULT 0
);
CREATE TABLE `order` (
  `id` INT PRIMARY KEY auto_increment,
  `goods_id` INT,
  `quantity` SMALLINT COMMENT '下单数量'
);
INSERT INTO goods VALUES (NULL, '手机', 40);
INSERT INTO goods VALUES (NULL, '电脑', 63);
INSERT INTO goodS VALUES (NULL, '平板', 87);
INSERT INTO `order` VALUES (NULL, 1, 3);
INSERT INTO `order` VALUES (NULL, 2, 4);

需求1:客户修改订单购买的数量,在原来购买数量的基础上减少2个

- delimiter
-- delimiter是mysql分隔符,在mysql客户端中分隔符默认是分号 ;。如果一次输入的语句较多,并且语句中间有分号,这时需要重新指定一个特殊的分隔符。
delimiter
CREATE TRIGGER trig_order_1 AFTER INSERT
ON `order` FOR EACH ROW
BEGIN
  UPDATE goods SET num = num - 2 WHERE id = 1;
END
delimiter ;
INSERT

需求2:客户修改订单购买的数量,商品表的库存数量自动改变

delimiter
CREATE TRIGGER trig_order_2 BEFORE UPDATE
ON `order` FOR EACH ROW
BEGIN
  UPDATE goods SET num=num+old.quantity - new.quantity WHERE id = new.goods_id;
END

delimiter ;
-- 测试
UPDATE `order` SET quantity = quantity+2 WHERE id = 1;

数据库游标

游标是针对行操作的,对从数据库中 select 查询得到的结果集的每一行可以进行分开的、独立的、相同或者不相同的操作。对于取出多行数据集,需要针对每行操作,可以使用游标。

游标常用于存储过程、函数、触发器、事件,游标相当于迭代器。

  • 定义游标
DECLARE cursor_name CURSOR FOR select_statement;
  • 打开游标
OPEN cursor_name;
  • 取游标数据
FETCH cursor_name INTO var_name[,var_name,......]
  • 取游标数据
FETCH cursor_name INTO var_name[,var_name,......]
  • 关闭游标
CLOSE curso_name;
  • 释放
DEALLOCATE cursor_name;
  • 设置游标结束标志
DECLARE done INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET done = 1; -- done 为标记为

使用例子如下:

CREATE PROCEDURE proc_while (IN age_in INT, OUT total_out INT)
BEGIN
-- 创建 用于接收游标值的变量
DECLARE p_id,p_age,p_total INT ;
DECLARE p_sex TINYINT ; 
-- 注意:接收游标值为中文时,需要给变量 指定字符集utf8
DECLARE p_name VARCHAR (32) CHARACTER SET utf8 ; 
-- 游标结束的标志
DECLARE done INT DEFAULT 0 ;
-- 声明游标
DECLARE cur_teacher CURSOR FOR SELECT
  teacher_id,
  teacher_name,
  teacher_sex,
  teacher_age
FROM
  teacher
WHERE
  teacher_age > age_in ; -- 指定游标循环结束时的返回值 
DECLARE CONTINUE HANDLER FOR NOT found
SET done = 1 ;
 -- 打开游标
OPEN cur_teacher ;
 -- 初始化 变量
SET p_total = 0 ; 
-- while 循环
WHILE done != 1 DO
  FETCH cur_teacher INTO p_id,
  p_name,
  p_sex,
  p_age ;
    IF done != 1 THEN
        SET p_total = p_total + 1 ;
    END IF;
END WHILE ; 
-- 关闭游标
CLOSE cur_teacher ;
-- 将累计的结果复制给输出参数
SET total_out = p_total ;
END//
delimiter ;
-- 调用
SET @p_age =20;
CALL proc_while(@p_age, @total);
SELECT @total;

数据库权限管理

  • 创建用户
CREATE USER username@host IDENTIFIED BY password;
-- host 指定该用户在哪个主机上可以登陆,如果是本地用户可用localhost,如果想让该用户可以从任意远程主机登陆,可以使用通配符 %
  • 用户授权
GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;
-- privileges:用户的操作权限,如SELECT,INSERT,UPDATE等,如果要授予所的权限则使用ALL
-- databasename.tablename 如果是 *.* 表示任意数据库以及任意表
-- WITH GRANT OPTION 这个选项表示该用户可以将自己拥有的权限授权给别人。
-- 在创建操作用户的时候不指定WITH GRANT OPTION 选项导致,该用户就不能使用 GRANT 命令创建用户或者给其它用户授权.
-- 如果不想这个用户有这个 grant 的权限,则不要加该 WITH GRANT OPTION 选项
  • 对视图授权
GRANT select, SHOW VIEW ON `databasename`.`tablename`  to 'username'@'host';
  • 刷新权限
-- 修改权限后需要刷新权限
FLUSH PRIVILEGES;

Mysql的远程连接

远程连接需要修改配置, 修改mysqld.cnf 中 bind-address 设置IP:

# mysqld.cnf
# vi /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address=127.0.0.1

修改 mysql.user 表,可以修改用户配置.

-- 修改user表
select `user`, `host` from `mysql`.`user`;
update user set host='%' where user='root';

在MySQL的浩瀚宇宙中,我们已经穿梭于性能调优的星辰大海,遨游于复杂查询的逻辑迷宫,攀登过数据库架构设计的巍峨高峰,穿越了安全策略的迷雾森林,最终抵达了高可用性和可扩展性的广阔天地。然而,这趟旅程并非终点,而是一个新的起点。

随着技术的不断演进,MySQL的高级进阶之路充满了未知与挑战。想象一下,未来的数据库世界可能充满了人工智能的智能优化、量子计算的革命性突破,以及边缘计算的全新应用场景。在这样的背景下,我们不仅需要掌握现有的知识,更需要培养一种能够快速适应新技术、新方法的能力。

在追求技术卓越的同时,我们也不应忽视团队协作的力量。数据库专家、开发人员、系统管理员和业务分析师之间的紧密合作,是实现高效数据库解决方案的关键。通过有效的沟通和协作,我们能够将复杂的技术问题转化为实际可行的解决方案,为组织的成功奠定坚实的基础。

让我们以开放的心态迎接每一个挑战,以创新的精神探索每一个未知领域。通过不断的学习和实践,我们不仅能够提升自己的专业技能,还能够为整个数据库社区贡献自己的力量。在这个不断变化的世界里,让我们成为引领变革的先锋,用我们的智慧和热情,书写MySQL高级进阶的辉煌篇章。

记住,技术的世界没有终点,只有不断前进的旅程。让我们一起,拥抱变化,勇往直前,探索MySQL的无限可能。

 


http://www.kler.cn/a/387197.html

相关文章:

  • WebAssembly在现代Web开发中的应用
  • Django基础用法+Demo演示
  • 某app最新版 vmp算法分析一
  • Openstack7--安装消息队列服务RabbitMQ
  • 若依笔记(八):Docker容器化并部署到公网
  • vxe-table 3.10+ 进阶高级用法(一),根据业务需求自定义实现筛选功能
  • 前端刺客系列----Vue 3 入门介绍
  • 数据挖掘(十)
  • Elasticsearch与Redis的Netty冲突
  • CentOS 9 Stream 上安装 PostgreSQL 16
  • C++builder中的人工智能(18):神经网络中的SoftMax函数
  • el-tab使用
  • 新手如何快速搭建一个Springboot项目
  • 代码随想录刷题记录(二十五)——54. 替换数字
  • 【信号处理】绘制IQ信号时域图、星座图、功率谱
  • 吾店云介绍 – 中国人的WordPress独立站和商城系统平台
  • docker进行SRS直播服务器搭建
  • WPS 默认模板修改
  • 关于qiskit版本>1.0.0,execute函数被替换
  • Java基于微信小程序的美食推荐系统(附源码,文档)
  • ONLYOFFICE 办公套件测评:高效办公新选择
  • 「Mac畅玩鸿蒙与硬件32」UI互动应用篇9 - 番茄钟倒计时应用
  • Python自动化运维:配置管理工具到自动化部署与版本控制
  • Flutter错误: uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared
  • Shortcut Learning in In-Context Learning: A Survey
  • MySQL 权限困境:从权限丢失到权限重生的完整解决方案20241108