PL / SQL的基本结构

PL / SQL代表Procedural Language / SQL。PL / SQL通过添加过程语言中的构造来扩展SQL,从而产生比SQL更强大的结构语言。PL / SQL中的基本单元是一个。所有PL / SQL程序都由块组成,这些块可以相互嵌套。通常,每个块在程序中执行逻辑操作。块具有以下结构:


 DECLARE/ *声明部分:变量,类型和本地子程序。* /BEGIN/ *可执行部分:过程和SQL语句都在这里。* // *这是块中唯一需要的部分。* /EXCEPTION/ *异常处理部分:错误处理语句在这里。* / END;

只需要可执行部分。其他部分是可选的。PL / SQL程序中允许的唯一SQL语句是SELECT, INSERT, UPDATE,DELETE和其他几个数据操作语句以及一些事务控制。但是,SELECT语句有一个特殊的形式,其中一个元组放在变量中; 稍后会详细介绍。不允许使用CREATE,DROP或ALTER等数据定义语句。可执行部分还包含诸如赋值,分支,循环,过程调用和触发器之类的构造,这些构造如下所述(触发器除外))。PL / SQL不区分大小写。可以使用C样式注释(/ * ... * /)。

要执行PL / SQL程序,我们必须遵循程序文本本身

  • 带有单个点(“ 。 ”)的行,然后
  • 一条带跑步的线;

与Oracle SQL程序一样,我们可以通过在sqlplus中键入PL / SQL程序或将代码放入文件并以我们在Oracle入门中学习的各种方式调用文件来调用PL / SQL程序。

变量和类型


变量和类型信息通过变量在PL / SQL程序和数据库之间传输 。每个变量都有一个与之关联的特定类型。那种类型可以

  • SQL用于数据库列的类型之一
  • PL / SQL中使用的泛型类型,例如NUMBER
  • 声明与某些数据库列的类型相同

最常用的泛型类型是NUMBER。NUMBER类型的变量 可以包含整数或实数。最常用的字符串类型是VARCHAR(),其中 n是字符串的最大长度(以字节为单位)。此长度是必需的,没有默认值。例如,我们可能会声明:

DECLAREprice  NUMBER;myBeer VARCHAR(20);

请注意,PL / SQL允许BOOLEAN变量,即使Oracle不支持BOOLEAN作为数据库列的类型。

PL / SQL中的类型可能很棘手。在许多情况下,PL / SQL变量将用于处理存在于现有关系中的数据。在这种情况下,变量必须与关系列具有相同的类型。如果存在任何类型不匹配,则变量赋值和比较可能无法按预期方式工作。为了安全起见,您应该使用%TYPE运算符,而不是硬编码变量的类型。例如:

DECLAREmyBeer Beers.name%TYPE;
给出了PL / SQL变量myBeer,无论为Beers中的name 列声明了什么类型 。

变量也可以具有包含多个字段的记录类型。声明此类变量的最简单方法是 在关系名称上使用%ROWTYPE。结果是一种记录类型,其中字段与关系的属性具有相同的名称和类型。例如:

DECLAREbeerTuple Beers%ROWTYPE;
使变量beerTuple成为具有字段名称 和制造的记录,假设该关系具有模式Beers(名称,制造商)。

任何变量的初始值,无论其类型如何,都是NULL。我们可以使用“ := ”运算符为变量赋值。赋值可以在声明变量的类型之后立即发生,也可以在程序的可执行部分中的任何位置发生。一个例子:

DECLAREa NUMBER := 3;BEGINa := a + 1;END;.run;

此程序在运行时无效,因为数据库没有任何更改。


PL / SQL中的简单程序最简单的程序形式有一些声明,后跟一个可执行部分,它由一个或多个我们熟悉的SQL语句组成。主要的细微差别是SELECT语句的形式与其SQL形式不同。在SELECT子句之后,我们必须 有一个INTO子句列出变量,一个用于SELECT子句中的每个属性,其中必须放置检索到的元组的组件。

注意我们说“元组”而不是“元组”,因为 PL / SQL中的SELECT语句只有在查询结果包含单个元组时才有效。与嵌入式SQL相关的情况基本上与本文第7.1.5节中讨论的“单行选择”的情况相同。如果查询返回多个元组,则需要使用游标,如下一节所述。这是一个例子:

CREATE TABLE T1(e INTEGER,f INTEGER);DELETE FROM T1;INSERT INTO T1 VALUES(1, 3);INSERT INTO T1 VALUES(2, 4);/* Above is plain SQL; below is the PL/SQL program. */DECLAREa NUMBER;b NUMBER;BEGINSELECT e,f INTO a,b FROM T1 WHERE e>1;INSERT INTO T1 VALUES(b,a);END;.run;

幸运的是,只有一个T1的元组具有大于1的第一个分量,即(2,4)。因此INSERT语句将(4,2)插入到T1中。

PL / SQL中的控制流程


PL / SQL中的控制流程PL / SQL允许您以相当熟悉的方式分支和创建循环。

1.条件控制

一个IF语句看起来象:

IF <condition> THEN <statement_list> ELSE <statement_list> END IF;

该ELSE部分是可选的。如果您想要一个多路分支,请使用:

IF <condition_1> THEN ...ELSIF <condition_2> THEN ...... ...ELSIF <condition_n> THEN ...ELSE ...END IF;

以下是一个示例,稍微修改了上一个,现在我们只在第二个组件为1时才进行插入。如果不是,我们首先向每个组件添加10,然后插入:

DECLAREa NUMBER;b NUMBER;BEGINSELECT e,f INTO a,b FROM T1 WHERE e>1;IF b=1 THENINSERT INTO T1 VALUES(b,a);ELSEINSERT INTO T1 VALUES(b+10,a+10);END IF;END;.run;

2.循环控制

使用以下内容创建循环:

LOOP<loop_body> /* A list of statements. */END LOOP;

<loop_body>中的 至少一个语句应该是 表单的 EXIT语句

EXIT WHEN <condition>;

如果<condition>为true,则循环中断。例如,这里有一种方法将每对(1,1)到(100,100)插入 上述两个例子的T1中:

DECLAREi NUMBER := 1;BEGINLOOPINSERT INTO T1 VALUES(i,i);i := i+1;EXIT WHEN i>100;END LOOP;END;.run;

一些其他有用的循环形成语句是:

     
  WHILE <condition> LOOP<loop_body>END LOOP;FOR <var> IN <start>..<finish> LOOP<loop_body>END LOOP;
  • EXIT本身就是一个无条件的循环中断。如果您愿意,可以在条件内使用它。
  • 加WHILE循环可形成
  • 可以形成 一个简单的FOR循环:
  • 这里,<var>可以是任何变量; 它是for循环的本地,不需要声明。此外,<start>和<finish> 是常量。

游标


游标是通过一些关系的元组运行的变量。这种关系可以是存储表,也可以是某些查询的答案。通过将关系中的每个元组提取到游标中,我们可以编写一个程序来读取和处理每个这样的元组的值。如果存储了关系,我们还可以更新或删除当前光标位置的元组。

下面的示例说明了一个游标循环。它使用我们的示例关系 T1(e,f), 其元组是整数对。程序将删除第一个组件小于第二个组件的每个元组,并将反向元组插入T1。

 1) DECLARE/ *用于保存查询结果的输出变量:* / 2)     a T1.e%TYPE;3)     b T1.f%TYPE;/ *光标声明:* / 4)     CURSOR T1Cursor IS5)         SELECT e, f6)         FROM T17)         WHERE e < f8)         FOR UPDATE;9) BEGIN10)     OPEN T1Cursor;11)     LOOP/ *将上述查询结果的每一行检索到PL / SQL变量中:* / 12)         FETCH T1Cursor INTO a, b;/ *如果没有要获取的行,退出循环:* / 13)         EXIT WHEN T1Cursor%NOTFOUND;/ *删除当前元组:* / 14)         DELETE FROM T1 WHERE CURRENT OF T1Cursor;/ *插入反向元组:* / 15)         INSERT INTO T1 VALUES(b, a);16)     END LOOP;/ *查询使用的免费游标。* / 17)     CLOSE T1Cursor;18) END;19) .20) run;

以下是该计划各行的解释:

  • 第(1)行介绍了声明部分。
  • 第(2)和(3)行声明变量a和b的类型等于关系 T1的属性e和f的类型。虽然我们知道这些类型是INTEGER,但我们明智地确保它们可能具有的任何类型都被复制到PL / SQL变量(与前面的示例相比,我们不那么小心并且声明相应的变量是NUMBER类型)。
  • 第(4)到(8)行定义了光标T1Cursor。它的范围超出SELECT - FROM - WHERE 查询定义的关系。该查询选择T1的元组,其第一个组件小于第二个组件。第(8)行声明游标FOR UPDATE,因为稍后我们将使用此游标在第(14)行修改T1。通常,如果光标不用于修改,则不需要FOR UPDATE。
  • 第(9)行开始程序的可执行部分。
  • 第(10)行打开光标,这是必不可少的步骤。
  • 行(11)到(16)是PL / SQL循环。请注意,这样的循环由LOOP和END LOOP括起来。在循环内我们发现:
    • 在Line(12)上,通过游标获取到局部变量。通常,FETCH语句必须为检索到的元组的每个组件提供变量。由于Lines(5)到(7)的查询产生了对,我们已经正确地提供了两个变量,并且我们知道它们的类型正确。
    • 在线(13),测试环路断开条件。它的含义应该是明确的:当游标的提取无法找到更多的元组时,游标名称后的%NOTFOUND是真的。
    • 在行 (14)上,SQL DELETE语句使用特殊的WHERE条件CURRENT OF T1Cursor删除当前元组。
    • 在行(15)上,一个SQL 反馈元组插入T1的SQL INSERT语句。
  • 第(17)行关闭光标。
  • 第(18)行结束PL / SQL程序。
  • 第(19)行和第(20)行导致程序执行。

存储过程


程序PL / SQL过程的行为与其他编程语言中的过程非常相似。下面是一个PL / SQL过程addtuple1的示例,给定一个整数i,将元组(i,'xxx')插入以下示例关系中:

CREATE TABLE T2 (a INTEGER,b CHAR(10));CREATE PROCEDURE addtuple1(i IN NUMBER) ASBEGININSERT INTO T2 VALUES(i, 'xxx');END addtuple1;.run;

关键字CREATE PROCEDURE后跟过程名称及其参数引入过程。一个选项是 通过OR REPLACE跟随CREATE。这样做的好处是,如果您已经完成了定义,那么您将不会收到错误。另一方面,如果先前的定义是同一个名称的不同过程,则不会发出警告,旧过程将丢失。

可以有任意数量的参数,每个参数后跟一个模式 和一个类型。可能的模式是IN(只读),OUT (只写)和INOUT(读和写)。注意:与PL / SQL变量声明中的类型说明符不同,参数声明中的类型说明符必须不受约束。例如,CHAR(10) 和VARCHAR(20)是非法的; 应该使用CHAR或VARCHAR。参数的实际长度取决于调用过程时传入的相应参数。

参数后面是关键字AS(IS是同义词)。然后是主体,它本质上是一个PL / SQL块。我们在END之后重复了过程的名称,但这是可选的。然而,DECLARE部分应与关键字开始DECLARE。相反,遵循AS,我们有:

... AS<local_var_declarations>BEGIN<procedure_body>END;.run;

将运行在最后运行该语句创建的程序; 它不执行该程序。要执行该过程,请使用另一个PL / SQL语句,其中该过程作为可执行语句调用。例如:

BEGIN addtuple1(99); END;.run;

以下过程还将一个元组插入到T2中,但它将两个组件作为参数:

CREATE PROCEDURE addtuple2(x T2.a%TYPE,y T2.b%TYPE)ASBEGININSERT INTO T2(a, b)VALUES(x, y);END addtuple2;.run;

现在,要向T2添加元组(10,'abc'):

BEGINaddtuple2(10, 'abc');END;.run;

以下说明使用OUT参数:

CREATE TABLE T3 (a INTEGER,b INTEGER);CREATE PROCEDURE addtuple3(a NUMBER, b OUT NUMBER)ASBEGINb := 4;INSERT INTO T3 VALUES(a, b);END;.run;DECLAREv NUMBER;BEGINaddtuple3(10, v);END;.run;

请注意,为声明为OUT或INOUT的参数赋值 会导致写入相应的输入参数。因此,OUT或INOUT参数的输入参数应该是具有“左值”的值,例如上面示例中的v之类的变量。对于OUT / INOUT参数,不应传入常量或文字参数。

我们也可以编写函数而不是程序。在函数声明中,我们按RETURN参数列表和返回值的类型:

CREATE FUNCTION <func_name>(<param_list>)RETURN <return_type> AS ...

在函数定义的主体中,“ RETURN <expression> ;” 退出函数并返回<expression>的值。

要找出您创建的过程和函数,请使用以下SQL查询:

select object_type, object_namefrom user_objectswhere object_type = 'PROCEDURE'or object_type = 'FUNCTION';

删除存储过程/函数:

drop procedure <procedure_name>;drop function <function_name>;

发现错误PL / SQL并不总是告诉您有关编译错误的信息。相反,它会给你一个神秘的信息,例如“使用编译错误创建的过程”。如果您没有立即看到错误,请尝试发出命令

show errors procedure <procedure_name>;

或者,您可以键入SHO ERR(SHOW ERRORS的缩写)以查看最新的编译错误。

请注意,作为错误消息的一部分给出的错误的位置并不总是准确的!


打印变量有时我们可能想要打印PL / SQL局部变量的值。一种“快速而又脏”的方式是将它存储为某种关系的唯一元组,并在PL / SQL语句打印出与SELECT 语句的关系之后。更流行的方法是定义一个绑定变量,这是唯一可以使用print命令打印的类型。绑定变量是必须在PL / SQL语句中以冒号作为前缀的类型,例如:关于触发器一节中讨论的new。

步骤如下:

     VARIABLE <name> <type>
  
  PRINT :<name>;
  1. 我们声明一个绑定变量如下:
  2. 其中类型只能是三件事之一:NUMBER,CHAR或CHAR(n)。
  3. 然后我们可以在后面的PL / SQL语句中为变量赋值,但是我们必须在冒号前面添加冒号。
  4. 最后,我们可以执行一个声明
  5. 在PL / SQL语句之外

这是一个简单的例子,它打印值1。

 
   VARIABLE x NUMBERBEGIN:x := 1;END;.run;PRINT :x;

本文件最初由Yu-May Chang和Jeff Ullman撰写,1997年秋季为CS145; 由Jun Yang于1998年春季修订Jennifer Widom教授的CS145课程; 1998年秋季杰夫乌尔曼的其他材料; 1999年春季杨军进一步修订; 2000年春季Jennifer Widom的小修订。

出处:http://infolab.stanford.edu/~ullman/fcdb/oracle/or-plsql.html

PL / SQL的基本结构相关推荐

  1. PL/SQL Developer 导出表结构和表数据

    导出表结构 打开PL/SQL Developer,选择tables 点击菜单栏Tools,选择Export User Objects 出现下面的窗口 导出后是一个sql文件. 导出表数据 一般情况下可 ...

  2. PL/SQL基础:结构、变量处理——PL/SQL教程(一)

    什么是PL/SQL ​ 许多时候我们会利用结构化查询语言(SQL)来访问和操作关系型数据库.这种语言的特点就是非过程化.也就是说使用的时候不用指明执行的具体方法和途径,即不用关注任何的实现细节.但这种 ...

  3. Oracle数据库之PL/SQL程序基础设计

    一.PL/SQL块结构 前边我们已经介绍了PL/SQL块的结构,再来回顾一下: DECLARE /** 声明部分--定义常量.变量.复杂数据类型.游标.用户自定义异常*/ BEGIN /** 执行部分 ...

  4. oracle if函数变量,Oracle数据库——PL/SQL编程

    PL/SQL块基本结构 declare -- 声明部分 begin -- 执行部分 exception -- 异常处理部分 end; 声明部分:包含变量.常量定义,由 declare 关键字开始,如果 ...

  5. PL/SQL块结构和组成元素

    本篇主要内容如下: 2.1   PL/SQL块 2.2   PL/SQL结构 2.3   标识符 2.4   PL/SQL 变量类型 2.4.1  变量类型 2.4.2  复合类型 2.4.2.1 记 ...

  6. PL/SQL 处理流程

    P249 -P254  oracle8i_9i数据库基础--查看本号百度文库 ***********PL/SQL 简介*************** 1.PL/SQL 是过程语言(Procedural ...

  7. Oracle入门(十四.1)之PL / SQL简介

    一.PL / SQL描述 程序语言扩展到SQL: •允许将基本程序逻辑和控制流与SQL语句组合在一起. •是Oracle专有编程语言. - 它只能用于Oracle数据库或工具. 二.程序语言扩展到SQ ...

  8. PL/SQL编程基本概念

    /* =============================================================================pl/sql编程 =========== ...

  9. [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)...

    [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) 原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之 ...

最新文章

  1. teamcity plugin中读取js和css文件的方法
  2. linux c++ 目录操作,C++文件及文件夹操作整理(代码示例)
  3. 2014新跟踪算法KCF笔记
  4. 【Ubuntu入门到精通系列讲解】常用 Linux 命令的基本使用
  5. Arduino ESP8266编程深入要点
  6. 东莞电子计算机学校,东莞市电子科技学校
  7. win10 hyper-v 虚拟机ping不通宿主机问题
  8. C# ASP.NET MVC 图片上传的多种方式(存储至服务器文件夹,阿里云oss)
  9. Linux 主机超全渗透测试命令汇总
  10. 人工智障学习笔记——机器学习(5)朴素贝叶斯
  11. qt 正则 html,Qt 正则表达式 (一)
  12. vim下中文乱码问题解决办法
  13. php 有几种打印方法,php 5种打印方式及变量类型,
  14. Value-Decomposition Networks For Cooperative Multi-Agent Learning(VDN)
  15. 米思齐(Mixly)图形化系列教程(三)-变量
  16. 【MindSpore易点通机器人-01】你也许见过很多知识问答机器人,但这个有点不一样
  17. Mockplus组件样式库一键解决风格复用
  18. html怎么直接修改,如何编辑运行HTML网页文件(HTML编辑工具使用介绍)
  19. R语言 Holt-Winters法
  20. oracle operation_type,案例:Oracle报错performing DML/DDL operation over object in bin解决办法

热门文章

  1. 关于使用字库-雅黑字体(msyh.ttf )显示中文的一些。。。
  2. u盘linux系统 隐藏文件,怎么样将u盘中隐藏的文件找出来
  3. 精尽 JDK 源码解析 —— 集合(七)TreeSet
  4. 计算机硕士论文参考文献,计算机硕士研究生方面论文参考文献 计算机硕士研究生论文参考文献哪里找...
  5. Container容器
  6. ABP Quartz.NET “最佳“实践-2 执行任务
  7. Eye in hand And eye on hand calibration
  8. CRM(客户关系管理)应用与理论研究综述
  9. Markdown 写作注意事项
  10. unexpected output in sfdisk --version [sfdisk,来自 util-linux 2.23.2]后端盘问题