-
MySQL 5.1对服务器一方的预制语句提供支持。如果您使用合适的客户端编程界面,则这种支持可以发挥在MySQL 4.1中实施的高效客户端/服务器二进制协议的优势。候选界面包括MySQL C API客户端库(用于C程序)、MySQL Connector/J(用于Java程序)和MySQL Connector/NET。例如,C API可以提供一套能组成预制语句API的函数调用。其它语言界面可以对使用了二进制协议(通过在C客户端库中链接)的预制语句提供支持。对预制语句,还有一个SQL界面可以利用。与在整个预制语句API中使用二进制协议相比,本界面效率没有那么高,但是它不要求编程,因为在SQL层级,可以直接利用本界面:当您无法利用编程界面时,您可以使用本界面。有些程序允许您发送SQL语句到将被执行的服务器中,比如mysql客户端程序。您可以从这些程序中使用本界面。即使客户端正在使用旧版本的客户端库,您也可以使用本界面。唯一的要求是,您能够连接到一个支持预制语句SQL语法的服务器上。预制语句的SQL语法在以下情况下使用:在编代码前,您想要测试预制语句在您的应用程序中运行得如何。或者也许一个应用程序在执行预制语句时有问题,您想要确定问题是什么。 您想要创建一个测试案例,该案例描述了您使用预制语句时出现的问题,以便您编制程序错误报告。 您需要使用预制语句,但是您无法使用支持预制语句的编程API。预制语句的SQL语法基于三个SQL语句:PREPARE stmt_name FROM preparable_stmt; EXECUTE stmt_name [USING @var_name [, @var_name] ...]; {DEALLOCATE | DROP} PREPARE stmt_name;PREPARE语句用于预备一个语句,并赋予它名称stmt_name,借此在以后引用该语句。语句名称对案例不敏感。preparable_stmt可以是一个文字字符串,也可以是一个包含了语句文本的用户变量。该文本必须展现一个单一的SQL语句,而不是多个语句。使用本语句,'?'字符可以被用于制作参数,以指示当您执行查询时,数据值在哪里与查询结合在一起。'?'字符不应加引号,即使您想要把它们与字符串值结合在一起,也不要加引号。参数制作符只能被用于数据值应该出现的地方,不用于SQL关键词和标识符等。如果带有此名称的预制语句已经存在,则在新的语言被预备以前,它会被隐含地解除分配。这意味着,如果新语句包含一个错误并且不能被预备,则会返回一个错误,并且不存在带有给定名称语句。预制语句的范围是客户端会话。在此会话内,语句被创建。其它客户端看不到它。在预备了一个语句后,您可使用一个EXECUTE语句(该语句引用了预制语句名称)来执行它。如果预制语句包含任何参数制造符,则您必须提供一个列举了用户变量(其中包含要与参数结合的值)的USING子句。参数值只能有用户变量提供,USING子句必须准确地指明用户变量。用户变量的数目与语句中的参数制造符的数量一样多。您可以多次执行一个给定的预制语句,在每次执行前,把不同的变量传递给它,或把变量设置为不同的值。要对一个预制语句解除分配,需使用DEALLOCATE PREPARE语句。尝试在解除分配后执行一个预制语句会导致错误。如果您终止了一个客户端会话,同时没有对以前已预制的语句解除分配,则服务器会自动解除分配。以下SQL语句可以被用在预制语句中:CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE和多数的SHOW语句。目前不支持其它语句。以下例子显示了预备一个语句的两种方法。该语句用于在给定了两个边的长度时,计算三角形的斜边。第一个例子显示如何通过使用文字字符串来创建一个预制语句,以提供语句的文本:mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; mysql> SET @a = 3; mysql> SET @b = 4; mysql> EXECUTE stmt1 USING @a, @b; +------------+ | hypotenuse | +------------+ | 5 | +------------+ mysql> DEALLOCATE PREPARE stmt1;第二个例子是相似的,不同的是提供了语句的文本,作为一个用户变量:mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; mysql> PREPARE stmt2 FROM @s; mysql> SET @a = 6; mysql> SET @b = 8; mysql> EXECUTE stmt2 USING @a, @b; +------------+ | hypotenuse | +------------+ | 10 | +------------+ mysql> DEALLOCATE PREPARE stmt2;对于已预备的语句,您可以使用位置保持符。以下语句将从tb1表中返回一行:mysql> SET @a=1; mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?"; mysql> EXECUTE STMT USING @a;以下语句将从tb1表中返回第二到第六行:mysql> SET @skip=1; SET @numrows=5; mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?, ?"; mysql> EXECUTE STMT USING @skip, @numrows;预制语句的SQL语法不能被用于带嵌套的风格中。也就是说,被传递给PREPARE的语句本身不能是一个PREPARE, EXECUTE或DEALLOCATE PREPARE语句。预制语句的SQL语法与使用预制语句API调用不同。例如,您不能使用mysql_stmt_prepare() CAPI函数来预备一个PREPARE, EXECUTE或DEALLOCATE PREPARE语句。预制语句的SQL语法可以在已存储的过程中使用,但是不能在已存储的函数或触发程序中使用。以上就是本文的全部内容,希望对大家的学习有所帮助。
-
一、概述 变量在存储过程中会经常被使用,变量的使用方法是一个重要的知识点,特别是在定义条件这块比较重要。 mysql版本:5.6二、变量定义和赋值 #创建数据库 DROP DATABASE IF EXISTS Dpro; CREATE DATABASE Dpro CHARACTER SET utf8 ; USE Dpro; #创建部门表 DROP TABLE IF EXISTS Employee; CREATE TABLE Employee (id INT NOT NULL PRIMARY KEY COMMENT '主键', name VARCHAR(20) NOT NULL COMMENT '人名', depid INT NOT NULL COMMENT '部门id' ); INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100),(2,'王',101),(3,'张',101),(4,'李',102),(5,'郭',103);declare定义变量在存储过程和函数中通过declare定义变量在BEGIN...END中,且在语句之前。并且可以通过重复定义多个变量注意:declare定义的变量名不能带‘@'符号,mysql在这点做的确实不够直观,往往变量名会被错成参数或者字段名。DECLARE var_name[,...] type [DEFAULT value]例如:DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陈'; SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid; END$$ DELIMITER ;SET变量赋值SET除了可以给已经定义好的变量赋值外,还可以指定赋值并定义新变量,且SET定义的变量名可以带‘@'符号,SET语句的位置也是在BEGIN ....END之间的语句之前。1.变量赋值SET var_name = expr [, var_name = expr] ... DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陈'; SET pname='王'; SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid AND name=pname; END$$ DELIMITER ; CALL Pro_Employee(101,@pcount); SELECT @pcount;2.通过赋值定义变量DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陈'; SET pname='王'; SET @ID=1; SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid AND name=pname; SELECT @ID; END$$ DELIMITER ; CALL Pro_Employee(101,@pcount);SELECT ... INTO语句赋值通过select into语句可以将值赋予变量,也可以之间将该值赋值存储过程的out参数,上面的存储过程select into就是之间将值赋予out参数。DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陈'; DECLARE Pid INT; SELECT COUNT(id) INTO Pid FROM Employee WHERE depid=pdepid AND name=pname; SELECT Pid; END$$ DELIMITER ; CALL Pro_Employee(101,@pcount);这个存储过程就是select into将值赋予变量;表中并没有depid=101 and name='陈'的记录。三、条件 条件的作用一般用在对指定条件的处理,比如我们遇到主键重复报错后该怎样处理。定义条件 定义条件就是事先定义某种错误状态或者sql状态的名称,然后就可以引用该条件名称开做条件处理,定义条件一般用的比较少,一般会直接放在条件处理里面DECLARE condition_name CONDITION FOR condition_value condition_value: SQLSTATE [VALUE] sqlstate_value | mysql_error_code1.没有定义条件:DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100); SET @ID=3; END$$ DELIMITER ; #执行存储过程 CALL Pro_Employee_insert(); #查询变量值 SELECT @ID,@X;报主键重复的错误,其中1062是主键重复的错误代码,23000是sql错误状态2.定义处理条件DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN #定义条件名称, DECLARE reprimary CONDITION FOR 1062; #引用前面定义的条件名称并做赋值处理 DECLARE EXIT HANDLER FOR reprimary SET @x=1; SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100); SET @ID=3; END$$ DELIMITER ; CALL Pro_Employee_insert(); SELECT @ID,@X;在执行存储过程的步骤中并没有报错,但是由于我定义的是exit,所以在遇到报错sql就终止往下执行了。接下来看看continue的不同。DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN #定义条件名称, DECLARE reprimary CONDITION FOR SQLSTATE '23000'; #引用前面定义的条件名称并做赋值处理 DECLARE CONTINUE HANDLER FOR reprimary SET @x=1; SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100); SET @ID=3; END$$ DELIMITER ; CALL Pro_Employee_insert(); SELECT @ID,@X;其中红色标示的是和上面不同的地方,这里定义条件使用的是SQL状态,也是主键重复的状态;并且这里使用的是CONTINUE就是遇到错误继续往下执行。 条件处理条件处理就是之间定义语句的错误的处理,省去了前面定义条件名称的步骤。DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement handler_type: CONTINUE| EXIT| UNDO condition_value: SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_codehandler_type:遇到错误是继续往下执行还是终止,目前UNDO还没用到。CONTINUE:继续往下执行EXIT:终止执行condition_values:错误状态SQLSTATE [VALUE] sqlstate_value:就是前面讲到的SQL错误状态,例如主键重复状态SQLSTATE '23000'condition_name:上面讲到的定义条件名称SQLWARNING:是对所有以01开头的SQLSTATE代码的速记,例如:DECLARE CONTINUE HANDLER FOR SQLWARNING。NOT FOUND:是对所有以02开头的SQLSTATE代码的速记。SQLEXCEPTION:是对所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码的速记。mysql_error_code:是错误代码,例如主键重复的错误代码是1062,DECLARE CONTINUE HANDLER FOR 1062 语句:DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN #引用前面定义的条件名称并做赋值处理 DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @x=2; #开始事务必须在DECLARE之后 START TRANSACTION ; SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(7,'陈',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100); SET @ID=3; IF @x=2 THEN ROLLBACK; ELSE COMMIT; END IF; END$$ DELIMITER ; #执行存储过程 CALL Pro_Employee_insert(); #查询 SELECT @ID,@X;通过SELECT @ID,@X可以知道存储过程已经执行到了最后,但是因为存储过程后面有做回滚操作整个语句进行了回滚,所以ID=7的符合条件的记录也被回滚了。总结 变量的使用不仅仅只有这些,在光标中条件也是一个很好的功能,刚才测试的是continue如果使用EXIT的话语句执行完“SET @ID=2;”就不往下执行了,后面的IF也不被执行整个语句不会被回滚,但是使用CONTINE当出现错误后还是会往下执行如果后面的语句还有很多的话整个回滚的过程将会很长,在这里可以利用循环,当出现错误立刻退出循环执行后面的if回滚操作,在下一篇讲循环语句会写到,欢迎关注华为云社区数据库板块·。
-
mysql游标的用法及作用例子:当前有三张表A、B、C其中A和B是一对多关系,B和C是一对多关系,现在需要将B中A表的主键存到C中;常规思路就是将B中查询出来然后通过一个update语句来更新C表就可以了,但是B表中有2000多条数据,难道要执行2000多次?显然是不现实的;最终找到写一个存储过程然后通过循环来更新C表,然而存储过程中的写法用的就是游标的形式。简介游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标充当指针的作用。尽管游标能遍历结果中的所有行,但他一次只指向一行。游标的作用就是用于对查询数据库所返回的记录进行遍历,以便进行相应的操作。用法一、声明一个游标: declare 游标名称 CURSOR for table;(这里的table可以是你查询出来的任意集合)二、打开定义的游标:open 游标名称;三、获得下一行数据:FETCH 游标名称 into testrangeid,versionid;四、需要执行的语句(增删改查):这里视具体情况而定五、释放游标:CLOSE 游标名称;注:mysql存储过程每一句后面必须用;结尾,使用的临时字段需要在定义游标之前进行声明。实例- BEGIN --定义变量 declare testrangeid BIGINT; declare versionid BIGINT; declare done int; --创建游标,并存储数据 declare cur_test CURSOR for select id as testrangeid,version_id as versionid from tp_testrange; --游标中的内容执行完后将done设置为1 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; --打开游标 open cur_test; --执行循环 posLoop:LOOP --判断是否结束循环 IF done=1 THEN LEAVE posLoop; END IF; --取游标中的值 FETCH cur_test into testrangeid,versionid; --执行更新操作 update tp_data_execute set version_id=versionid where testrange_id = testrangeid; END LOOP posLoop; --释放游标 CLOSE cur_test; END -例子2:--在windows系统中写存储过程时,如果需要使用declare声明变量,需要添加这个关键字,否则会报错。 delimiter // drop procedure if exists StatisticStore; CREATE PROCEDURE StatisticStore() BEGIN --创建接收游标数据的变量 declare c int; declare n varchar(20); --创建总数变量 declare total int default 0; --创建结束标志变量 declare done int default false; --创建游标 declare cur cursor for select name,count from store where name = 'iphone'; --指定游标循环结束时的返回值 declare continue HANDLER for not found set done = true; --设置初始值 set total = 0; --打开游标 open cur; --开始循环游标里的数据 read_loop:loop --根据游标当前指向的一条数据 fetch cur into n,c; --判断游标的循环是否结束 if done then leave read_loop; --跳出游标循环 end if; --获取一条数据时,将count值进行累加操作,这里可以做任意你想做的操作, set total = total + c; --结束游标循环 end loop; --关闭游标 close cur; --输出结果 select total; END; --调用存储过程 call StatisticStore();fetch是获取游标当前指向的数据行,并将指针指向下一行,当游标已经指向最后一行时继续执行会造成游标溢出。使用loop循环游标时,他本身是不会监控是否到最后一条数据了,像下面代码这种写法,就会造成死循环;read_loop:loop fetch cur into n,c; set total = total+c; end loop;在MySql中,造成游标溢出时会引发mysql预定义的NOT FOUND错误,所以在上面使用下面的代码指定了当引发not found错误时定义一个continue 的事件,指定这个事件发生时修改done变量的值。declare continue HANDLER for not found set done = true;所以在循环时加上了下面这句代码:--判断游标的循环是否结束 if done then leave read_loop; --跳出游标循环 end if;如果done的值是true,就结束循环。继续执行下面的代码使用方式游标有三种使用方式:第一种就是上面的实现,使用loop循环;第二种方式如下,使用while循环:drop procedure if exists StatisticStore1; CREATE PROCEDURE StatisticStore1() BEGIN declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'iphone'; declare continue HANDLER for not found set done = true; set total = 0; open cur; fetch cur into n,c; while(not done) do set total = total + c; fetch cur into n,c; end while; close cur; select total; END; call StatisticStore1();第三种方式是使用repeat执行:drop procedure if exists StatisticStore2; CREATE PROCEDURE StatisticStore2() BEGIN declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'iphone'; declare continue HANDLER for not found set done = true; set total = 0; open cur; repeat fetch cur into n,c; if not done then set total = total + c; end if; until done end repeat; close cur; select total; END; call StatisticStore2();游标嵌套在mysql中,每个begin end 块都是一个独立的scope区域,由于MySql中同一个error的事件只能定义一次,如果多定义的话在编译时会提示Duplicate handler declared in the same block。drop procedure if exists StatisticStore3; CREATE PROCEDURE StatisticStore3() BEGIN declare _n varchar(20); declare done int default false; declare cur cursor for select name from store group by name; declare continue HANDLER for not found set done = true; open cur; read_loop:loop fetch cur into _n; if done then leave read_loop; end if; begin declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'iphone'; declare continue HANDLER for not found set done = true; set total = 0; open cur; iphone_loop:loop fetch cur into n,c; if done then leave iphone_loop; end if; set total = total + c; end loop; close cur; select _n,n,total; end; begin declare c int; declare n varchar(20); declare total int default 0; declare done int default false; declare cur cursor for select name,count from store where name = 'android'; declare continue HANDLER for not found set done = true; set total = 0; open cur; android_loop:loop fetch cur into n,c; if done then leave android_loop; end if; set total = total + c; end loop; close cur; select _n,n,total; end; begin end; end loop; close cur; END; call StatisticStore3();上面就是实现一个嵌套循环,当然这个例子比较牵强。凑合看看就行。动态SQLMysql 支持动态SQL的功能set @sqlStr='select * from table where condition1 = ?'; prepare s1 for @sqlStr; --如果有多个参数用逗号分隔 execute s1 using @condition1; --手工释放,或者是 connection 关闭时, server 自动回收 deallocate prepare s1;
-
如何快速的复制一张表首先创建一张表db1.t,并且插入1000行数据,同时创建一个相同结构的表db2.t假设,现在需要把db1.t里面的a>900的数据行导出来,插入到db2.t中mysqldump方法几个关键参数注释:–single-transaction的作用是,在导出数据的时候不需要对表db1.t加表锁,而是使用START TRANSACTION WITH CONSISTENT SNAPSHOT的方法;–no-create-info的意思是,不需要导出表结构;–result-file指定了输出文件的路径,其中client表示生成的文件是在客户端机器上的。导出csv文件select * from db1.t where a>900 into outfile '/server_tmp/t.csv';这条语句会将结果保存在服务端。如果你执行命令的客户端和MySQL服务端不在同一个机器上,客户端机器的临时目录下是不会生成t.csv文件的。这条命令不会帮你覆盖文件,因此你需要确保/server_tmp/t.csv这个文件不存在,否则执行语句时就会因为有同名文件的存在而报错。得到.csv导出文件后,你就可以用下面的load data命令将数据导入到目标表db2.t中。load data infile '/server_tmp/t.csv' into table db2.t;打开文件/server_tmp/t.csv,以制表符(\t)作为字段间的分隔符,以换行符(\n)作为记录之间的分隔符,进行数据读取;启动事务。判断每一行的字段数与表db2.t是否相同:若不相同,则直接报错,事务回滚;若相同,则构造成一行,调用InnoDB引擎接口,写入到表中。重复步骤3,直到/server_tmp/t.csv整个文件读入完成,提交事务。物理拷贝方法mysqldump方法和导出CSV文件的方法,都是逻辑导数据的方法,也就是将数据从表db1.t中读出来,生成文本,然后再写入目标表db2.t中。有物理导数据的方法吗?比如,直接把db1.t表的.frm文件和.ibd文件拷贝到db2目录下,是否可行呢?答案是不行的。因为,一个InnoDB表,除了包含这两个物理文件外,还需要在数据字典中注册。直接拷贝这两个文件的话,因为数据字典中没有db2.t这个表,系统是不会识别和接受它们的。在MySQL 5.6版本引入了可传输表空间(transportable tablespace)的方法,可以通过导出+导入表空间的方式,实现物理拷贝表的功能。假设现在的目标是在db1的库下,复制一个跟表t相同的表r,具体执行步骤:执行create table r like t,创建一个相同表结构的空表,执行alter table r discard tablespace,这时候r.ibd文件会被删除执行flush table t for export这时候会生成一个t.cfg在db1目录下执行cp t.cfg r.cfg; cp t.ibd r.ibd;这两个命令;执行unlock tables,这时候t.cfg文件会被删除;执行alter table r import tablespace,将这个r.ibd文件作为表r的新的表空间,由于这个文件的数据内容和t.ibd是相同的,所以表r中就有了和表t相同的数据。这三种方法的优缺点物理拷贝的方式速度最快,尤其对于大表拷贝来说是最快的方法。但必须是全拷贝,不能是部分拷贝,需要到服务器上拷贝数据,在用户无法登录数据库主机时无法使用,而且源表和目标表都必须是innodb引擎。用mysqldump生成包含INSERT语句文件的方法,可以在where参数增加过滤条件,来实现只导出部分数据。这个方式的不足之一是,不能使用join这种比较复杂的where条件写法。用select … into outfile的方法是最灵活的,支持所有的SQL写法。但,这个方法的缺点之一就是,每次只能导出一张表的数据,而且表结构也需要另外的语句单独备份。后两种都是逻辑备份方式,可以跨引擎使用的。mysql全局权限SELECT * FROM MYSQL.USER WHERE USER='UA'\G 显示所有权限作用域整个mysql,信息保存在mysql的user表里赋予用户ua一个最高权限:grant all privileges on *.* to 'ua'@'%' with grant option;同样也是相对应的两个操作,磁盘中权限字段修改位N,内存中对象的access的值修改位0。mysqlDB权限grant all privileges on db1.* to 'ua'@'%' with grant option;使用SELECT * FROM MYSQL.DB WHERE USER = 'UA'\G来查看当前用户的db权限,同样的也是对磁盘和内存中的对象修改权限db权限存储在mysql.db表中注意:和全局权限不同,db权限会对已经存在的连接对象产生影响。mysql表权限和列权限表权限放在mysql.tables_priv中,列权限存放在mysql.columns_priv中,这两类权限组合起来存放在内存的hash结构column_priv_hash中。跟db权限类似,这两个权限每次grant的时候都会修改数据表,也会同步修改内存中的hash结构,因此,这两类权限的操作,也会影响到已经存在的连接。flush privileges的使用场景有些文档里提到,grant之后马上执行flush privileges命令,才能使赋权语句生效。其实更准确的说法应该是在数据表中的权限跟内存中的权限数据不一致的时候,flush privileges语句可以用来重建内存数据,达到一致状态。比如某时刻删除了数据表的记录,但是内存的数据还存在,导致了给用户赋权失败,因为在数据表中找不到记录。同时重新创建这个用户也不行,因为在内存判断的时候,会认为这个用户还存在。以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
-
我们前面所学习的 MySQL 语句都是针对一个表或几个表的单条 SQL 语句,但是在数据库的实际操作中,并非所有操作都那么简单,经常会有一个完整的操作需要多条 SQL 语句处理多个表才能完成。例如,为了确认学生能否毕业,需要同时查询学生档案表、成绩表和综合表,此时就需要使用多条 SQL 语句来针对几个数据表完成这个处理要求。存储过程可以有效地完成这个数据库操作。存储过程是数据库存储的一个重要的功能,但是 MySQL 在 5.0 以前并不支持存储过程,这使得 MySQL 在应用上大打折扣。好在 MySQL 5.0 终于开始已经支持存储过程,这样即可以大大提高数据库的处理速度,同时也可以提高数据库编程的灵活性。存储过程是一组为了完成特定功能的 SQL 语句集合。使用存储过程的目的是将常用或复杂的工作预先用 SQL 语句写好并用一个指定名称存储起来,这个过程经编译和优化后存储在数据库服务器中,因此称为存储过程。当以后需要数据库提供与已定义好的存储过程的功能相同的服务时,只需调用“CALL存储过程名字”即可自动完成。常用操作数据库的 SQL 语句在执行的时候需要先编译,然后执行。存储过程则采用另一种方式来执行 SQL 语句。语法CREATE PROCEDURE 过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型…]]) [特性 ...] 过程体DELIMITER // CREATE PROCEDURE myproc(OUT s int) BEGIN SELECT COUNT(*) INTO s FROM students; END // DELIMITER ;分隔符MySQL默认以";"为分隔符,如果没有声明分割符,则编译器会把存储过程当成SQL语句进行处理,因此编译过程会报错,所以要事先用“DELIMITER //”声明当前段分隔符,让编译器把两个"//"之间的内容当做存储过程的代码,不会执行这些代码;“DELIMITER ;”的意为把分隔符还原。参数:存储过程根据需要可能会有输入、输出、输入输出参数,如果有多个参数用","分割开。MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT:IN参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值OUT:该值可在存储过程内部被改变,并可返回INOUT:调用时指定,并且可被改变和返回过程体过程体的开始与结束使用BEGIN与END进行标识。注释MySQL存储过程可使用两种风格的注释:双杠:--,该风格一般用于单行注释C风格: 一般用于多行注释MySQL存储过程的调用用call和你过程名以及一个括号,括号里面根据需要,加入参数,参数包括输入参数、输出参数、输入输出参数。MySQL存储过程的查询#查询存储过程 SELECT name FROM mysql.proc WHERE db='数据库名'; SELECT routine_name FROM information_schema.routines WHERE routine_schema='数据库名'; SHOW PROCEDURE STATUS WHERE db='数据库名';#查看存储过程详细信息 SHOW CREATE PROCEDURE 数据库.存储过程名;MySQL存储过程的修改ALTER PROCEDURE 更改用CREATE PROCEDURE 建立的预先指定的存储过程,其不会影响相关存储过程或存储功能。ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...] characteristic: { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string'sp_name参数表示存储过程或函数的名称;characteristic参数指定存储函数的特性。CONTAINS SQL表示子程序包含SQL语句,但不包含读或写数据的语句;NO SQL表示子程序中不包含SQL语句;READS SQL DATA表示子程序中包含读数据的语句;MODIFIES SQL DATA表示子程序中包含写数据的语句。SQL SECURITY { DEFINER | INVOKER }指明谁有权限来执行,DEFINER表示只有定义者自己才能够执行;INVOKER表示调用者可以执行。COMMENT 'string'是注释信息。实例:#将读写权限改为MODIFIES SQL DATA,并指明调用者可以执行。 ALTER PROCEDURE num_from_employee MODIFIES SQL DATA SQL SECURITY INVOKER ; #将读写权限改为READS SQL DATA,并加上注释信息'FIND NAME'。 ALTER PROCEDURE name_from_employee READS SQL DATA COMMENT 'FIND NAME' ; MySQL存储过程的删除DROP PROCEDURE [过程1[,过程2…]]从MySQL的表格中删除一个或多个存储过程。优点一个存储过程是一个可编程的函数,它在数据库中创建并保存,一般由 SQL 语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的特定功能时,存储过程尤为合适。存储过程通常有如下优点:1) 封装性存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的 SQL 语句,并且数据库专业人员可以随时对存储过程进行修改,而不会影响到调用它的应用程序源代码。2) 可增强 SQL 语句的功能和灵活性存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。3) 可减少网络流量由于存储过程是在服务器端运行的,且执行速度快,因此当客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而可降低网络负载。4) 高性能存储过程执行一次后,产生的二进制代码就驻留在缓冲区,在以后的调用中,只需要从缓冲区中执行二进制代码即可,从而提高了系统的效率和性能。5) 提高数据库的安全性和数据的完整性使用存储过程可以完成所有数据库操作,并且可以通过编程的方式控制数据库信息访问的权限。
-
子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从 MySQL 4.1 开始引入,在 SELECT 子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。子查询中常用的操作符有 ANY(SOME)、ALL、IN 和 EXISTS。子查询可以添加到 SELECT、UPDATE 和 DELETE 语句中,而且可以进行多层嵌套。子查询也可以使用比较运算符,如“<”、“<=”、“>”、“>=”、“!=”等。子查询中常用的运算符1) IN子查询结合关键字 IN 所使用的子查询主要用于判断一个给定值是否存在于子查询的结果集中。其语法格式为:<表达式> [NOT] IN <子查询>语法说明如下。<表达式>:用于指定表达式。当表达式与子查询返回的结果集中的某个值相等时,返回 TRUE,否则返回 FALSE;若使用关键字 NOT,则返回的值正好相反。<子查询>:用于指定子查询。这里的子查询只能返回一列数据。对于比较复杂的查询要求,可以使用 SELECT 语句实现子查询的多层嵌套。2) 比较运算符子查询比较运算符所使用的子查询主要用于对表达式的值和子查询返回的值进行比较运算。其语法格式为:<表达式> {= | < | > | >= | <= | <=> | < > | != }{ ALL | SOME | ANY} <子查询>语法说明如下。<子查询>:用于指定子查询。<表达式>:用于指定要进行比较的表达式。ALL、SOME 和 ANY:可选项。用于指定对比较运算的限制。其中,关键字 ALL 用于指定表达式需要与子查询结果集中的每个值都进行比较,当表达式与每个值都满足比较关系时,会返回 TRUE,否则返回 FALSE;关键字 SOME 和 ANY 是同义词,表示表达式只要与子查询结果集中的某个值满足比较关系,就返回 TRUE,否则返回 FALSE。3) EXIST子查询关键字 EXIST 所使用的子查询主要用于判断子查询的结果集是否为空。其语法格式为:EXIST <子查询>若子查询的结果集不为空,则返回 TRUE;否则返回 FALSE。子查询的应用【实例 1】在 tb_departments 表中查询 dept_type 为 A 的学院 ID,并根据学院 ID 查询该学院学生的名字,输入的 SQL 语句和执行结果如下所示。mysql> SELECT name FROM tb_students_info -> WHERE dept_id IN -> (SELECT dept_id -> FROM tb_departments -> WHERE dept_type= 'A' ); +-------+ | name | +-------+ | Dany | | Henry | | Jane | | Jim | | John | +-------+ 5 rows in set (0.01 sec)上述查询过程可以分步执行,首先内层子查询查出 tb_departments 表中符合条件的学院 ID,单独执行内查询,查询结果如下所示。mysql> SELECT dept_id -> FROM tb_departments -> WHERE dept_type='A'; +---------+ | dept_id | +---------+ | 1 | | 2 | +---------+ 2 rows in set (0.00 sec)可以看到,符合条件的 dept_id 列的值有两个:1 和 2。然后执行外层查询,在 tb_students_info 表中查询 dept_id 等于 1 或 2 的学生的名字。嵌套子查询语句还可以写为如下形式,可以实现相同的效果。mysql> SELECT name FROM tb_students_info -> WHERE dept_id IN(1,2); +-------+ | name | +-------+ | Dany | | Henry | | Jane | | Jim | | John | +-------+ 5 rows in set (0.03 sec)上例说明在处理 SELECT 语句时,MySQL 实际上执行了两个操作过程,即先执行内层子查询,再执行外层查询,内层子查询的结果作为外部查询的比较条件。【实例 2】与前一个例子类似,但是在 SELECT 语句中使用 NOT IN 关键字,输入的 SQL 语句和执行结果如下所示。mysql> SELECT name FROM tb_students_info -> WHERE dept_id NOT IN -> (SELECT dept_id -> FROM tb_departments -> WHERE dept_type='A'); +--------+ | name | +--------+ | Green | | Lily | | Susan | | Thomas | | Tom | +--------+ 5 rows in set (0.04 sec)提示:子查询的功能也可以通过连接查询完成,但是子查询使得 MySQL 代码更容易阅读和编写。【实例 3】在 tb_departments 表中查询 dept_name 等于“Computer”的学院 id,然后在 tb_students_info 表中查询所有该学院的学生的姓名,输入的 SQL 语句和执行过程如下所示。 mysql> SELECT name FROM tb_students_info -> WHERE dept_id = -> (SELECT dept_id -> FROM tb_departments -> WHERE dept_name='Computer'); +------+ | name | +------+ | Dany | | Jane | | Jim | +------+ 3 rows in set (0.00 sec)【实例 4】在 tb_departments 表中查询 dept_name 不等于“Computer”的学院 id,然后在 tb_students_info 表中查询所有该学院的学生的姓名,输入的 SQL 语句和执行过程如下所示。mysql> SELECT name FROM tb_students_info -> WHERE dept_id <> -> (SELECT dept_id -> FROM tb_departments -> WHERE dept_name='Computer'); +--------+ | name | +--------+ | Green | | Henry | | John | | Lily | | Susan | | Thomas | | Tom | +--------+ 7 rows in set (0.00 sec)【实例 5】查询 tb_departments 表中是否存在 dept_id=1 的供应商,如果存在,就查询 tb_students_info 表中的记录,输入的 SQL 语句和执行结果如下所示。mysql> SELECT * FROM tb_students_info -> WHERE EXISTS -> (SELECT dept_name -> FROM tb_departments -> WHERE dept_id=1); +----+--------+---------+------+------+--------+------------+ | id | name | dept_id | age | sex | height | login_date | +----+--------+---------+------+------+--------+------------+ | 1 | Dany | 1 | 25 | F | 160 | 2015-09-10 | | 2 | Green | 3 | 23 | F | 158 | 2016-10-22 | | 3 | Henry | 2 | 23 | M | 185 | 2015-05-31 | | 4 | Jane | 1 | 22 | F | 162 | 2016-12-20 | | 5 | Jim | 1 | 24 | M | 175 | 2016-01-15 | | 6 | John | 2 | 21 | M | 172 | 2015-11-11 | | 7 | Lily | 6 | 22 | F | 165 | 2016-02-26 | | 8 | Susan | 4 | 23 | F | 170 | 2015-10-01 | | 9 | Thomas | 3 | 22 | M | 178 | 2016-06-07 | | 10 | Tom | 4 | 23 | M | 165 | 2016-08-05 | +----+--------+---------+------+------+--------+------------+ 10 rows in set (0.00 sec)由结果可以看到,内层查询结果表明 tb_departments 表中存在 dept_id=1 的记录,因此 EXSTS 表达式返回 TRUE,外层查询语句接收 TRUE 之后对表 tb_students_info 进行查询,返回所有的记录。EXISTS 关键字可以和条件表达式一起使用。【实例 6】查询 tb_departments 表中是否存在 dept_id=7 的供应商,如果存在,就查询 tb_students_info 表中的记录,输入的 SQL 语句和执行结果如下所示。mysql> SELECT * FROM tb_students_info -> WHERE EXISTS -> (SELECT dept_name -> FROM tb_departments -> WHERE dept_id=7); Empty set (0.00 sec)
-
视图是数据库系统中一种非常有用的数据库对象。MySQL 5.0 之后的版本添加了对视图的支持。认识视图视图是一个虚拟表,其内容由查询定义。同真实表一样,视图包含一系列带有名称的列和行数据,但视图并不是数据库真实存储的数据表。视图是从一个、多个表或者视图中导出的表,包含一系列带有名称的数据列和若干条数据行。视图并不同于数据表,它们的区别在于以下几点:视图不是数据库中真实的表,而是一张虚拟表,其结构和数据是建立在对数据中真实表的查询基础上的。存储在数据库中的查询操作 SQL 语句定义了视图的内容,列数据和行数据来自于视图查询所引用的实际表,引用视图时动态生成这些数据。视图没有实际的物理记录,不是以数据集的形式存储在数据库中的,它所对应的数据实际上是存储在视图所引用的真实表中的。视图是数据的窗口,而表是内容。表是实际数据的存放单位,而视图只是以不同的显示方式展示数据,其数据来源还是实际表。视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些 SQL 语句的集合。从安全的角度来看,视图的数据安全性更高,使用视图的用户不接触数据表,不知道表结构。视图的建立和删除只影响视图本身,不影响对应的基本表。视图与表在本质上虽然不相同,但视图经过定义以后,结构形式和表一样,可以进行查询、修改、更新和删除等操作。同时,视图具有如下优点:1) 定制用户数据,聚焦特定的数据在实际的应用过程中,不同的用户可能对不同的数据有不同的要求。例如,当数据库同时存在时,如学生基本信息表、课程表和教师信息表等多种表同时存在时,可以根据需求让不同的用户使用各自的数据。学生查看修改自己基本信息的视图,安排课程人员查看修改课程表和教师信息的视图,教师查看学生信息和课程信息表的视图。2) 简化数据操作在使用查询时,很多时候要使用聚合函数,同时还要显示其他字段的信息,可能还需要关联到其他表,语句可能会很长,如果这个动作频繁发生的话,可以创建视图来简化操作。3) 提高基表数据的安全性视图是虚拟的,物理上是不存在的。可以只授予用户视图的权限,而不具体指定使用表的权限,来保护基础数据的安全。4) 共享所需数据通过使用视图,每个用户不必都定义和存储自己所需的数据,可以共享数据库中的数据,同样的数据只需要存储一次。5) 更改数据格式通过使用视图,可以重新格式化检索出的数据,并组织输出到其他应用程序中。6) 重用 SQL 语句视图提供的是对查询操作的封装,本身不包含数据,所呈现的数据是根据视图定义从基础表中检索出来的,如果基础表的数据新增或删除,视图呈现的也是更新后的数据。视图定义后,编写完所需的查询,可以方便地重用该视图。注意:要区别视图和数据表的本质,即视图是基于真实表的一张虚拟的表,其数据来源均建立在真实表的基础上。使用视图的时候,还应该注意以下几点:创建视图需要足够的访问权限。创建视图的数目没有限制。视图可以嵌套,即从其他视图中检索数据的查询来创建视图。视图不能索引,也不能有关联的触发器、默认值或规则。视图可以和表一起使用。视图不包含数据,所以每次使用视图时,都必须执行查询中所需的任何一个检索操作。如果用多个连接和过滤条件创建了复杂的视图或嵌套了视图,可能会发现系统运行性能下降得十分严重。因此,在部署大量视图应用时,应该进行系统测试。ORDER BY 子句可以用在视图中,但若该视图检索数据的 SELECT 语句中也含有 ORDER BY 子句,则该视图中的 ORDER BY 子句将被覆盖。
-
我们前面所学习的 MySQL 语句都是针对一个表或几个表的单条 SQL 语句,但是在数据库的实际操作中,并非所有操作都那么简单,经常会有一个完整的操作需要多条 SQL 语句处理多个表才能完成。例如,为了确认学生能否毕业,需要同时查询学生档案表、成绩表和综合表,此时就需要使用多条 SQL 语句来针对几个数据表完成这个处理要求。存储过程可以有效地完成这个数据库操作。存储过程是数据库存储的一个重要的功能,但是 MySQL 在 5.0 以前并不支持存储过程,这使得 MySQL 在应用上大打折扣。好在 MySQL 5.0 终于开始已经支持存储过程,这样即可以大大提高数据库的处理速度,同时也可以提高数据库编程的灵活性。存储过程是一组为了完成特定功能的 SQL 语句集合。使用存储过程的目的是将常用或复杂的工作预先用 SQL 语句写好并用一个指定名称存储起来,这个过程经编译和优化后存储在数据库服务器中,因此称为存储过程。当以后需要数据库提供与已定义好的存储过程的功能相同的服务时,只需调用“CALL存储过程名字”即可自动完成。常用操作数据库的 SQL 语句在执行的时候需要先编译,然后执行。存储过程则采用另一种方式来执行 SQL 语句。一个存储过程是一个可编程的函数,它在数据库中创建并保存,一般由 SQL 语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的特定功能时,存储过程尤为合适。存储过程通常有如下优点:1) 封装性存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的 SQL 语句,并且数据库专业人员可以随时对存储过程进行修改,而不会影响到调用它的应用程序源代码。2) 可增强 SQL 语句的功能和灵活性存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。3) 可减少网络流量由于存储过程是在服务器端运行的,且执行速度快,因此当客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而可降低网络负载。4) 高性能存储过程执行一次后,产生的二进制代码就驻留在缓冲区,在以后的调用中,只需要从缓冲区中执行二进制代码即可,从而提高了系统的效率和性能。5) 提高数据库的安全性和数据的完整性使用存储过程可以完成所有数据库操作,并且可以通过编程的方式控制数据库信息访问的权限。
-
MySQL 数据库中触发器是一个特殊的存储过程,不同的是执行存储过程要使用 CALL 语句来调用,而触发器的执行不需要使用 CALL 语句来调用,也不需要手工启动,只要一个预定义的事件发生就会被 MySQL自动调用。引发触发器执行的事件一般如下:增加一条学生记录时,会自动检查年龄是否符合范围要求。每当删除一条学生信息时,自动删除其成绩表上的对应记录。每当删除一条数据时,在数据库存档表中保留一个备份副本。触发程序的优点如下:触发程序的执行是自动的,当对触发程序相关表的数据做出相应的修改后立即执行。触发程序可以通过数据库中相关的表层叠修改另外的表。触发程序可以实施比 FOREIGN KEY 约束、CHECK 约束更为复杂的检查和操作。触发器与表关系密切,主要用于保护表中的数据。特别是当有多个表具有一定的相互联系的时候,触发器能够让不同的表保持数据的一致性。在 MySQL 中,只有执行 INSERT、UPDATE 和 DELETE 操作时才能激活触发器。在实际使用中,MySQL 所支持的触发器有三种:INSERT 触发器、UPDATE 触发器和 DELETE 触发器。1) INSERT 触发器在 INSERT 语句执行之前或之后响应的触发器。使用 INSERT 触发器需要注意以下几点:在 INSERT 触发器代码内,可引用一个名为 NEW(不区分大小写)的虚拟表来访问**入的行。在 BEFORE INSERT 触发器中,NEW 中的值也可以被更新,即允许更改**入的值(只要具有对应的操作权限)。对于 AUTO_INCREMENT 列,NEW 在 INSERT 执行之前包含的值是 0,在 INSERT 执行之后将包含新的自动生成值。2) UPDATE 触发器在 UPDATE 语句执行之前或之后响应的触发器。使用 UPDATE 触发器需要注意以下几点:在 UPDATE 触发器代码内,可引用一个名为 NEW(不区分大小写)的虚拟表来访问更新的值。在 UPDATE 触发器代码内,可引用一个名为 OLD(不区分大小写)的虚拟表来访问 UPDATE 语句执行前的值。在 BEFORE UPDATE 触发器中,NEW 中的值可能也被更新,即允许更改将要用于 UPDATE 语句中的值(只要具有对应的操作权限)。OLD 中的值全部是只读的,不能被更新。注意:当触发器设计对触发表自身的更新操作时,只能使用 BEFORE 类型的触发器,AFTER 类型的触发器将不被允许。3) DELETE 触发器在 DELETE 语句执行之前或之后响应的触发器。使用 DELETE 触发器需要注意以下几点:在 DELETE 触发器代码内,可以引用一个名为 OLD(不区分大小写)的虚拟表来访问被删除的行。OLD 中的值全部是只读的,不能被更新。总体来说,触发器使用的过程中,MySQL 会按照以下方式来处理错误。若对于事务性表,如果触发程序失败,以及由此导致的整个语句失败,那么该语句所执行的所有更改将回滚;对于非事务性表,则不能执行此类回滚,即使语句失败,失败之前所做的任何更改依然有效。若 BEFORE 触发程序失败,则 MySQL 将不执行相应行上的操作。若在 BEFORE 或 AFTER 触发程序的执行过程中出现错误,则将导致调用触发程序的整个语句失败。仅当 BEFORE 触发程序和行操作均已被成功执行,MySQL 才会执行AFTER触发程序。
-
转载:https://blog.csdn.net/m0_47452405/article/details/109053808?utm_medium=distribute.pc_category.none-task-blog-hot-1.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-1.nonecase&request_id=一、完全备份、差异备份与增量备份概述三者的特点完全备份:每次对数据库进行完整的备份(包括表的结构和数据)特点:备份与恢复操作简单,但占用大量备份空间,数据重复率高,冗余数据多,备份与恢复时间长差异备份:以完全备份为基准,备份自从上次完全备份之后被修改过的文件特点:占用空间小,但是安全性变差增量备份:只有在上次完全备份或者增量备份后被修改的文件才会被备份特点:无冗余数据,依靠二进制日志文件进行逐次增量备份,单个文件丢失则数据不完整,安全性低三者的区别举例备份类型第一次备份:原有数据a第二次备份:a,b第三次备份:a,b,c完全备份aa,ba,b,c差异备份abb,c增量备份abc二、完全备份实例2.1 冷备份与恢复数据库所有的数据在这个目录里,直接整个目录打包(需要关闭数据库,基本不用)[root@host3 data]# service mysqld stop //先关闭数据库Redirecting to /bin/systemctl stop mysqld.service[root@host3 data]# mkdir /opt/backup //创建备份目录,[root@host3 data]# tar zcvf /opt/backup/mysql_all_$(date +%F).tar.gz /usr/local/mysql/data///把整个数据目录打包[root@host3 data]# cd /opt/backup[root@host3 backup]# lltotal 1384 -rw-r--r-- 1 root root 1413851 Oct 13 20:03 mysql_all_2020-10-13.tar.gz12345678910当数据库故障时,直接把压缩包解压,数据挪回data目录下2.2 mysqldump备份与恢复2.2.1单库备份与恢复mysqldump -u 用户 -p[密码,不写则进行交互] 库名 > 保存的位置(文件以sql格式结尾)[root@host3 mysql]# mysqldump -uroot -p school > /opt/school.sqlEnter password: [root@host3 mysql]# cd /opt[root@host3 opt]# lltotal 47700 drwxr-xr-x 38 7161 31415 4096 Oct 14 10:22 mysql-5.7.20 -rw-r--r-- 1 root root 48833145 Oct 23 2017 mysql-boost-5.7.20.tar.gz drwxr-xr-x. 2 root root 6 Oct 31 2018 rh -rw-r--r-- 1 root root 2144 Oct 14 14:05 school.sql1234567891011查看sql文件可知,没有备份创建数据库的语句,所以恢复的时候需要先创建数据库,再恢复制造故障:mysql> drop database school;Query OK, 1 row affected (0.01 sec)直接恢复 mysql> source /opt/school.sql ERROR 1046 (3D000): No database selected 报错,没有数据库可选 Query OK, 0 rows affected (0.00 sec)123456单库正确恢复方式mysql> create database school; 数据库名可根据需求取 Query OK, 1 row affected (0.00 sec)mysql> use school;Database changed 方法一:在数据库内用source语句恢复 mysql> source /opt/school.sql Query OK, 9 rows affected (0.00 sec)Records: 9 Duplicates: 0 Warnings: 0 查看,已恢复 mysql> show tables;+------------------+| Tables_in_school |+------------------+| info |+------------------+ 1 row in set (0.00 sec)mysql> select * from info;+----+----------+-------+-------+------+| id | name | hobby | score | addr |+----+----------+-------+-------+------+| 1 | zhangsan | 1 | 88 | NULL || 2 | lisi | 2 | 66 | NULL || 3 | wangwu | 2 | 77 | NULL || 4 | zhaoliu | 1 | 80 | NULL || 5 | tianqi | 3 | 50 | NULL || 6 | liyu | 1 | 90 | NULL || 7 | wooo | 1 | 99 | NULL || 8 | wooooo | 1 | 99 | NULL || 9 | owoo | 1 | 99 | NULL |+----+----------+-------+-------+------+ 9 rows in set (0.00 sec)方法二:用linux命令mysql进行恢复 mysql> drop table info; //把表删了 Query OK, 0 rows affected (0.02 sec)mysql> show tables;Empty set (0.00 sec)mysql> exit;Bye[root@host3 opt]# mysql -uroot -p school < /opt/school.sql //反向导入恢复Enter password: [root@host3 opt]# mysql -uroot -p -e 'show tables from school' //查看Enter password: +------------------+| Tables_in_school |+------------------+| info |+------------------+1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556572.2.2多库备份mysqldump [选项] --databases 库名1 [库名2] … > /备份路径/备份文件名[root@host3 opt]# mysqldump -uroot -p --databases mysql school > /opt/mysql-school.sqlEnter password: [root@host3 opt]# cd /opt[root@host3 opt]# lltotal 49684 drwxr-xr-x 38 7161 31415 4096 Oct 14 10:22 mysql-5.7.20 -rw-r--r-- 1 root root 48833145 Oct 23 2017 mysql-boost-5.7.20.tar.gz -rw-r--r-- 1 root root 1098302 Oct 14 14:26 mysql-school.sql drwxr-xr-x. 2 root root 6 Oct 31 2018 rh -rw-r--r-- 1 root root 2144 Oct 14 14:05 school.sql1234567891011进去文件内查看,可以看到,在多库备份的时候,备份了创建数据库的语句,所以恢复的时候可以直接恢复2.2.3所有库备份mysqldump [选项] --all-databases > /备份路径/备份文件名[root@host3 opt]# mysqldump -uroot -p --all-databases > /opt/all-data.sqlEnter password: [root@host3 opt]# lsall-data.sql mysql-boost-5.7.20.tar.gz rh mysql-5.7.20 mysql-school.sql school.sql123452.2.4对数据库表数据备份mysqldump [选项] 库名 [表名1] [表名2] … > /备份路径/备份文件名[root@host3 opt]# mysqldump -uroot -p school info > /opt/school-info.sqlEnter password: 12三、增量备份实例3.1增量备份增量备份基于二进制日志文件备份,二进制日志在启动mysql服务器后开始记录,并在文件达到二进制日志所设置的最大值或者接受到flush logs命令后重新创建新的日志文件,生成二进制的文件序列,并及时把这些日志文件保存到安全的存储位置,即可完成一个时间段的增量备份。先进入my.cnf文件重启数据库刷新接下来关于所有的数据库操作,都被记录在000001文件里。进行一系列正确错误操作,目的是加入第十条ysql> select * from info;+----+----------+-------+-------+------+| id | name | hobby | score | addr |+----+----------+-------+-------+------+| 1 | zhangsan | 1 | 88 | NULL || 2 | lisi | 2 | 66 | NULL || 3 | wangwu | 2 | 77 | NULL || 4 | zhaoliu | 1 | 80 | NULL || 5 | tianqi | 3 | 50 | NULL || 6 | liyu | 1 | 90 | NULL || 7 | wooo | 1 | 99 | NULL || 8 | wooooo | 1 | 99 | NULL || 9 | owoo | 1 | 99 | NULL |+----+----------+-------+-------+------+ 9 rows in set (0.00 sec)mysql> delete from info where name='lisi';Query OK, 1 row affected (0.00 sec)mysql> insert into info (name,hobby,score) values ('zhaosi',2,66);Query OK, 1 row affected (0.00 sec)mysql> delete from info where hobby=1;Query OK, 6 rows affected (0.00 sec)mysql> select * from info;+----+--------+-------+-------+------+| id | name | hobby | score | addr |+----+--------+-------+-------+------+| 3 | wangwu | 2 | 77 | NULL || 5 | tianqi | 3 | 50 | NULL || 10 | zhaosi | 2 | 66 | NULL |+----+--------+-------+-------+------+ 3 rows in set (0.00 sec)误删了很多数据1234567891011121314151617181920212223242526272829303132333435想要通过增量备份恢复正确的数据先刷新二进制日志文件mysqladmin -uroot -p flush-logs Enter password: 12mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000001 使用mysqlbinlog工具查看日志文件12每一次命令,都是一次事务的提交3.2基于一般恢复mysqlbinlog [–no-defaults] 增量备份文件 | mysql -u 用户名 -p一般恢复是直接把整个二进制文件的内容进行恢复。mysql> select * from info; 当前内容 +----+--------+-------+-------+------+| id | name | hobby | score | addr |+----+--------+-------+-------+------+| 3 | wangwu | 2 | 77 | NULL || 5 | tianqi | 3 | 50 | NULL || 10 | zhaosi | 2 | 66 | NULL |+----+--------+-------+-------+------+ mysql> drop table info;Query OK, 0 rows affected (0.02 sec)先把表删了,模拟故障123456789101112先进行完全备份的恢复 mysql> source /opt/school-info.sql mysql> select * from info;+----+----------+-------+-------+------+| id | name | hobby | score | addr |+----+----------+-------+-------+------+| 1 | zhangsan | 1 | 88 | NULL || 2 | lisi | 2 | 66 | NULL || 3 | wangwu | 2 | 77 | NULL || 4 | zhaoliu | 1 | 80 | NULL || 5 | tianqi | 3 | 50 | NULL || 6 | liyu | 1 | 90 | NULL || 7 | wooo | 1 | 99 | NULL || 8 | wooooo | 1 | 99 | NULL || 9 | owoo | 1 | 99 | NULL |+----+----------+-------+-------+------+ 再进行一般恢复[root@host3 data]# mysqlbinlog --no-defaults mysql-bin.000001 |mysql -uroot -pEnter password: 查看,所有操作都恢复了[root@host3 data]# mysql -uroot -p -e 'select * from school.info'Enter password: +----+--------+-------+-------+------+| id | name | hobby | score | addr |+----+--------+-------+-------+------+| 3 | wangwu | 2 | 77 | NULL || 5 | tianqi | 3 | 50 | NULL || 10 | zhaosi | 2 | 66 | NULL |+----+--------+-------+-------+------+12345678910111213141516171819202122232425262728293.3基于位置恢复通过查看文件,可以得出操作第一次操作第二次操作第三次操作操作id开始219 结束434开始499 结束716开始781 结束1095时间点开始2020-10-14 16:30:19结束2020-10-14 16:31:50开始2020-10-14 16:31:50结束2020-10-14 16:33:38开始2020-10-14 16:33:38结束2020-10-14 16:52:38只有第二次是正确操作,第一次和第三次都误删数据1、恢复数据到指定位置mysqlbinlog --stop-position=’操作 id’ 二进制日志 |mysql -u 用户名 -p 密码和一般恢复一样,先进行完全备份,变成这样 mysql> select * from info;+----+----------+-------+-------+------+| id | name | hobby | score | addr |+----+----------+-------+-------+------+| 1 | zhangsan | 1 | 88 | NULL || 2 | lisi | 2 | 66 | NULL || 3 | wangwu | 2 | 77 | NULL || 4 | zhaoliu | 1 | 80 | NULL || 5 | tianqi | 3 | 50 | NULL || 6 | liyu | 1 | 90 | NULL || 7 | wooo | 1 | 99 | NULL || 8 | wooooo | 1 | 99 | NULL || 9 | owoo | 1 | 99 | NULL |+----+----------+-------+-------+------+ 只进行第一次的操作恢复 mysqlbinlog --no-defaults --stop-position='434' mysql-bin.000001 |mysql -uroot -p Enter password: 1234567891011121314151617182、从指定的位置开始恢复数据mysqlbinlog --start-position=’操作 id’ 二进制日志 |mysql -u 用户名 -p 密码从第二次操作开始[root@host3 data]# mysqlbinlog --no-defaults --start-position='499' mysql-bin.000001 |mysql -uroot -pEnter password: 123.4基于时间点恢复删除表,恢复完全备份后mysql> select * from info;+----+----------+-------+-------+------+| id | name | hobby | score | addr |+----+----------+-------+-------+------+| 1 | zhangsan | 1 | 88 | NULL || 2 | lisi | 2 | 66 | NULL || 3 | wangwu | 2 | 77 | NULL || 4 | zhaoliu | 1 | 80 | NULL || 5 | tianqi | 3 | 50 | NULL || 6 | liyu | 1 | 90 | NULL || 7 | wooo | 1 | 99 | NULL || 8 | wooooo | 1 | 99 | NULL || 9 | owoo | 1 | 99 | NULL |+----+----------+-------+-------+------+12345678910111213141、从日志开头截止到某个时间点的恢复mysqlbinlog [–no-defaults] --stop-datetime=’年-月-日 小时:分钟:秒’ 二进制日志 | mysql -u 用户名 -p 密码只进行第一次操作[root@host3 data]# mysqlbinlog --no-defaults --stop-datetime='2020-10-14 16:31:50' mysql-bin.000001 |mysql -uroot -pEnter password: 1232、从某个时间点到日志结尾的恢复mysqlbinlog [–no-defaults] --start-datetime=’年-月-日 小时:分钟:秒’ 二进制日志 | mysql -u 用户名 -p 密码进行后面的操作Enter password:[root@host3 data]# mysqlbinlog --no-defaults --start-datetime='2020-10-14 16:31:50' mysql-bin.000001 |mysql -uroot -p13、从某个时间点到某个时间点的恢复mysqlbinlog [–no-defaults] --start-datetime=’年-月-日 小时:分钟:秒’ --stop-datetime=’年-月-日小时:分钟:秒’ 二进制日志 | mysql -u 用户名 -p 密码恢复所有正确操作,不回复误删的操作完全备份恢复之后直接进行第二步操作[root@host3 data]# mysqlbinlog --no-defaults --start-datetime='2020-10-14 16:31:50' --stop-datetime='2020-10-14 16:33:38' mysql-bin.000001 |mysql -uroot -pEnter password: 12恢复正确数据
W--wangzhiqiang
发表于2020-10-15 11:53:20
2020-10-15 11:53:20
最后回复
W--wangzhiqiang
2020-10-15 11:53:20
1105 0 -
2020-10-15:mysql的双1设置是什么?#福大大架构师每日一题#
-
在使用 MySQL 的过程中,MySQL 自带的函数可能完成不了我们的业务需求,这时候就需要自定义函数。自定义函数是一种与存储过程十分相似的过程式数据库对象。它与存储过程一样,都是由 SQL 语句和过程式语句组成的代码片段,并且可以被应用程序和其他 SQL 语句调用。自定义函数与存储过程之间存在几点区别:自定义函数不能拥有输出参数,这是因为自定义函数自身就是输出参数;而存储过程可以拥有输出参数。自定义函数中必须包含一条 RETURN 语句,而这条特殊的 SQL 语句不允许包含于存储过程中。可以直接对自定义函数进行调用而不需要使用 CALL 语句,而对存储过程的调用需要使用 CALL 语句。创建并使用自定义函数可以使用 CREATE FUNCTION 语句创建自定义函数。语法格式如下:CREATE FUNCTION <函数名> ( [ <参数1> <类型1> [ , <参数2> <类型2>] ] … ) RETURNS <类型> <函数主体>语法说明如下:<函数名>:指定自定义函数的名称。注意,自定义函数不能与存储过程具有相同的名称。<参数><类型>:用于指定自定义函数的参数。这里的参数只有名称和类型,不能指定关键字 IN、OUT 和 INOUT。RETURNS<类型>:用于声明自定义函数返回值的数据类型。其中,<类型>用于指定返回值的数据类型。<函数主体>:自定义函数的主体部分,也称函数体。所有在存储过程中使用的 SQL 语句在自定义函数中同样适用,包括前面所介绍的局部变量、SET 语句、流程控制语句、游标等。除此之外,自定义函数体还必须包含一个 RETURN<值> 语句,其中<值>用于指定自定义函数的返回值。在 RETURN VALUE 语句中包含 SELECT 语句时,SELECT 语句的返回结果只能是一行且只能有一列值。若要查看数据库中存在哪些自定义函数,可以使用 SHOW FUNCTION STATUS 语句;若要查看数据库中某个具体的自定义函数,可以使用 SHOW CREATE FUNCTION<函数名> 语句,其中<函数名>用于指定该自定义函数的名称。【实例 1】创建存储函数,名称为 StuNameById,该函数返回 SELECT 语句的查询结果,数值类型为字符串类型,输入的 SQL 语句和执行结果如下所示。mysql> CREATE FUNCTION StuNameById() -> RETURNS VARCHAR(45) -> RETURN -> (SELECT name FROM tb_students_info -> WHERE id=1); Query OK, 0 rows affected (0.09 sec)注意:当使用 DELIMITER 命令时,应该避免使用反斜杠“\”字符,因为反斜杠是 MySQL 的转义字符。成功创建自定义函数后,就可以如同调用系统内置函数一样,使用关键字 SELECT 调用用户自定义的函数,语法格式为:SELECT <自定义函数名> ([<参数> [,...]])【实例 2】调用自定义函数 StuNameById,查看函数的运行结果,如下所示。mysql> SELECT StuNameById(); +---------------+ | StuNameById() | +---------------+ | Dany | +---------------+ 1 row in set (0.24 sec)修改自定义函数可以使用 ALTER FUNCTION 语句来修改自定义函数的某些相关特征。若要修改自定义函数的内容,则需要先删除该自定义函数,然后重新创建。删除自定义函数自定义函数被创建后,一直保存在数据库服务器上以供使用,直至被删除。删除自定义函数的方法与删除存储过程的方法基本一样,可以使用 DROP FUNCTION 语句来实现。语法格式如下:DROP FUNCTION [ IF EXISTS ] <自定义函数名>语法说明如下。<自定义函数名>:指定要删除的自定义函数的名称。IF EXISTS:指定关键字,用于防止因误删除不存在的自定义函数而引发错误。【实例 3】删除自定义函数 StuNameById,查看函数的运行结果,如下所示。mysql> DROP FUNCTION StuNameById; Query OK, 0 rows affected (0.09 sec) mysql> SELECT StuNameById(); ERROR 1305 (42000): FUNCTION test_db.StuNameById does not exist
-
在使用 MySQL SELECT 语句查询数据的时候返回的是所有匹配的行。基本语法:distinct一般是用来去除查询结果中的重复记录的,而且这个语句在select、insert、delete和update中只可以在select中使用,具体的语法如下:select distinct expression[,expression...] from tables [where conditions];例如,查询 tb_students_info 表中所有 age 的执行结果如下所示。mysql> SELECT age FROM tb_students_info; +------+ | age | +------+ | 25 | | 23 | | 23 | | 22 | | 24 | | 21 | | 22 | | 23 | | 22 | | 23 | +------+ 10 rows in set (0.00 sec)可以看到查询结果返回了 10 条记录,其中有一些重复的 age 值,有时出于对数据分析的要求,需要消除重复的记录值。这时候就需要用到 DISTINCT 关键字指示 MySQL 消除重复的记录值,语法格式为:SELECT DISTINCT <字段名> FROM <表名>;例 1查询 tb_students_info 表中 age 字段的值,返回 age 字段的值且不得重复,输入的 SQL 语句和执行结果如下所示。mysql> SELECT DISTINCT age FROM tb_students_info; +------+ | age | +------+ | 25 | | 23 | | 22 | | 24 | | 21 | +------+ 5 rows in set (0.11 sec)由运行结果可以看到,这次查询结果只返回了 5 条记录的 age 值,且没有重复的值。针对NULL的处理从1.1和1.2中都可以看出,distinct对NULL是不进行过滤的,即返回的结果中是包含NULL值的。与ALL不能同时使用默认情况下,查询时返回所有的结果,此时使用的就是all语句,这是与distinct相对应的,如下:select all country, province from person结果如下: 与distinctrow同义select distinctrow expression[,expression...] from tables [where conditions];这个语句与distinct的作用是相同的。对*的处理*代表整列,使用distinct对*操作sql select DISTINCT * from person 相当于select DISTINCT id, `name`, country, province, city from person;
-
MySQL 数据库中可以使用 REVOKE 语句删除一个用户的权限,此用户不会被删除。语法格式有两种形式,如下所示:1) 第一种:REVOKE <权限类型> [ ( <列名> ) ] [ , <权限类型> [ ( <列名> ) ] ]…ON <对象类型> <权限名> FROM <用户1> [ , <用户2> ]…2) 第二种:REVOKE ALL PRIVILEGES, GRANT OPTIONFROM user <用户1> [ , <用户2> ]…语法说明如下:REVOKE 语法和 GRANT 语句的语法格式相似,但具有相反的效果。第一种语法格式用于回收某些特定的权限。第二种语法格式用于回收特定用户的所有权限。要使用 REVOKE 语句,必须拥有 MySQL 数据库的全局 CREATE USER 权限或 UPDATE 权限。【实例】使用 REVOKE 语句取消用户 testUser 的插入权限,输入的 SQL 语句和执行过程如下所示。mysql> REVOKE INSERT ON *.* -> FROM 'testUser'@'localhost'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT Host,User,Select_priv,Insert_priv,Grant_priv -> FROM mysql.user -> WHERE User='testUser'; +-----------+----------+-------------+-------------+------------+ | Host | User | Select_priv | Insert_priv | Grant_priv | +-----------+----------+-------------+-------------+------------+ | localhost | testUser | Y | N | Y | +-----------+----------+-------------+-------------+------------+ 1 row in set (0.00 sec)
-
当成功创建用户账户后,还不能执行任何操作,需要为该用户分配适当的访问权限。可以使用 SHOW GRANT FOR 语句来查询用户的权限。注意:新创建的用户只有登录 MySQL 服务器的权限,没有任何其他权限,不能进行其他操作。USAGE ON*.* 表示该用户对任何数据库和任何表都没有权限。授予用户权限对于新建的 MySQL 用户,必须给它授权,可以用 GRANT 语句来实现对新建用户的授权。语法格式:GRANT <权限类型> [ ( <列名> ) ] [ , <权限类型> [ ( <列名> ) ] ] ON <对象> <权限级别> TO <用户> 其中<用户>的格式: <用户名> [ IDENTIFIED ] BY [ PASSWORD ] <口令> [ WITH GRANT OPTION] | MAX_QUERIES_PER_HOUR <次数> | MAX_UPDATES_PER_HOUR <次数> | MAX_CONNECTIONS_PER_HOUR <次数> | MAX_USER_CONNECTIONS <次数>语法说明如下:1) <列名>可选项。用于指定权限要授予给表中哪些具体的列。2) ON 子句用于指定权限授予的对象和级别,如在 ON 关键字后面给出要授予权限的数据库名或表名等。3) <权限级别>用于指定权限的级别。可以授予的权限有如下几组:列权限,和表中的一个具体列相关。例如,可以使用 UPDATE 语句更新表 students 中 student_name 列的值的权限。表权限,和一个具体表中的所有数据相关。例如,可以使用 SELECT 语句查询表 students 的所有数据的权限。数据库权限,和一个具体的数据库中的所有表相关。例如,可以在已有的数据库 mytest 中创建新表的权限。用户权限,和 MySQL 中所有的数据库相关。例如,可以删除已有的数据库或者创建一个新的数据库的权限。对应地,在 GRANT 语句中可用于指定权限级别的值有以下几类格式:*:表示当前数据库中的所有表。*.*:表示所有数据库中的所有表。db_name.*:表示某个数据库中的所有表,db_name 指定数据库名。db_name.tbl_name:表示某个数据库中的某个表或视图,db_name 指定数据库名,tbl_name 指定表名或视图名。tbl_name:表示某个表或视图,tbl_name 指定表名或视图名。db_name.routine_name:表示某个数据库中的某个存储过程或函数,routine_name 指定存储过程名或函数名。TO 子句:用来设定用户口令,以及指定被赋予权限的用户 user。若在 TO 子句中给系统中存在的用户指定口令,则新密码会将原密码覆盖;如果权限被授予给一个不存在的用户,MySQL 会自动执行一条 CREATE USER 语句来创建这个用户,但同时必须为该用户指定口令。GRANT语句中的<权限类型>的使用说明如下:1) 授予数据库权限时,<权限类型>可以指定为以下值:SELECT:表示授予用户可以使用 SELECT 语句访问特定数据库中所有表和视图的权限。INSERT:表示授予用户可以使用 INSERT 语句向特定数据库中所有表添加数据行的权限。DELETE:表示授予用户可以使用 DELETE 语句删除特定数据库中所有表的数据行的权限。UPDATE:表示授予用户可以使用 UPDATE 语句更新特定数据库中所有数据表的值的权限。REFERENCES:表示授予用户可以创建指向特定的数据库中的表外键的权限。CREATE:表示授权用户可以使用 CREATE TABLE 语句在特定数据库中创建新表的权限。ALTER:表示授予用户可以使用 ALTER TABLE 语句修改特定数据库中所有数据表的权限。SHOW VIEW:表示授予用户可以查看特定数据库中已有视图的视图定义的权限。CREATE ROUTINE:表示授予用户可以为特定的数据库创建存储过程和存储函数的权限。ALTER ROUTINE:表示授予用户可以更新和删除数据库中已有的存储过程和存储函数的权限。INDEX:表示授予用户可以在特定数据库中的所有数据表上定义和删除索引的权限。DROP:表示授予用户可以删除特定数据库中所有表和视图的权限。CREATE TEMPORARY TABLES:表示授予用户可以在特定数据库中创建临时表的权限。CREATE VIEW:表示授予用户可以在特定数据库中创建新的视图的权限。EXECUTE ROUTINE:表示授予用户可以调用特定数据库的存储过程和存储函数的权限。LOCK TABLES:表示授予用户可以锁定特定数据库的已有数据表的权限。ALL 或 ALL PRIVILEGES:表示以上所有权限。2) 授予表权限时,<权限类型>可以指定为以下值:SELECT:授予用户可以使用 SELECT 语句进行访问特定表的权限。INSERT:授予用户可以使用 INSERT 语句向一个特定表中添加数据行的权限。DELETE:授予用户可以使用 DELETE 语句从一个特定表中删除数据行的权限。DROP:授予用户可以删除数据表的权限。UPDATE:授予用户可以使用 UPDATE 语句更新特定数据表的权限。ALTER:授予用户可以使用 ALTER TABLE 语句修改数据表的权限。REFERENCES:授予用户可以创建一个外键来参照特定数据表的权限。CREATE:授予用户可以使用特定的名字创建一个数据表的权限。INDEX:授予用户可以在表上定义索引的权限。ALL 或 ALL PRIVILEGES:所有的权限名。3) 授予列权限时,<权限类型>的值只能指定为 SELECT、INSERT 和 UPDATE,同时权限的后面需要加上列名列表 column-list。4) 最有效率的权限是用户权限。授予用户权限时,<权限类型>除了可以指定为授予数据库权限时的所有值之外,还可以是下面这些值:CREATE USER:表示授予用户可以创建和删除新用户的权限。SHOW DATABASES:表示授予用户可以使用 SHOW DATABASES 语句查看所有已有的数据库的定义的权限。【实例】使用 GRANT 语句创建一个新的用户 testUser,密码为 testPwd。用户 testUser 对所有的数据有查询、插入权限,并授予 GRANT 权限。输入的 SQL 语句和执行过程如下所示。mysql> GRANT SELECT,INSERT ON *.* -> TO 'testUser'@'localhost' -> IDENTIFIED BY 'testPwd' -> WITH GRANT OPTION; Query OK, 0 rows affected, 1 warning (0.05 sec)使用 SELECT 语句查询用户 testUser 的权限,如下所示。mysql> SELECT Host,User,Select_priv,Grant_priv -> FROM mysql.user -> WHERE User='testUser'; +-----------+----------+-------------+------------+ | Host | User | Select_priv | Grant_priv | +-----------+----------+-------------+------------+ | localhost | testUser | Y | Y | +-----------+----------+-------------+------------+ 1 row in set (0.01 sec)
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签