精华内容
下载资源
问答
  • oracle存储过程----变量的介绍及使用(PL/SQL)

    万次阅读 多人点赞 2018-08-17 08:16:00
      学习一门语言,既然学会了hello word 的输出,那就要关注下基础,首先要熟悉存储过程 中的变量类型。   关于存储过程变量有哪些 ,这样的问题,我在百度上搜索,却发现很多没用的,最近在同事那里,忽然看到...

    上一篇 oracle存储过程—-入门存储过程

    oracle存储过程—-变量的介绍及使用

      学习一门语言,既然学会了hello word 的输出,那就要关注下基础,首先要熟悉存储过程 中的变量类型。
      关于存储过程变量有哪些 ,这样的问题,我在百度上搜索,却发现很多没用的,最近在同事那里,忽然看到一本《oracle从入门到精通》,搜了一下,发现了存储过程 的东西,却是PL/SQL 中的基础知识 ,好尴尬啊。
    这里写图片描述
      通过学习,了解到了变量的一些知识。
    变量的分类如下:

    存储过程中的变量:
    一、标量类型 (有%TYPE)
    二、复合类型
         (1)记录类型 (有%ROWTYPE)
         (2)索引表类型(关联数组)
         (3)varry变长数组

    一、标量类型

      标量类型,一种是常用的有NUMBERCHARVARCHAR2VARCHARNCHARNVARCHAR2LONGDATETIMESTAMP ,基本上oracle 数据库认识的类型都可以直接用了。
      还有一些我觉得不常用的,PLS_INTEGERBINARY_INTEGERSIMPLE_INTEGER布尔类型(可以用来存储逻辑的值,不能用作定义表中的数据类型)
      另外还有一个最常用的 %TYPE
      因为上一篇已经简单用过第一种,所以这里介绍一下%TYPE
      %TYPE 这种方式定义的变量类型的方式和其他的有所不同,它利用已经存在的数据类型来定义新数据的数据类型。例如,当定义多个变量或常量时,只要前面使用过的数据类型,后边的变量就可以利用%TYPE 引用,最常见的就是把表中的字段类型作为变量或常量的数据类型。使用此种方式的好处有以下几点:

    1. 利用%TYPE 方式定义的变量类型和被引用的常量数据类型保持一致,如果以前是VARCHAR 类型,现在要改成NUMBER 类型,那就只需要直接改数据表中的类型即可,对已写好的存储过程 没有影响。
    2. 还有个好处就是,存储过程 基本都会有表操作,这就避免了在数据传入的时候,引发数据溢出或不符的情况。比如数据库里是VARCHAR(1) 这样的,但是实际传入的可能是张三 这样的字符串,肯定会导致在执行到这行数据的时候引发异常。如果能用%TYPE,那在调用存储过程 的时候,就能抛出错误。

    如下图所示:
      sex LY_DS.LY_NB%TYPE ,表示:
      定义一个变量sex,它的类型与表LY_DS中的字段LY_NB` 类型一致。

    create or replace procedure test_select_procedure
    (sex  LY_DS.LY_NB%TYPE,countNum out number)
    AS
    BEGIN
    select count(*) into countNum from ly_ds where LY_NB=sex;
    dbms_output.put_line(countNum);
    END;

    二、复合类型

    1、记录类型

      如果在存储过程中查询结果中,是多列的情况,我们可能需要查询到结果后,对其做引用名称.成员名称 这样取值。上一篇中说到过,可以使用into,即如下写法:

    create or replace procedure test_select2_procedure
    (sex  varchar)
    AS
    countNum number(10); --别忘了写上具体的长度,并且以分号结束
    maxId number(10); --别忘了写上具体的长度,并且以分号结束
    BEGIN
    select count(*),max(id) into countNum,maxId from ly_ds where LY_NB=sex;
    dbms_output.put_line(countNum);
    dbms_output.put_line(maxId);
    END;

      上边的是一种写法,就是into 后边跟上定义好的多个标量类型 。但是如果字段很多呢?
      显而易见,再用这个into 就不合适了,记录类型 就是解决这个的。

    (1)定义type 的声明写法

      定义type 的写法为 type type_name is record(col_name col_type); 这样,括号里可以写多个,中间用 , 分割,但最后一个不能有 , ,具体如下:

    set serveroutput on;
    DECLARE
    TYPE new_type IS RECORD   --以TYPE type_name IS RECORD开始
    (
       v_ly_nl LY_DS.LY_NL%TYPE,
       v_ly_mc varchar(100) --最后不要加,   
    );  --最后以 ;结束
    v_obj new_type; --将新对象定义为刚才声明的类型
    BEGIN
     --into赋值给v_obj,会按照定义的type顺序赋值
    select ly_nl,ly_mc into v_obj from ly_ds where id='2'; 
    dbms_output.put_line('第一个变量:'||v_obj.v_ly_nl);
    dbms_output.put_line('第二个变量:'||v_obj.v_ly_mc);
    END;

      输出结果如下:

    匿名块已完成
    第一个变量:22
    第二个变量:王五
    
    (2)通过%ROWTYPE 的声明写法

      %ROWTYPE 该类型是提取行记录时常用的存储数据的方式。这种声明方式,可以直接引用表中的行作为变量类型,它同%TYPE 在优点上类似,避免因表中字段的数据类型改变,而导致PL/SQL 块出错的问题。
      下边是%ROWTYPE 的用法例子,挺简单的:

    set serveroutput on;
    DECLARE
    v_obj ly_ds%rowtype; --ROWTYPE不区分大小写
    BEGIN
     --into赋值给v_obj,会按照定义的type顺序赋值
    select * into v_obj from ly_ds where id='2'; 
    dbms_output.put_line('第一个变量:'||v_obj.ly_nl);
    dbms_output.put_line('第二个变量:'||v_obj.ly_mc);
    END;

      注意一个地方,就是上边的into 前边,只能为 * ,如果要写为具体的列,那就要写全

    2、索引表类型(关联数组)

      该类型与数组相似,利用键值查找对应的数据,但是这里的键值同我们真正的数组下标不同,这种索引表的下标,还可以为字符串,真正的数组下标都是数字。索引表中的数据可以是上边介绍过的标量类型,也可以是记录类型。当在赋值的过程中,对已存在的索引表下标重复赋值,则会替换以前的数据,这个很好理解。

      以下是我学习的时候,记录的这部分内容,都写在了下边:

    set serveroutput on;
    DECLARE
      /**
       *声明一个存储ly_ds整行数据的索引表,下标为数字,
       *即 binary_integer
       */
      type index_row_type is table of ly_ds%rowtype
      index by binary_integer;
    
      /**
       *声明一个存储字符串数据的索引表,下标也为数字,
       *即 pls_integer
       */
      type index_val_type is table of varchar2(10)
      index by pls_integer;
    
      /**
       *声明一个存储字符串数据的索引表,下标为字符串,
       *即 varchar(100)、varchar(10),必须给固定大小
       */
      type index_str_val_type is table of varchar2(100)
      index by varchar(10);
       /**
        *定义一个下标为数字,存ly_ds一行的变量
        */
      v_row index_row_type; 
      /**
       *定义一个下标为数字,存字符串的变量
       */
      v_val index_val_type; 
      /**
       *定义一个下标为字符串,存字符串的变量
       */
      v_str_val index_str_val_type; 
    BEGIN
     /**
      *为下标为数字的 字符串索引表下标1赋值
      */
      v_val(1) :='正数'; 
      /**
      *为下标为数字的 字符串索引表下标-1赋值
      */
      v_val(-1) :='负数'; 
      dbms_output.put_line('v_val中下标1的值:'||v_val(1));
      dbms_output.put_line('v_val中下标-1的值:'||v_val(-1));
    
      /**
      *将改行数据赋值给行变量的下标1上
      */
      select * into v_row(1) from ly_ds where id='2'; 
      dbms_output.put_line('v_row(1)中ly_mc的值:'||v_row(1).ly_mc);
      dbms_output.put_line('v_row(1)中ly_nl的值:'||v_row(1).ly_nl);
    
       /**
        *为下标为字符串的 字符串索引表的下标one赋值
        */
      v_str_val('one') :='java天下第一';  
       /**
        *为下标为字符串的 字符串索引表的下标test赋值
        */
      v_str_val('test') :='java天下无敌'; 
       /**
        *为下标为字符串的 字符串索引表的下标test1赋值
        */
      v_str_val('test1') :='java太可怕了'; 
      dbms_output.put_line('v_str_val中下标one的值:'||v_str_val('one'));
      dbms_output.put_line('v_str_val中下标test的值:'||v_str_val('test'));
      dbms_output.put_line('v_str_val中第一个值的下标:'||v_str_val.first);
      dbms_output.put_line('v_str_val中第一个下标对应的值:'||v_str_val(v_str_val.first));
      dbms_output.put_line('v_str_val中最后一个下标:'||v_str_val.last);
    END;

      运行后会有下边的结果:

    匿名块已完成
    v_val中下标1的值:正数
    v_val中下标-1的值:负数
    v_row(1)ly_mc的值:王五
    v_row(1)ly_nl的值:22
    v_str_val中下标one的值:java天下第一
    v_str_val中下标test的值:java天下无敌
    v_str_val中第一个值的下标:one
    v_str_val中第一个下标对应的值:java天下第一
    v_str_val中最后一个下标:test1

      上边有个特别注意的问题,就是,定义下标和存储的值的时候,一定要给出大小,比如字符串,不能写成varchar ,必须要写成varchar(100) 这样有固定大小的类型。
      上边我用了三种,一种是pls_integerbinary_integer ,一种是ly_ds%rowtype ,这两种都有固定的大小,第一种是数字类型,它们有固定的大小,可以百度一下。如果定义了标量类型那种,必须要要给出大小,这个需要注意下。

    3、varry变长数组

      varry 数组,是另一种存储有序元素的集合。集合下标从1开始,比较适合较少的数据使用。具体如下:
      它有一个注意的地方,就是数组在定义一个变量时候,一定要初始化 ,并且,在使用前 一定要先确定容量 。对于,在初始化时,已赋值的,可以不用定义存储的大小了。这点与java 中的数组是一样的。

    set serveroutput on;
    DECLARE
      /**
       *声明一个最多容纳100个数的varry数组,注意,它的下标是从1开始的。
       *即 binary_integer
       */
      type array_type is varray(100) of varchar(100);
      /**
       *分别定义一个直接赋值的和两个未赋值的数组。
       *注意:一定要初始化,但可以不赋值。对于没有赋值的这种数组,在用之前
       *也一定要先确定容量。
       */
      v_val_array array_type := array_type('one','two');
      v_val_array2 array_type := array_type();
      v_val_array3 array_type := array_type();
    BEGIN
       /**
        *获取第一个varry数组中的值
        *varry的下标从1开始
        */
        dbms_output.put_line('v_val_array中下标1的值:'||v_val_array(1));
        dbms_output.put_line('v_val_array中下标2的值:'||v_val_array(2));
    
    
       /**
        *获取第二个varry数组中的值
        *因为第二个varry没有初始化长度,所以通过extend方法,
        *为该数组加一个空位
        */
        v_val_array2.extend;
        v_val_array2(1) :='aaa'; 
        v_val_array2.extend;
        v_val_array2(2) :='bbb'; 
        v_val_array2.extend;
        v_val_array2(3) :='ccc'; 
        dbms_output.put_line('v_val_array2中下标1的值:'||v_val_array2(1));
        dbms_output.put_line('v_val_array2中下标2的值:'||v_val_array2(2));
        dbms_output.put_line('v_val_array2中下标3的值:'||v_val_array2(3));
    
         /**
        *获取第三个varry数组中的值
        *因为第三个varry没有初始化长度,所以通过extend方法
        *初始化空位
        */
    
      /**
        *获取第二个varry数组中的值
        *因为第二个varry没有初始化长度,所以通过extend方法,
        *为该数组初始化长度
        */
        v_val_array3.extend(v_val_array2.count());
        v_val_array3(1) :='ddd'; 
        v_val_array3(2) :='eee'; 
        v_val_array3(3) :='fff'; 
        dbms_output.put_line('v_val_array3中下标1的值:'||v_val_array3(1));
        dbms_output.put_line('v_val_array3中下标2的值:'||v_val_array3(2));
        dbms_output.put_line('v_val_array3中下标3的值:'||v_val_array3(3));
    END;

      执行后的结果为:

    匿名块已完成
    v_val_array中下标1的值:one
    v_val_array中下标2的值:two
    v_val_array2中下标1的值:aaa
    v_val_array2中下标2的值:bbb
    v_val_array2中下标3的值:ccc
    v_val_array3中下标1的值:ddd
    v_val_array3中下标2的值:eee
    v_val_array3中下标3的值:fff

      上边分别是三种情况,其中有extend ,可能新手会感到迷惑。
      因为v_val_array2v_val_array3 开始的时候,只是定义了变量,所以,在使用前,需要给出大小,extent 的用法,即是对数组的长度加1个空位 的意思。
      如果想直接为v_val_array3给出固定大小,可以直接v_val_array3.extend(3) ,这样就会给v_val_array3 一个默认的存储大小为3 ,也可以通过已有数组的大小,即是上边的v_val_array3.extend(v_val_array2.count())

      虽然上边都是PL/SQL 那边的知识,但是它们在存储过程 中,都是通用的。变量这地方,浪费了挺长的时间,但是基础有利用后边的学习,我觉得浪费了这两天应该会对自己有用处的。
      下一篇 oracle存储过程—-存储过程执行简单的增删改查sql

    展开全文
  • 存储过程和函数区别 存储过程的限制相对较少,函数限制...from 关键字后面】存储过程可返回参数或结果集【可返回多个】,函数只能返回值或表对象【只能返回一个变量存储过程的参数可以in,out,inout三种类型,...

    存储过程和函数的区别

    存储过程的限制相对较少,函数限制比较多【不能用临时表,只能用表变量】
    存储过程实现的功能比较复杂,函数实现的功能针对性更强
    存储过程一般作为独立的部分来执行,函数可以作为查询语句的一部分来调用【可位于 select 中 from 关键字后面】
    存储过程可返回参数或结果集【可返回多个】,函数只能返回值或表对象【只能返回一个变量】
    存储过程的参数可以有in,out,inout三种类型,函数只能有in类
    存储过程声明时不需要返回类型,函数声明时需要描述返回类型,且函数体中必须包含一个有效的return语句
    函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行
    存储过程处理比较复杂的业务时比较实用
    使用了存储过程的系统更加稳定
    存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译
    存储过程声明时不需要返回类型
    存储过程通过call语句调用 call 存储过程名

    什么是视图?

    视图(view)也被称作虚表,即虚拟的表,也就是说该表里面没有数据,他的数据是从别的基础表中获取的,是一组数据的逻辑表示;视图本身并不包含任何数据,它只包含映射到基表的一个查询语句,当基表数据发生变化,视图数据也随之变化;视图也是一张表,对于基础表的所有基础操作(增删改查),视图也适用。

    视图的作用?

    ① 可以定制用户数据,聚焦特定的数据
    ② 可以合并分离的数据,创建分区视图
    ③ 能够简化用户的操作
    ④ 能使用户以多钟角度看待同一数据
    ⑤ 能对重构数据库提供一定程度的逻辑独立性【重构数据库指数据库长时间运行后,物理结构、逻辑结构等发生变化,导致性能低下】
    ⑥ 视图能够对机密数据提供安全保护

    什么是索引?

    索引类似于一本书的目录,可以提高数据检索的效率,降低数据库的IO成本,索引的目的是为了更快速找到数据。
    MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。我们可以简单理解为:快速查找排好序的一种数据结构。

    索引的种类有哪些?

    普通索引:仅加速查询
    唯一索引:加速查询 + 列值唯一(可以有null)
    主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个
    组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
    全文索引:对文本的内容进行分词,进行搜索

    Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE

    1. FULLTEXT索引:即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。

    2. HASH索引:可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。

    3. BTREE索引:是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。

    4. RTREE索引:在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。相对于BTREE,RTREE的优势在于范围查找。

    什么是触发器?

    触发器是一种特殊类型的存储过程,当在指定表中对数据进行 update、insert 或 delete 数据修改操作时,触发器会生效。触发器可以查询其它表,而且可以包含复杂的 SQL 语句。它们主要用于强制复杂的业务规则或要求。
    简单的说,就是当一张表发生数据修改操作(插入、删除、更新)时,会自动触发执行预先编写好的若干条 SQL 语句
    特点:触发事件的操作和触发器里的SQL语句是一个事务操作,具有原子性,要么全部执行,要么都不执行
    作用:保证数据的完整性,起到约束的作用

    触发器与存储过程的唯一区别是触发器不能执行 execute 语句调用,而是在用户执行 Transact-SQL 语句时自动触发执行

    展开全文
  • 目录这里使用是MySQL8关键字存储过程相关操作声明语句结束符创建存储过程存储过程开始和结束变量的使用变量赋值用户变量局部变量查看变量值调用存储过程删除存储过程查询数据库有哪些存储过程查看存储过程详情存储...


    这里使用的是MySQL 8)

    关键字

    括号中是小写,看起来方便,但关键字还是建议写成大写形式的。不过学习时可以先写成小写,毕竟自己看着舒服!

    关键字 作用
    DELIMITER (delimiter) 声明存储过程体语句结束符
    CREATE PROCEDURE (create procedure) 创建存储过程(其实应该分开,两个关键字,但这样记好记),可以传参
    参数类型: IN (in) 表示参数是输入参数(传入值可以是字面量或变量)
    参数类型:OUT (out) 表示参数是输出参数,向调用者返回数据(可以返回多个值)(传出值只能是变量)
    参数类型: INOUT (inout) 表示参数即是输入参数又是输出参数(值只能是变量)
    BEGIN .... END (begin…end) 存储过程开始和结束标签
    @ 用在用户变量名前,表示该变量是用户变量
    DECLARE (declare) 声明局部变量,只能在 BEGIN .... END 内使用
    SET (set) 给变量赋值
    call 调用存储过程

    存储过程相关操作

    声明语句结束符

    语句结束符用在END关键字后面,用来表示存储体过程结束。如:END $$

    • 命令:

      DELIMITER 符号(可以自定义)
      
    • 示例

      DELIMITER $$
      

      或者

      DELIMITER //
      
    • 注意
      在存储过程结束后,要将语句结束符修改回;,即:

      DELIMITER ;
      

    创建存储过程

    • 命令

      CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数数据类型 )
      

      或:

      CREATE PROCEDURE 数据库名.存储过程名(IN|OUT|INOUT 参数名 参数数据类型 )
      

      默认情况下,存储过程和默认数据库相关联,如果想指定存储过程创建在某个特定的数据库下,那么在过程名前面加数据库名做前缀。

    • 示例

      CREATE PROCEDURE myprocedure(IN test_in int)
      

    存储过程开始和结束

    • 命令

      BEGIN
      	存储过程体
      END $$
      
    • 示例

      CREATE PROCEDURE myprocedure(IN test_in int)
      BEGIN
      	存储过程体
      END $$
      

      这组关键字还可以嵌套使用、贴标签等,示例:

      CREATE PROCEDURE myprocedure(IN test_in int)
      label1: BEGIN
      	label2: BEGIN
      		存储过程体
      	END label2 ; -- 注意这里的封号
      END label1 $$
      

    变量的使用

    变量赋值
    • 命令

      set 变量名 = 值
      
    用户变量

    用户变量可以在存储过程体外声明,使用@符号表明该变量是用户变量。

    • 形式

      @变量名
      
    • 声明并赋值

      set @u_variable= 1;
      
    • 注意

      • @只是表明变量是用户变量,可以在存储过程体外声明,并不意味着用户变量是用@来创建,如:@u_variable;是不正确的。
      • 声明和使用用户变量时,都需要加上@,如:select @u_variable
      • 滥用用户变量会导致程序难以理解及管理。
    局部变量

    局部变量只能存在与BEGIN ... END之内,使用DECLARE声明

    • 命令

      DECLARE 变量名 数据类型 [default value]
      
    • 数据类型
      MySQL数据类型:int, float, date,varchar(length)等

    • 声明示例

      BEGIN
      	DECLARE test_int int unsigned default 1;  
      	DECLARE test_numeric number(8,2) DEFAULT 9.95;  
      	DECLARE test_date date DEFAULT '2020-7-18';  
      	DECLARE test_datetime datetime DEFAULT '2020-7-18 15:55:59';  
      	DECLARE test_varchar varchar(255) DEFAULT 'hello world';
      END $$
      
      • unsigned : 无符号
      • signed :有符号
    • 引用示例

      CREATE PROCEFURE myprocedure(OUT t_int int)
      BEGIN
      	DECLARE test_int int unsigned default 1;
      	set t_int = test_int;
      END $$
      
    查看变量值
    • 命令
      用在BEGIN .. END
      select 局部变量名;
      
      或者:
      用在存储过程体外
      select @用户变量名;
      

    调用存储过程

    • 命令

      call 存储过程名
      
    • 示例:@t_int是返回参数

      call myprocedure(@t_int);
      select @t_int;
      

    删除存储过程

    • 命令

      DROP PROCEDURE 存储过程名
      

    查询数据库有哪些存储过程

    • 命令

      show procedure status where db='数据库名';
      

      或者:

      select routine_name from information_schema.routines where routine_schema='数据库名';
      

    查看存储过程详情

    • 命令

      show create procedure 数据库名.存储过程名;
      

    存储过程注释

    使用双横杠代表注释。

    • 命令

      -- 这里是注释内容
      

    存储过程参数类型

    • 首先,创建一个数据库,并插入数据
    create table t_user(
    id int primary key auto_increment,
    username varchar(30),
    sex varchar(10)
    )engine = innodb;
    
    insert into t_user(id, username, sex) values(default, "吕布", "男");
    insert into t_user(id, username, sex) values(default, "貂蝉", "女");
    

    以下写的是比较完整的存储过程模板,可以借鉴以下!!!

    参数类型:IN

    表示参数是输入类型参数,由调用者传递给存储过程(传入值可以是字面量或变量)。下面代码:从用户表中查询用户id为1的用户。

    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS test_in;
      CREATE PROCEDURE test_in(IN t_id int)
      BEGIN
      	SELECT * FROM t_user WHERE id = t_id;
      END $$
      DELIMITER ;
      
      set @t_id = 1;
      call test_in(@t_id);
      

    参数类型:OUT

    表示参数是输出参数,由存储过程返回给调用者,(可以返回多个值,传出值只能是变量)。下面代码:从user表中查出用户id为2的用户的性别。

    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS test_out;
      CREATE PROCEDURE test_out(OUT t_sex varchar(10))
      BEGIN
      	DECLARE u_sex varchar(10) DEFAULT '男';
      	set u_sex = (select sex from t_user where id=2);
      	set t_sex = u_sex;
      END $$
      DELIMITER ;
      call test_out(@t_sex);
      select @t_sex;
      

    参数类型:INOUT

    表示这个参数即是输入参数又是输出参数,以下代码功能:传递用户名称,获取用户性别。

    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS test_inout;
      CREATE PROCEDURE test_inout(INOUT t_msg varchar(30))
      BEGIN
      	DECLARE t_msg_tmp varchar(10) DEFAULT '男';
      	set t_msg_tmp = (select sex from t_user where username=t_msg);
      	set t_msg = t_msg_tmp;
      END $$
      DELIMITER ;
      set @t_msg = '貂蝉';
      call test_inout(@t_msg);
      select @t_msg;
      

    存储过程控制语句

    变量的作用域

    BEGIN ... END内声明的局部变量,在嵌套使用时,外层声明的变量可以在内层进行访问,但是内层的访问在遇到自己的END时,就会消失,无法在外层访问到。可以通过OUT参数等方式保存下来。

    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc()
      BEGIN
      		DECLARE x1 int unsigned default 1;
      		BEGIN
      			DECLARE x1 int unsigned default 2; -- 内层的x1只在本层有效
      			select x1; 
      		END; -- 注意这里的封号
      		select x1; -- 这里是外层的x1,内层的x1已经失效
      END $$
      DELIMITER ;
      call proc();
      

    条件语句

    • 命令

      if 条件 then
      	执行语句;
      elseif 条件 then
      	执行语句;
      else
      	执行语句;
      end if;
      
    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc(INOUT t_num int)
      BEGIN
      	DECLARE x1 int unsigned default 3;
      	if x1=1 then
      		set t_num=1;
      	elseif x1=2 then
      		set t_num=2;
      	else
      		set t_num=3;
      	end if;
      END $$
      DELIMITER ;
      
      set @t_num = 0;
      call proc(@t_num);
      select @t_num;
      

    case语句

    • 命令

      case 条件变量
      when 条件值 then
      	执行语句;
      when 条件值 then
      	执行语句;
      else
      	执行语句;
      end case;
      
    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc(INOUT t_num int)
      BEGIN
      	DECLARE x1 int unsigned default 3;
      	case x1
      	when 1 then
      		set t_num = 1;
      	when 2 then
      		set t_num = 2;
      	else 
      		set t_num =3;
      	end case;
      END $$
      DELIMITER ;
      
      set @t_num = 0;
      call proc(@t_num);
      select @t_num;
      

    while循环语句

    先判断条件是否符合,符合才执行语句。只有符合条件,才执行循环体。也就是只有符合条件才进行循环

    • 命令

      while 条件 do
      	执行语句;
      end while;
      
    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc(INOUT t_num int)
      BEGIN
      	while t_num <3 do
      		set t_num = t_num + 1;
      	end while;
      END $$
      DELIMITER ;
      
      set @t_num = 0;
      call proc(@t_num);
      select @t_num;
      

    repeat循环语句

    先执行依次语句,在判断是否符合条件,不符合则继续执行语句。直到符合条件,才不执行循环体,否则一直执行,也就是直到符合条件才退出循环

    • 命令

      repeat
      	执行语句
      until 循环条件
      end repeat;
      
    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc(INOUT t_num int)
      BEGIN
      	repeat
      		set t_num = t_num + 1;
      	until t_num >3
      	end repeat;
      END $$
      DELIMITER ;
      
      set @t_num = 0;
      call proc(@t_num);
      select @t_num;
      

    loop循环语句

    loop不需要给定循环条件,使用标签leave关键字退出循环。我们可以使用if条件语句去控制loop循环次数。

    • 命令

      自定义标签:loop
      	执行语句;
      	leave 自定义标签;
      end loop;
      
    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc(INOUT t_num int)
      BEGIN
      	loop_label:loop
      		set t_num = t_num + 1;
      		if t_num > 3 then
      			leave loop_label;
      		end if;
      	end loop;
      END $$
      DELIMITER ;
      
      set @t_num = 0;
      call proc(@t_num);
      select @t_num;
      

    LABELS标签

    标签,也叫标号,可以用在 begin、repeat、while 或者 loop 语句前,语句标号只能在合法的语句前面使用。可以跳出循环,使运行指令达到复合语句的最后一步。不需要加引号,直接写即可!如上loop_label所示那样!

    ITERATE迭代

    ITERATE 通过引用复合语句的标签,来重新开始复合语句。

    • 命令

      iterate 标签;
      
    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc(INOUT t_num int)
      BEGIN
      	loop_label:loop
      		set t_num = t_num + 1;
      		if t_num = 3 then
      			set t_num = t_num+1;
      			iterate loop_label;
      		end if;
      		
      		if t_num > 6 then
      			leave loop_label;
      		end if;
      	end loop;
      END $$
      DELIMITER ;
      
      set @t_num = 0;
      call proc(@t_num);
      select @t_num;
      

    游标遍历查询结果集

    当我们需要对查询的结果集循环进行处理时,就可以使用游标来逐一获取结果集中的值,再逐一进行处理即可。

    • 命令

      -- 定义while循环标志,不同循环语句,判定条件不同,注意了
      -- 在MySQL中,int类型0代表false,1代表true,done可以自定义,是比变量名而已
      DECLARE done int default true;
      -- 定义游标
      DECLARE cur CURSOR FOR (具体的查询语句);
      -- 设定循环标志为结束标志,当游标中没有数据时,设定标志位为false,结束while循环
      DECLARE CONTINUE HANDLER FOR NOT FOUND set done = false;
      -- 打开游标
      OPEN cur;
      -- 使用while循环语句
      while done do
      	-- 使用FETCH关键字从游标中取值,使用INTO关键字将值注入局部变量
      	FETCH cur INTO 局部变量1, 局部变量2;
      	-- 具体操作
      	执行语句;
      end while;
      -- 关闭游标
      CLOSE cur;
      
    • 数据库表
      在这里插入图片描述

    • 代码示例

      DELIMITER $$
      DROP PROCEDURE IF EXISTS proc;
      CREATE PROCEDURE proc()
      BEGIN
      	-- 为数据库表的每个字段设置局部变量,用户保存
      	DECLARE tmp_id int unsigned default 1;
      	DECLARE tmp_username varchar(30) default '';
      	DECLARE tmp_sex varchar(10) default '男';
      
      	-- 定义循环标志
      	DECLARE done int default true;
      	-- 定义游标
      	DECLARE cur CURSOR FOR (select * from t_user);
      	-- 设定循环标志为结束标志
      	DECLARE CONTINUE HANDLER FOR NOT FOUND set done = false;
      	-- 打开游标
      	OPEN cur;
      	-- 使用while循环语句
      	while done do
      		FETCH cur INTO tmp_id, tmp_username, tmp_sex;
      		-- 具体操作
      		select tmp_id,tmp_username,tmp_sex;
      	end while;
      	-- 关闭游标
      	CLOSE cur;
      END $$
      DELIMITER ;
      call proc();
      
    展开全文
  • 从一开始学习Java我们就知道Java...四种引用类型可以说是在学习Java的过程中经常会接触到。Java中主要包括了四种引用类型,分别是:强引用,软引用,弱引用以及虚引用。 一、强引用 强引用是一种最常见引用形式,

    从一开始学习Java我们就知道Java的数据类型一般有两种,一种是基本数据类型,另一种是引用数据类型。其中,基本数据类型的值通常储存在栈内存中,用于对该类型的对象进行存储;而引用数据类型则在存储堆中对需要引用的对象进行引用。

    在这里插入图片描述

    引用是Java面向对象的一个特点,如果一个对象不曾被任何变量应用的话,那么整个程序也就无法再使用这一对象。四种引用类型可以说是在学习Java的过程中经常会接触到的。Java中主要包括了四种引用类型,分别是:强引用,软引用,弱引用以及虚引用。

    一、强引用

    强引用是一种最常见的引用形式,同时也较为普遍。是指创建一个对象并把这个对象直接赋给一个变量:

    Student s = new Student();
    String name = "周二鸭";
    

    如果内存空间不足,Java虚拟机将会直接抛出OutOfMemoryError错误,从而程序将异常停止。强引用的对象是不会被 GC 回收线程回收的,不可以随意回收具有强引用的对象来解决内存不足的问题。在Java中,强引用是一种默认的状态,除非JVM虚拟机停止工作。

    如果想终止一个强引用与一个对象直接的联系,可以将对象赋值为null,那么JVM就可以在合适时间将这个对象回收。

    Student s = new Student();
    s = null;
    

    二、软引用

    软引用和强引用不同,如果内存空间足够多,一个对象被软引用,则垃圾回收器不会将其回收;如果内存空间不足,这些引用对象就会被回收。所以,软引用就是当回收器没有回收某个对象时,程序就可以对其使用。它可用来较为敏感的高速缓存,虚拟机可以将软引用加入到与之向关联的队列。下面利用代码说明一下:

    Student s = new Student();  
    SoftReference<Student> softRef = new SoftReference<Studnet>(s);
    

    此时,对于这个Student对象,有两条引用路径,一个是来自SoftReference对象的软引用,另外一个是来自于s这个变量的强引用。现在这个Student对象是不会被垃圾回收线程回收,接下来我们可以结束s对这个Student实例的强引用,将其置为null:s = null,那么此时如果内存空间足够的话,它就不会被回收:

    s = (Student)softRef.get();
    System.out.println(s);
    

    如果内存空间不足,那么Student的实例对象就会被回收,上面代码就会获得null。

    三:弱引用

    弱引用的特点就是引用对象的生命周期较短。GC回收器在扫描内存区域是若发现弱引用,无论内存空间足够与否,弱引用对象都会被回收。但弱引用对象也可以加入队列,这样就可以不被回收。

    Public class WeakRefDemo {
        public static void main (String[] args) {  
            WeakReference<Student> ref = new WeakReference<Student>(new Student("周二鸭", 20));  
            System.out.println(ref.get());
            // 通知 GC 线程回收资源  
            System.gc();
            System.out.println(ref.get());  
        }
    }
    
    
    class Student{  
        public String name;  
        public int age;
        
        public Student(String name,int age) {  
            this.name=name;  
            this.age=age;  
        } 
        
        @Override  
        public String toString() {  
            return "hello";  
        }  
    }
    

    上面代码输出:hello \n null

    弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

    如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象。

    四:虚引用

    虚引用也称为幻影引用:一个对象是都有虚引用的存在都不会对生存时间都构成影响,也无法通过虚引用来获取对一个对象的真实引用。唯一的用处:能在对象被GC时收到系统通知,JAVA中用PhantomReference来实现虚引用。

    展开全文
  • 说简单点就是,程序在运行过程中可以变化量就是变量。要搞清楚变量的本质,必须先要明白两个问题:1.电脑使用内存来记忆计算时所使用数据;2.内存存储数据规则。 2.申明变量的语法 数据类型 变量名 [=...
  • JS面试题—变量类型和计算

    千次阅读 2017-08-07 15:55:36
    JS面试题,是针对前端工程师面试时一些知识点梳理,整篇会围绕题目、知识点、解答三个过程进行学习。本人也属于此次总结学生,希望借此机会重新温习巩固基础...JS变量存储区分为哪些类型,并描述其特点 如何理解
  • 第四章:存储过程

    2013-05-13 10:01:00
     全局变量@@,局部变量@ 3、我们曾学习过的查询,合并多个表中的数据的方法有哪些?  联合(Union)-合并多个数据表中的行 子查询-将一个查询包含到另一个查询中 联接-合并多个数据表中的列 二:第四...
  • 浅析数据类型的转化

    2020-03-14 14:59:59
    在 JavaScript 程序执行过程中,往往需要变量存储的数值是某种特定数据类型,别数据类型不行,此时就需要进行数据类型转化 数据类型转化有哪些类型? 数据类型转化分为 : 自动转化 和 强制转化 两种...
  • in参数 入参值会仅在存储过程中起作用out参数 入参值会被置为空,存储中计算值会影响外面引用该变量的值inout参数 入参值不会被置为空,存储中计算值会影响外面引用该变量的值*/use mysql;/*创建1个存储...
  • 具体哪些类型是值类型哪些是引用类 型,大家翻翻书,背一背就好了,不过我想,做过一段时间开发,即使您背不了书上教条定义,也不会把值类型和引用类型搞混。接下来,还是老规矩,咱看 码说话吧。 1: public ...
  • 类型:类的描述信息,如此类有哪些局部变量、方法以及它的父类是什么等  类型存储地址:内存中的方法区  类型的生命周期的简单描述  类型生命周期过程: 装载——>连接——>初始化——>卸载  装载:把二...
  •  异常表示程序运行过程中可能出现非正常状态,运行时异常表示虚拟机通常操作中可能遇到异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生非运行时异常,但是并不要求必须声明抛出未被捕获...
  • 空间,这些内容决定了变量在程序的哪些部分是可见的。 第10章:对象和类 类是用户定义的类型,对象(如变量)是类的实例。本章介绍面向对象编程和类设计。对象声明描述的是存 储在对象中的信息以及可对对象执行的...
  • 1. 讨论算法在问题求解过程中的重要性。 2. 指出好的算法所必备的性质。 3. 开发求解简单问题的算法。 4. 使用伪代码或程序设计语言实现、测试和调试求解简单问题的算法。 5. 描述调试中的实用策略。 PF3.基本的...
  • 空间,这些内容决定了变量在程序的哪些部分是可见的。 第10章:对象和类 类是用户定义的类型,对象(如变量)是类的实例。本章介绍面向对象编程和类设计。对象声明描述的是存 储在对象中的信息以及可对对象执行的...
  • 空间,这些内容决定了变量在程序的哪些部分是可见的。 第10章:对象和类 类是用户定义的类型,对象(如变量)是类的实例。本章介绍面向对象编程和类设计。对象声明描述的是存 储在对象中的信息以及可对对象执行的...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 197
精华内容 78
关键字:

存储过程中的变量有哪些类型