PLSQL 之类型、变量和结构

1、类型

在《.Net程序员学用Oracle系列(5):三大数据类型》一文中详细地讲述了 Oracle 的基本数据类型,文中还提到,除基本数据类型之外,Oracle 还在语法上支持一些非固有数值类型。

事实上,Oracle 在语法上支持的数据类型远不止于此,Oracle 还支持一些复杂而强大的数据类型。如属性类型%TYPE%ROWTYPE,记录类型 RECORD,集合类型 VARRAY 和 TABLE 等。本节将会介绍实用的属性类型和灵活的记录类型。

1.1、属性类型

属性类型是一种可以直接引用数据库中列的数据类型来描述变量类型的类型。Oracle 提供了两种属性类型,分别是%TYPE%ROWTYPE,下文将逐一说明。

%TYPE:该属性允许在声明中引用数据库中的列或先前声明的变量的数据类型,而不是硬编码类型名称。在声明常量、变量和参数时,都可以使用%TYPE属性作为数据类型说明符。如果引用的类型被更改,则声明也将自动更新,这点有利于后期代码维护。

示例:

DECLAREv_staff_name t_staff.staff_name%TYPE;BEGINSELECT t.staff_name INTO v_staff_name FROM demo.t_staff t WHERE t.staff_id=5;DBMS_OUTPUT.PUT_LINE(v_staff_name);END;

%ROWTYPE:该属性可以表示数据库中表或游标的行的记录类型。使用%ROWTYPE声明的变量可以存储从表中选择或从游标或游标变量获取的整行数据,且变量记录中的字段和每行中的相应列具有相同的名称和数据类型。

示例:

DECLAREv_staff t_staff%ROWTYPE;BEGINSELECT t.* INTO v_staff FROM demo.t_staff t WHERE t.staff_id=5;DBMS_OUTPUT.PUT_LINE(v_staff.staff_name);END;

想要更多的了解属性类型可参考:《Database PL/SQL User's Guide and Reference: %TYPE Attribute》和《Database PL/SQL User's Guide and Reference: %ROWTYPE Attribute》。

1.2、记录类型

记录类型是由单行多列标量构成的复合结构。可以看做是一种用户自定义的数据类型,提供了将一个或多个标量封装成一个对象进行操作的能力。在使用记录数据类型的变量时,需要在声明部分先定义记录的成员变量,然后在执行部分引用该记录变量本身或其中的成员。但不可以对记录做整体性的比较运算,如判断记录类型的变量是否为 NULL。

示例:

DECLARETYPE staff_type IS RECORD(staff_name VARCHAR2(50),gender VARCHAR2(2));v_staff staff_type;BEGINSELECT t.staff_name,DECODE(t.gender,1,'男',0,'女','两性') INTO v_staff.staff_name,v_staff.gender  FROM demo.t_staff t WHERE t.staff_id=5;DBMS_OUTPUT.PUT_LINE(v_staff.staff_name||'|'||v_staff.gender);END;

记录类型和%ROWTYPE属性在用途上比较相似,区别在于前者是自定义结构,而后者为表结构,前者比较灵活,而后者比较方便。

2、变量

一般计算机编程语言中都有变量的概念,PL/SQL 也不例外,变量用于存储计算结果和表示可变状态,本节将着重介绍在 PL/SQL 中变量如何定义及赋值。另外,PL/SQL 中也有常量,只是极少有人使用,有兴趣的读者可以参考《Oracle Database PL/SQL Language Reference: Constant》。

2.1、变量类型

在 PL/SQL 中定义变量的可选类型非常多,包括 Oracle 中常见的三大类基本数据类型,以及 Oracle 在语法上支持的诸多非固有数据类型。如整形(INT/INTEGER)、布尔类型(BOOLEAN)等 Oracle 本身并不支持,却在 PL/SQL 中可用的数据类型。

2.2、变量定义

在 PL/SQL 中定义变量与 C# 中定义变量本质上并无区别,不同的是 PL/SQL 中的变量得集中定义,变量定义区域得用DECLARE关键字开头,且每行只能定义一个变量。如果是 SQL*Plus 环境则必须用VAR[IABLE]开头。

语法:

variable_name datatype [[NOT NULL] {:= | DEFAULT} expression];

如果使用了 NOT NULL 则必须给变量赋初始值。另外,在命名变量的时候还需要遵守以下命名规则:

  • 1、变量名必须以字母开头。

  • 2、变量名长度不能超过 30 个字符。

  • 3、变量名中不能含有空格。

  • 4、同一语句块内变量名不能重复。

  • 5、变量名不能与查询中的列名相同。

2.3、变量赋值

给 PL/SQL 变量赋值的写法与给 C# 字段赋值写法基本一样,既可以在定义变量时就赋给它一个初始值,也可以在使用之前给它赋值,如果不赋值也会有默认值。唯一的区别就是,C# 中类型不同默认值也不同,而 PL/SQL 中所有类型的默认值都一样,都是 NULL。

在 PL/SQL 中还有一点比较怪的就是,可能所有编程语言的赋值操作符都是=,而 PL/SQL 中的赋值操作符却偏偏是:=。而且 Oracle 相关的 API 中参数写法也与其它大多数数据库不同。

示例一(普通 PL/SQL 环境):

DECLAREv1 NUMBER;v2 NUMBER(5,2);v3 NUMBER := 50.20;v4 NUMBER(4) := 1998;v5 VARCHAR2(4) DEFAULT 'A';v6 DATE NOT NULL := fn_now;BEGINv1 := 100;v2 := 99.99;v5 := 'A5';v6 := SYSDATE;  DBMS_OUTPUT.PUT_LINE(v1||'|'||v2||'|'||v3||'|'||v4||'|'||v5||'|'||v6);END;

示例二(SQL*Plus 环境):

VARIABLE v1 NUMBERBEGIN:v1 := 12;DBMS_OUTPUT.PUT_LINE(:v1);END;/

3、结构

和普通编程语言一样,PL/SQL 中也有常见的三大控制结构以及顺序控制语句——GOTO。本节将重点讲述被广泛接受的三大控制结构,至于不受待见的 GOTO 语句,有兴趣的读者可以参考《Oracle Database PL/SQL User's Guide and Reference: Using the GOTO Statement》。

3.1、顺序结构

顺序结构是面向过程编程中最基本、最简单、最常用的程序控制结构。顺序结构用于表示若干个依次执行的处理步骤,表现形式就是线性结构,一个方向走下去、不拐弯。使用时只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下、依次执行。

3.2、选择结构

PL/SQL 中提供了两种选择结构,分别是IF结构和CASE结构。其中IF结构有三种变体,CASE结构有两种变体。下文将逐一讲述各个选择语句:

IF 结构变体一:

语法:

IF condition THEN{...statements to execute when condition is TRUE...}END IF;

示例:

BEGINIF 1>0 THENDBMS_OUTPUT.PUT_LINE('executed');  END IF;END;

IF 结构变体二:

语法:

IF condition THEN{...statements to execute when condition is TRUE...}ELSE{...statements to execute when condition is FALSE...}END IF;

示例:

BEGINIF 1>2 THENDBMS_OUTPUT.PUT_LINE('The result is true');ELSEDBMS_OUTPUT.PUT_LINE('The result is false');  END IF;END;

IF 结构变体三:

语法:

IF condition1 THEN{...statements to execute when condition1 is TRUE...}ELSIF condition2 THEN{...statements to execute when condition2 is TRUE...}[ELSE{...statements to execute when both condition1 and condition2 are FALSE...}]END IF;

示例:

BEGINIF 1>2 THENDBMS_OUTPUT.PUT_LINE('1>2 branch');ELSIF 1<2 THENDBMS_OUTPUT.PUT_LINE('1<2 branch');  ELSEDBMS_OUTPUT.PUT_LINE('1=2 branch');  END IF;END;

注意:IF 结构变体三中有个巨坑,就是 IF 和 ELSE 之间的分支写法,不是 ELSE IF 也不是 ELSEIF 而是 ELSIF。尽管你写成 ELSE IF 编辑器也有智能提示,但当你执行的时候就会报ORA-06550的错,而且这个错误的描述正常人基本没可能看懂。

CASE 结构变体一

示例:

DECLAREv_grade VARCHAR2(1);BEGINv_grade:='B';  CASE v_gradeWHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('甲');WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('乙');WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('丙');    ELSE DBMS_OUTPUT.PUT_LINE('丁');  END CASE;END;

CASE 结构变体二

示例:

DECLAREv_score NUMBER(3);
BEGINv_score:=78;  CASEWHEN v_score>=80 THEN DBMS_OUTPUT.PUT_LINE('优');WHEN v_score>=70 THEN DBMS_OUTPUT.PUT_LINE('良');WHEN v_score>=60 THEN DBMS_OUTPUT.PUT_LINE('中');ELSE DBMS_OUTPUT.PUT_LINE('差');END CASE;END;

与多分支的 IF 语句相比,CASE 语句更可读、更高效,所以当程序分支较多时,应尽可能的使用 CASE 而不是 IF。CASE 语句的 ELSE 子句是可选的。但如果省略 ELSE 字句,PL/SQL 将为 CASE 语句添加以下隐式的 ELSE 子句:

ELSE RAISE CASE_NOT_FOUND;

换句话说,如果你省略了 ELSE 子句,且 CASE 语句与 WHEN 子句不匹配,PL/SQL 就会引发预定义的异常CASE_NOT_FOUND

3.3、循环结构

PL/SQL 中提供了三种循环结构,分别是LOOPWHILE LOOPFOR LOOP。另外 PL/SQL 还提供了EXIT语句用于退出当前循环。下文将逐一讲述各个循环语句:

LOOP 循环

语法:

LOOP  {...statements...}EXIT [ WHEN boolean_condition ];END LOOP;

示例一:

DECLAREv_counter BINARY_INTEGER := 0;
BEGIN  LOOPv_counter := v_counter + 1;DBMS_OUTPUT.PUT_LINE(v_counter); -- 输出结果:1、2、3、4、5、6、7、8、9IF v_counter >= 9 THENEXIT;    END IF;-- 上面的 IF 语句块还可以由“EXIT WHEN v_counter >= 9;”代替  END LOOP;END;

示例二(嵌套循环):

DECLARE  i BINARY_INTEGER := 0;  j BINARY_INTEGER := 0;
BEGINLOOP    i := i + 1;    j := 0;LOOP      j := j + 1;DBMS_OUTPUT.PUT_LINE('i*j=('||i||'*'||j||')='||i*j);EXIT WHEN j >= 3;END LOOP;EXIT WHEN i >= 4;END LOOP;
END;

示例三(标记循环):

DECLARE  i BINARY_INTEGER := 0;  j BINARY_INTEGER := 0;
BEGIN<<outer_loop>>LOOP    i := i + 1;    j := 0;<<inner_loop>>LOOP      j := j + 1;DBMS_OUTPUT.PUT_LINE('i*j=('||i||'*'||j||')='||i*j);EXIT inner_loop WHEN j >= 3;EXIT outer_loop WHEN i >= 4;END LOOP inner_loop;END LOOP outer_loop;
END;

WHILE LOOP 循环

语法:

WHILE condition
LOOP  {...statements...}END LOOP;

示例:

DECLAREv_score NUMBER(3) := 0;BEGINWHILE v_score < 60 LOOPv_score := v_score + 10;DBMS_OUTPUT.PUT_LINE(v_score); -- 输出结果:10、20、30、40、50、60END LOOP;DBMS_OUTPUT.PUT_LINE('over');END;

FOR LOOP 循环

语法:

FOR loop_counter IN [REVERSE] lowest_number..highest_number
LOOP  {...statements...}END LOOP;

示例一(正向循环):

BEGINFOR i IN 3..7 LOOPDBMS_OUTPUT.PUT_LINE(i); -- 输出结果:3、4、5、6、7END LOOP;END;

示例二(反向循环):

BEGINFOR i IN REVERSE 3..7 LOOPDBMS_OUTPUT.PUT_LINE(i); -- 输出结果:7、6、5、4、3END LOOP;END;

注意:FOR LOOP 循环中的计数器(变量)可以被读取,但不能被修改。另外,在 LOOP 循环的示例中用到的 EXIT 和循环标记,同样可用于 WHILE LOOP 循环和 FOR LOOP 循环中

本文转自帅气的头头博客51CTO博客,原文链接http://blog.51cto.com/12902932/1926164如需转载请自行联系原作者


sshpp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/279570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kindle图书免费下载_如何在Kindle上免费签出图书馆书籍

kindle图书免费下载Tired of paying so much for ebooks? Most libraries these days let you check out eBooks, for free, just like regular books. 厌倦了为电子书支付这么多钱&#xff1f; 如今&#xff0c;大多数图书馆都让您免费阅读电子书&#xff0c;就像普通书籍一样…

第五章 了解你的用户

第五章 了解你的用户逻辑人的争议&#xff1a;要学会把软件开发简单易用象牙塔式的开发&#xff1a;开发团队常年闭封在“高塔”之中&#xff0c;一门心思的做着魔法一般的软件。这些开发者根本就不知道用户会怎么样的使用他们所做的软件。我们应该避免这种象牙塔式的开发&…

总结之:CentOS 6.4系统裁减详解及装载网卡步骤

前言 随着接触Linux的慢慢深入、对Linux也有了一个基本认识了吧&#xff0c;慢慢的接触系统内核、系统配置文件、在了解Linux的系统启动流程后&#xff0c;现在来总结一下一个简单的Linux系统的裁减方法和步骤&#xff0c;一个只有内核文件和几个简单的命令的小Linux系统&am…

android 设备占用_如何查看正在占用Android设备的空间

android 设备占用When you picked up your shiny new Android device, you probably thought “yeah, this has plenty of storage. I’ll never fill it up!” But here you are, some number of months later with a full phone and no clue why. No worries: here’s how yo…

最近沉迷生意经

高度战略抢占顾客心智 速度战略 . 规模不够就谈发展速度&#xff0c;避开自己的劣势&#xff1b; . 发展速度快说明产品好&#xff0c;受欢迎度高; 钱是工具&#xff0c;从钱上解脱 . 不能被钱所困 . 放下钱&#xff0c;才能潇洒地使用钱 第一时间抢占顾客心智 . 核心点就是抢占…

mysql密码正确却提示错误, 不输入密码反而能登录

今天部署阿里云服务器, 发现之前可以连接的mysql服务器突然连接不上了, 密码我确认是正确的,但登录时就是显示密码错误, 很崩溃, 差点气得我就想重装mysql了。 好在经过几番苦寻找到了以下能解决我问题的资料&#xff0c; 成功解决了我的问题&#xff0c; 万分感谢&#xff0c;…

域用户权限|安装软件

如何让普通的域用户有安装软件的权限&#xff1f;现在给客户部署了活动目录&#xff0c;客户要求 普通的域用户也可以自己安装软件。不知道如何设置&#xff0c;希望大家帮帮忙&#xff01;我告诉客户的做法如下&#xff1a;不知道可行性如何&#xff1f; 1、在域中新建一个域账…

c/c++ new delete初探

new delete初探 1&#xff0c;new有2个作用 开辟内存空间。调用构造函数。2&#xff0c;delete也有2个作用 释放内存空间调用析构函数。如果用new开辟一个类的对象的数组&#xff0c;这个类里必须有默认(没有参数的构造函数&#xff0c;或者有默认值的参数的构造函数)的构造函数…

php旧版本windows_Windows的旧版本中如何进行多任务处理?

php旧版本windowsConsidering that DOS was a single-tasking OS and the ties it had with early versions of Windows, just how did earlier versions of Windows manage to accomplish multi-tasking? Today’s SuperUser Q&A post looks at the answers to this ques…

批量提取视频文件信息(文件大小及时长)并统计

随着设备性能提高&#xff0c;视频文件越来越大了。服务器在对外提供视频服务时&#xff0c;需要承担越来越大的存储负担。一般提供1080P的AVC编码视频已满足多数观看需求。&#xff08;1小时视频大约1.3G&#xff09;此文要解决的就是关于已有大量高清视频&#xff08;1小时超…

列出所有K个元素的子集-----2013年1月26日

问题描述:列出一个集合的元素个数为k的所有子集。思路:在字典顺序列出所有子集的基础上判断元素个数就可以了&#xff0c;比较简单。代码如下:1 #include <stdio.h>2 #define MAX 10003 4 int main()5 {6 int n5;7 int set[MAX]{1};8 int index0;9 int …

docker swarm的应用----docker集群的构建

一、docker安装 这里我们安装docker-ce 的18.03版本 yum -y remove docker 删除原有版本 #安装依赖包 [rootDocker ~]# yum -y install yum-utils device-mapper-persistent-data lvm2 #添加docker的CE版本的yum源配置文件 [rootDocker ~]# curl https://download.docker…

微信小程序 fire_如何在Fire TV和Fire TV Stick上侧面加载应用程序

微信小程序 fireAmazon’s Fire TV and Fire TV stick technically runs Android…but you wouldn’t know it from looking. Amazon has a wall of content for its set-top box, and doesn’t want Google (with its own competing platform) to crash the party. But even t…

PS 技巧

1. 钢笔的使用&#xff1a; 扣完一圈以后&#xff0c;按Ctrl回车键&#xff0c;会出现蚂蚁线&#xff0c;然后按CtrlJ 是复制扣出来的图层&#xff0c;右下角的框里会出现一个新图层&#xff0c;注意每个图层前边有一个小框&#xff0c;点一下是出现眼睛就可以显示该图层在中央…

Ibatis - Open quote is expected for attribute {1} associated with an element type '

昨天晚上提交的代码&#xff0c;今天运行起来&#xff0c;始终报错&#xff1a; Open quote is expected for attribute "{1}" associated with an element type id,查了半天&#xff0c;觉得很奇怪。 回滚到昨天的代码&#xff0c;运行正常。经过compare代码&#…

Linux系统运维之路

九月份开始&#xff0c;半年内搞定运维&#xff0c;博客会慢慢的更新&#xff0c;vim编辑器&#xff0c;Nginx配置文件优化 运维基础 运维基础-Linux发展史、安装、基本操作 运维基础-用户和组管理 运维基础-文件权限管理 运维基础-进程管理 运维基础-IO 管道 运维基础-查找压…

设备无法获得谷歌运行怎么办_因此,您刚刚获得了Google主页。 怎么办?

设备无法获得谷歌运行怎么办So you scored a Google Home for Christmas. That’s awesome because this is a killer little smart speaker that can do a lot of different things—in fact, it can be a little overwhelming. The good news is that we’ve got you covered…

IDEA Maven创建多个Module相互依赖

1、前言 在大型企业项目中&#xff0c;系统架构复杂多变&#xff0c;一个项目根本无法支撑起所有业务。为了提高项目扩展性、灵活性、重用性&#xff0c;封装性&#xff0c;将项目分为多个Module是非常必要的。 这里就不说IDEA如何安装了&#xff0c;安装好IDEA后需要修改maven…

速达5000出现计算成本数据溢出的问题

算成本提示某货品成本溢出处理方法&#xff0c;该问题是由于货品成本异常&#xff0c;成本上亿或者负亿造成的&#xff1b; 1.首先通过语句&#xff1a;select * into tmp_goods from l_goods where ABS(aprice)>100000&#xff0c;把成本价格超过10万的货品资料取出&#x…

Win32页上的所有控件属性与方法

Win32页上的所有控件。该页控件是在32位Win系统中的一些基本控件&#xff0c;如果你选择开发CLX程序&#xff0c;则在控件面板上不会显示该页TTabControl属性DisplayRect&#xff1a;只定该控件客户区的一个矩形HotTrack&#xff1a;设置当鼠标经过页标签时&#xff0c;它的字是…