Mysql Procedure create_synonym_db

Wesley13
• 阅读 779

这个存储过程的含义是复制一个数据库,将其数据表变为视图。这是Mysql sys数据库中的存储过程

Mysql  Procedure  create_synonym_db Mysql  Procedure  create_synonym_db

CREATE DEFINER=`mysql.sys`@`localhost` PROCEDURE `create_synonym_db`( IN in_db_name VARCHAR(64),  IN in_synonym VARCHAR(64) )
    MODIFIES SQL DATA
    SQL SECURITY INVOKER
    COMMENT '\n Description\n \n Takes a source database name and synonym name, and then creates the \n synonym database with views that point to all of the tables within\n the source database.\n \n Useful for creating a "ps" synonym for "performance_schema",\n or "is" instead of "information_schema", for example.\n \n Parameters\n \n in_db_name (VARCHAR(64)):\n The database name that you would like to create a synonym for.\n in_synonym (VARCHAR(64)):\n The database synonym name.\n \n Example\n \n mysql> SHOW DATABASES;\n +--------------------+\n | Database           |\n +--------------------+\n | information_schema |\n | mysql              |\n | performance_schema |\n | sys                |\n | test               |\n +--------------------+\n 5 rows in set (0.00 sec)\n \n mysql> CALL sys.create_synonym_db(''performance_schema'', ''ps'');\n +---------------------------------------+\n | summary                               |\n +---------------------------------------+\n | Created 74 views in the `ps` database |\n +---------------------------------------+\n 1 row in set (8.57 sec)\n \n Query OK, 0 rows affected (8.57 sec)\n \n mysql> SHOW DATABASES;\n +--------------------+\n | Database           |\n +--------------------+\n | information_schema |\n | mysql              |\n | performance_schema |\n | ps                 |\n | sys                |\n | test               |\n +--------------------+\n 6 rows in set (0.00 sec)\n \n mysql> SHOW FULL TABLES FROM ps;\n +------------------------------------------------------+------------+\n | Tables_in_ps                                         | Table_type |\n +------------------------------------------------------+------------+\n | accounts                                             | VIEW       |\n | cond_instances                                       | VIEW       |\n | events_stages_current                                | VIEW       |\n | events_stages_history                                | VIEW       |\n ...\n '
BEGIN DECLARE v_done bool DEFAULT FALSE; 
 DECLARE v_db_name_check VARCHAR(64);
 DECLARE v_db_err_msg TEXT; DECLARE v_table VARCHAR(64); 
 DECLARE v_views_created INT DEFAULT 0;  
 DECLARE db_doesnt_exist CONDITION FOR SQLSTATE '42000'; 
 DECLARE db_name_exists CONDITION FOR SQLSTATE 'HY000';  
 DECLARE c_table_names CURSOR FOR  
 SELECT TABLE_NAME  FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = in_db_name; 
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;
 SELECT 
    SCHEMA_NAME
INTO v_db_name_check FROM
    INFORMATION_SCHEMA.SCHEMATA
WHERE
    SCHEMA_NAME = in_db_name; 
    IF v_db_name_check IS NULL THEN SET v_db_err_msg = CONCAT('Unknown database ', in_db_name); 
    SIGNAL SQLSTATE 'HY000' 
    SET MESSAGE_TEXT = v_db_err_msg;
    END IF;
SELECT 
    SCHEMA_NAME
INTO v_db_name_check FROM
    INFORMATION_SCHEMA.SCHEMATA
WHERE
    SCHEMA_NAME = in_synonym; 
    IF v_db_name_check = in_synonym THEN SET v_db_err_msg = CONCAT('Can\'t create database ', in_synonym, '; database exists'); 
    SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = v_db_err_msg; 
    END IF;  
    SET @create_db_stmt := CONCAT('CREATE DATABASE ', sys.quote_identifier(in_synonym));
    PREPARE create_db_stmt FROM @create_db_stmt; EXECUTE create_db_stmt; DEALLOCATE PREPARE create_db_stmt; 
    SET v_done = FALSE; OPEN c_table_names;
    c_table_names: LOOP FETCH c_table_names INTO v_table;
    IF v_done THEN LEAVE c_table_names; END IF;  
    SET @create_view_stmt = CONCAT( 'CREATE SQL SECURITY INVOKER VIEW ', sys.quote_identifier(in_synonym), '.', sys.quote_identifier(v_table), ' AS SELECT * FROM ', sys.quote_identifier(in_db_name), '.', sys.quote_identifier(v_table) );
    PREPARE create_view_stmt FROM @create_view_stmt; EXECUTE create_view_stmt; DEALLOCATE PREPARE create_view_stmt; 
    SET v_views_created = v_views_created + 1; END LOOP; CLOSE c_table_names;
    SELECT 
    CONCAT('Created ',
            v_views_created,
            ' view',
            IF(v_views_created != 1, 's', ''),
            ' in the ',
            sys.quote_identifier(in_synonym),
            ' database') AS summary; 
END;

View Code

1.存储过程的调用

CALL sys.create_synonym_db('INFORMATION_SCHEMA', 'info1');
SHOW DATABASES ;

效果是创建了一个Info1的数据库;INFORMATION_SCHEMA里面有多个数据表,但没有视图,创建的Info1中有视图没有表。

INFORMATION_SCHEMA数据库是MySQL系统自带的数据库,它提供了数据库元数据的访问方式。感觉information_schema就像是MySQL实例的一个百科全书,记录了数据库当中大部分我们需要了结的信息,比如字符集,权限相关,数据库实体对象信息,外检约束,分区,压缩表,表信息,索引信息,参数,优化,锁和事物等等。通过information_schema我们可以窥透整个MySQL实例的运行情况,可以了结MySQL实例的基本信息,甚至优化调优,维护数据库等。

Mysql  Procedure  create_synonym_db Mysql  Procedure  create_synonym_db

CREATE DEFINER=`mysql.sys`@`localhost` PROCEDURE `create_synonym_db`( IN in_db_name VARCHAR(64),  IN in_synonym VARCHAR(64) )
    MODIFIES SQL DATA
    SQL SECURITY INVOKER

DEFINER :存储过程的创建者;决定用户权限,Mysql对存储过程具有3个权限:创建 CREATE ROUTINE,编辑或者删除 ALTER ROUTINE,运行EXECUTE。

INVOKER用于指定哪些用户有调用存储过程的权限。SQL SECURITY INVOKER 意思是SQL Security指定DEFINER 表示执行者拥有创建者的权限。

MODIFIES SQL DATA:表示子程序包含写数据的语句

入口参数有两个 in_db_name 需要复制的数据库(源),in_synonym 需要新建的数据库(目的)。

3. BEGIN END是procedure的主体程序

DECLARE v_done bool DEFAULT FALSE; 
 DECLARE v_db_name_check VARCHAR(64);
 DECLARE v_db_err_msg TEXT; DECLARE v_table VARCHAR(64); 
 DECLARE v_views_created INT DEFAULT 0;  
 DECLARE db_doesnt_exist CONDITION FOR SQLSTATE '42000'; 
 DECLARE db_name_exists CONDITION FOR SQLSTATE 'HY000';  
 DECLARE c_table_names CURSOR FOR  SELECT TABLE_NAME  FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = in_db_name; 
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;

1)DECLARE 声明变量。语法:   DECLARE 变量名  数据类型,默认值;

  1. 条件定义: DECLARE  变量名 CONDITION FOR 变量值;

  2. 异常处理:DECLARE  harder_type FRO  SQLSTATA SET operation;

harder_type : CONTINUE:在处理器操作完成之后,会继续执行产生这个异常语句之后的下一条语句。

EIXT :在处理器操作完成之后,存储过程会终止,并将控制返回调用者。

UNDO:在处理器操作完成之后,会滚回存储过程中执行过的SQL操作,操作完成之后,终止存储过程。

系统定义的异常状态 SQLSTATA

NOT FOUND  : 标识导致SQLCODE值为+100或者SQLSATE值为02000的异常。这个异常通常在SELECT没有返回行的时候出现。

SQLEXCEPTIOIN: 标识导致SQLCODE值为负的异常。

SQLWARNING: 标识导致警告异常或者导致正100以上的SQLCODE值的异常。

例子:DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNINGSET stmt ='ABORTED';//在出现SQLWARNING异常时也终止存储过程,并将名为stmt的变量设为“ABORTED”

4)定义游标  DECLARE 游标名称 CURSOR FOR 集合(一般为Select语句)

游标:为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力。游标机制允许用户在SQL server内逐行地访问这些记录,按照用户自己的意愿来显示和处理这些记录。

游标使用步骤    声明游标:DECLARE 游标名称 CURSOR FOR 集合(一般为Select语句)

打开游标:OPEN c_table_names;

使用游标操作数据:

   c_table_names: LOOP FETCH c_table_names INTO v_table;
    IF v_done THEN LEAVE c_table_names; END IF;  
    SET @create_view_stmt = CONCAT( 'CREATE SQL SECURITY INVOKER VIEW ', sys.quote_identifier(in_synonym), '.', sys.quote_identifier(v_table), ' AS SELECT * FROM ', sys.quote_identifier(in_db_name), '.', sys.quote_identifier(v_table) );
    PREPARE create_view_stmt FROM @create_view_stmt; EXECUTE create_view_stmt; DEALLOCATE PREPARE create_view_stmt; 
    SET v_views_created = v_views_created + 1; END LOOP;

关闭游标:CLOSE c_table_names;

4.下面一段代码的意思是,从INFORMATION_SCHEMA.SCHEMATA中查找SCHEMA_NAME为in_db_name(传入的参数:数据库名),并将其赋值给v_db_name_check中。

如果v_db_name_check 为空则设置v_db_err_msg 为‘Unknown database’

SELECT  SCHEMA_NAME INTO v_db_name_check FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = in_db_name; 
    IF v_db_name_check IS NULL THEN SET v_db_err_msg = CONCAT('Unknown database ', in_db_name); 
    SIGNAL SQLSTATE 'HY000' 
    SET MESSAGE_TEXT = v_db_err_msg;
    END IF;

 SELECT col_names INTO var_names FROM TABLE :给变量复制,用来将查询返回的一行的各个列值保存到局部变量中

SELECT col_names INTO table_name FROM table :复制列到新表中。

另外需要注意的是如果拼接后的语句中有字符串,那么四个单引号表示一个引号,这是很重要的,谨记于心。

例如:'''',name2,''''  拼接后的形式为 ‘name2’。

SELECT  SCHEMA_NAME INTO v_db_name_check FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = in_synonym; 
    IF v_db_name_check = in_synonym THEN SET v_db_err_msg = CONCAT('Can\'t create database ', in_synonym, '; database exists'); 
    SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = v_db_err_msg; 
    END IF;  

MESSAGE_TEXT的效果。

Mysql  Procedure  create_synonym_db

5.创建Sql语句,并执行;

SET @create_db_stmt := CONCAT('CREATE DATABASE ', sys.quote_identifier(in_synonym));
    PREPARE create_db_stmt FROM @create_db_stmt; EXECUTE create_db_stmt; DEALLOCATE PREPARE create_db_stmt;

PREPARE statement_name FROM preparable_SQL_statement; /*定义*/  preparable_SQL_statement为Sql语句
EXECUTE statement_name [USING @var_name [, @var_name] …]; /*执行预处理语句*/
{DEALLOCATE | DROP} PREPARE statement_name /*删除定义*/ ;

 6.游标操作

c_table_names: 
    LOOP FETCH c_table_names INTO v_table;
    IF v_done THEN LEAVE c_table_names; END IF;  
    SET @create_view_stmt = CONCAT( 'CREATE SQL SECURITY INVOKER VIEW ', sys.quote_identifier(in_synonym), '.', sys.quote_identifier(v_table), ' AS SELECT * FROM ', sys.quote_identifier(in_db_name), '.', sys.quote_identifier(v_table) );
    PREPARE create_view_stmt FROM @create_view_stmt; EXECUTE create_view_stmt; DEALLOCATE PREPARE create_view_stmt; 
    SET v_views_created = v_views_created + 1; 
    END LOOP;

LOOP  .... END LOOP  循环体 名称为c_table_name, 

FETCH   集合 INTO 变量名,诸葛取出数据到变量中。

跳出循环体的条件  v_done = true;   个人理解当从c_table_names 中取不到数据的时候,捕获到NOT FOUND的异常,v_done=true;退出循环。

如果取到值,则继续往下执行,  @create_view_satmt =' CREATE SQL SECURITY INVOKER VIEW `info1`.`CHARACTER_SETS` as select * from `INFORMATION_SCHEMA`.`CHARACTER_SETS`;'

执行Sql语句,至此完成根据in_db_name中的表结构创建,新数据库in_synonym中的View视图。

7. 执行完之后显示结果

SELECT 
    CONCAT('Created ',
            v_views_created,
            ' view',
            IF(v_views_created != 1, 's', ''),
            ' in the ',
            sys.quote_identifier(in_synonym),
            ' database') AS summary;

  最后执行的Sql语句为: select 'Created 30 views  in the  `info1` database as summary';

 Mysql  Procedure  create_synonym_db

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这