网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 交易代码 > SQL语法 > 正文

天PLSQL简介

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

【网学网提醒】:网学会员为您提供天PLSQL简介参考,解决您在天PLSQL简介学习中工作中的难题,参考学习。


    目标
    PL/SQL是一项ORACLE的技术它可以让SQL像过程型语言一样工作到今天的结
    束你将
    ??对PL/SQL有一个基本的了解
    ??明白PL/SQL的特点以及它与标准的SQL的区别
    ??知道PL/SQL编写程序的基本原理
    ??可以写简单的PL/SQL程序
    ??知道如何处理在PL/SQL编程中的错误
    ??知道如何在真实的世界中使用PL/SQL
    入门
    从对标准的SQL进行介绍是一种入门PL/SQL或SQL的方法SQL是一种可以让
    关系数据库用户以一种直接的方式来访问数据库的方法你可以使用SQL来对数据库进行
    查询和修改其中的表在你写SQL语句的时候你可以告诉数据库你要做什么而不是如
    何去做优化器会自己决定采用一种最有效的方法来执行你的语句如果你向数据库中发
    送了一系列标准的SQL语句服务将会按语句的先后次序来执行它们
    PL/SQL是ORACLE的过程型语言它由标准的SQL语句和一系列可以让你在不同的
    情况下对SQL语句的执行进行控制的命令组成PL/SQL也可以在运行时捕获错误储如
    LOOP和IFTHENELSE语句让PL/SQL具有了第三代编程语言的能力PL/SQL
    也可以以交互方式写出用户友好型界面会把数值赋给它的变量你可以使用许多种预定
    义的包它们可以将信息显示给用户
    今天的内容主要包括PL/SQL的以下特性
    ??程序员可以定义在语句中使用的变量
    ??程序员可以使用错误控制例程来访止程序的意外中断和退出
    ??程序员可以写交互式程序来接受来自用户的输入
    SQL21日自学通(V1.0)翻译人笨猪
    379
    ??程序员可以将功能划分为不同的逻辑代码块编程的模块化为应用程序开发环境
    提供了更大的灵活性
    ??SQL语句可以并行执行以获得最优的性能
    在PL/SQL中的数据类型
    大多数数据的类型是相似的但是每一种解释器都有自己独特的存储方式和内部过程
    需要在写PL/SQL的语句块时你将会定义变量它们必须是真实的数据类型下边的
    小标题对PL/SQL中可用的变量进行了详细的介绍
    在PL/SQL中也提供了数据类型的子类型例如数据类型NUMBER的子类型叫
    INTEGER你可以在PL/SQL程序中使用子类型来保证它与其它程序如COBOL中数据类
    型的一致尤其是在其它的程序中内嵌的PL/SQL代码时更要如此子类型只是ORACLE
    中数据类型的别名所以它必须遵循与之相关联的数据类型的规则
    注在大多数的SQL解释器中语法的大小写是不敏感的PL/SQL同样允许在它的语句中
    使用大小写它也是大小写不敏感的
    字符串类型
    在PL/SQL中的字符串类型所你所想的一样是一种常见的数据类型定义它允许在
    其中有字母和数字像名字代码描述序列号等都可以包括在字符串中
    CHAR中存储着固定长度的字符串CHAR在最大长度为32767个字节尽管很难想
    象在哪一个表中的字符串会有这么长
    语法
    CHAR(max_length)
    子类型CHARACTER
    VARCHAR2则存储着长度可变的字符串你会经常用VARCHAR2来存储长度可变的
    字符串比如某人的名字VARCHAR2所允许的最大长度为32767个字节
    语法
    VARCHAR2(max_length)
    子类型VARCHAR,STRING
    SQL21日自学通(V1.0)翻译人笨猪
    380
    LONG也可以存储变长的字符串它的最大长度为32760个字节LONG是典型的用
    以存储长文本如备注尽管VARCHAR2也能做同样的工作
    数值数据类型
    NUMBER用以存储在ORACLE数据库中的任何类型的数值
    语法
    NUMBER(max_length)
    你也可以使用下边的语法来指定数据类型的精度
    NUMBER(precision,scale)
    子类型DECDECIMALDOUBLEPRECISIONINTEGERINTNUMERICREAL,
    SMALLINTFLOAT
    PLS_INTEGER定义的整数是可以带有符号的例如负数
    二进制数据类型
    二进制数据类型可以以二进制形式来存储数据如图形或图像这种数据类型包括RAW
    和LONGRAW
    日期数据类型
    DATE是在ORACLE中可以有效存储的数据类型如果你将某一列定义为DATE类型
    你就不能指定它的长度DATE数据类型的长度是默认的ORACLE数据类型是像01-
    OCT-97这样的
    逻辑数据类型
    逻辑数据类型可以存储下列数值TRUEFALSE和NULL与DATE相类似BOOLEAN
    在作为列或变量的类型在定义时也不需要参数
    SQL21日自学通(V1.0)翻译人笨猪
    381
    ROWID
    ROWID是存在于ORACLE数据库的每一个表中的预定义列ROWID以二进制格式
    存储和确定表中的每一列索引就是使用ROWID指向数据的
    PL/SQL块的结构
    PL/SQL是一种块结构语言也就是说PL/SQL的程序可以分成逻辑块来写在一个块
    的内部可以有像数据操作或查询之类的过程下边将会对PL/SQL的块进行详细的讨论
    ??在DECLARE部分包括了定义的变量和其它的对象如常量和指针这一部分在
    PL/SQL块中是可以选择的
    ??PROCDURE部分包括条件语句和SQL语句块可以对它进行控制它是PL/SQL
    的必须部分
    ??EXCEPTION告诉了PL/SQL如何处理指定的错误并按用户的定义进行处理它
    也是PL/SQL的可选择部分
    注块是PL/SQL代码的逻辑单元包括至少一个PROCDURE部分和可以选择的
    DECLARE以及EXCEPTION部分
    这里是PL/SQL块的基本结构
    SYNTAX:
    BEGIN--optional,denotesbeginningofblock
    DECLARE--optional,variabledefinitions
    BEGIN--mandatory,denotesbeginningofproceduresection
    EXCEPTION--optional,denotesbeginningofexceptionsection
    END--mandatory,denotesendingofproceduresection
    END--optional,denotesendingofblock
    请注意必要部分在第二个BEGIN——END对中的它构成了一个过程部分当然
    在它们中间是有语句的如果你使用了第一个BEGIN那么你必须同时使用第二个BEGIN
    反之亦然
    SQL21日自学通(V1.0)翻译人笨猪
    38
    2
    注释
    如果一个程序没有注释会怎样编程语言提供了命令使你可以在你的代码中放放注
    释PL/SQL当然不例外你可以在需要注释的行前加一短线公认的PL/SQL注释形式如
    下多行注释则与C语言的注释方法相同
    语法
    --Thisisaone-linecomment.
    /*Thisisa
    multiple-linecomment.*/
    注PL/SQL可以直接支持数据操作言语DML命令和数据查询然而它不支持数据
    字典语言DDL命令你通常会使用PL/SQL维护在数据库结构中的数据但是并
    不能维护这些结构
    DECLARE部分
    在PL/SQL的DECLARE部分包括了变量常量指针和特殊数据类型的定义作为
    一个PL/SQL程序员你可以在你的代码块中定义所有类型的变量但是你必须要指定数
    据类型而且每一个变量都必须与ORACLE中所定义的数据类型一致变量也要符合
    ORACLE的对象命名标准
    变量声明
    在PL/SQL语句块中变量的数据是可变以在变量声明时必须对它加以定义如有必
    须还要进行初始化工作下例中定义了一组在PL/SQL的DECLARE部分的变量
    DECLARE
    ownerchar(10);
    tablenamechar(30);
    bytesnumber(10);
    todaydate
    分析
    DECLARE部分不能自动运行DECLARE部分以DECLARE语句开头每一个变量
    SQL21日自学通(V1.0)翻译人笨猪
    383
    占一行注意在每一个定义的变量后边都有一个分号
    在DECLARE部分也可以对变量进行初始化工作例如
    DECLARE
    customerchar(30);
    fiscal_yearnumber(2):='97';
    你可以使用=符号来进行初始化工作或者说是赋给它一个初值对于被定义为NOT
    NULL的变量你必须要赋初值
    DECLARE
    customerchar(30);
    fiscal_yearnumber(2)NOTNULL:='97';
    分析
    NOTNULL子句在这里的作用与它在CREATETABLE中所起的作用类似
    常量定义
    定义常量的方法与定义变量相同但是常量的数值是静态的他们不能改变在上个
    例子中fiscal_year可能是常量
    注在每一个变量的定义都必须以分号结束
    指针定义
    指针是PL/SQL中的另一种类型的变量在你通常所认为的变量中保存的是数值而
    指针型变量则指向了查询结果中的某一行数据在查询的结果有多个时为了分析数据你
    需要在每个记录之间进行翻阅在查看PL/SQL块中的查询结果时它使用指针来指向返
    回的每一行下边是一个在PL/SQL语句块中定义指针的例子
    INPUT
    DECLARE
    cursoremployee_cursoris
    select*fromemployees;
    指针与视图类似通过在PROCDURE部分使用LOOP循环你可以翻阅指针这
    SQL21日自学通(V1.0)翻译人笨猪
    384
    项技术曾简要地提到过
    %TYPE属性
    %TYPE可以返回表中给定列的变量属性除了查看在PL/SQL中的数据类型定义代码
    你可以使用%TYPE来保持在你的块中的代码的一致性
    INPUT
    DECLARE
    cursoremployee_cursoris
    selectemp_id,emp_namefromemployees;
    id_numemployees.emp_id%TYPE;
    nam
    eemployees.emp_name%TYPE;
    分析
    在这个例子中表中ID_NUM变量与EMP_ID变量具有相同的数据类型%TYPE所定
    义的变量NAME具有与EMPLOYEES中的emp_name具有相同的数据类型
    %ROWTYPE属性
    变量不仅限于单一的数值如果你所定义的变量与一个指针相关联的话你可以使用
    %ROWTYPE属性来声明变量与保证它与游标所在行的类型相同在ORACLE的词典中
    %ROWTYPE
    INPUT
    DECLARE
    cursoremployee_cursoris
    selectemp_id,emp_namefromemployees;
    employee_recordemployee_cursor%ROWTYPE
    分析
    在上例中定义了一个叫employee_record的变量%ROWTYPE定义了这个变量的使它
    与employee_cursor所在行的数据类型相同这个%ROWTYPE属性定义的变量也称为集合
    变量
    SQL21日自学通(V1.0)翻译人笨猪
    385
    %ROWCOUNT属性
    在PL/SQL中%ROWCOUNT属性可以保证在特定的SQL语句块中的游标行数
    INPUT
    DECLARE
    cursoremployee_cursoris
    selectemp_id,emp_namefromemployees;
    records_processed:=employee_cursor%ROWCOUNT;
    分析
    在上例中变量records_processed将会返回PL/SQL语句所访问的employee_cursor的行
    数
    警告在定义变量的时候要小心以访止它和表的名字相冲突例如如果你定义的变量与
    你的PL/SQL语句块中所访问的表的名字是相同的那么变量的名字会优先于表的名字
    Procdure部分
    PROCDURE部分是PL/SQL语句块中的必须部分在这一部分将会使用变量和用户指
    针来操作数据库中的数据PROCDURE部分是一个块的主要部分它包括条件语句和SQL
    语句
    BEGINEND
    在一个语句块中BEGIN标明了一个过程的开始与此类似END则标明了一个语
    句块的结束下边的例子显示了一个PROCDURE部分的基本结构
    语法
    BEGIN
    openacursor;
    condition1
    statement1
    condition2
    statement2
    SQL21日自学通(V1.0)翻译人笨猪
    386
    condition3
    statement3
    closethecursor
    END
    指针控制命令
    现在你将学习如何在PL/SQL的语句块中定义一个指针你需要知道如何来访问一个
    定义过的指针这一部分诠释了基本的指针控制命令DECLAREOPENFETCH和
    CLOSE
    DECLARE
    在今天的早些时候你已经学习了如何在DELCARE部分定义一个指针DECLARE语
    句包括下列指针控制命令
    OPEN
    现在你已经定义了一个指针但是你应该如何去使用它呢如果你不使用打开这本书
    你无法看到它的内容的同样如果你不使用OPEN命令来打开一个指针你也将无法使用
    它例如
    语法
    BEGIN
    openemployee_cursor;
    statement1;
    statement2;
    .
    END
    SQL21日自学通(V1.0)翻译人笨猪
    387
    FETCH
    FETCH可以从一个指针中取得变量的值这里有两个使用FETCH的例子一个是取
    得一个集合变量另外了个则取得特定的变量
    INPUT
    DECLARE
    cursoremployee_cursoris
    selectemp_id,emp_namefromemployees;
    employee_recordemployee_cursor%ROWTYPE;
    BEGIN
    openemp
    loyee_cursor;
    loop
    fetchemployee_cursorintoemployee_record;
    endloop;
    closeemployee_cursor;
    END
    分析
    上一个例子中将一个指针所指的行的数据赋给了一个名字叫employee_record的变量
    它使用LOOP循环来移动指针当然这个块事实上没有做任何工作
    DECLARE
    cursoremployee_cursoris
    selectemp_id,emp_namefromemployees;
    id_numemployees.emp_id%TYPE;
    nameemployees.emp_name%TYPE;
    BEGIN
    openemployee_cursor;
    loop
    fetchemployee_cursorintoid_num,name;
    endloop;
    closeemployee_cursor;
    SQL21日自学通(V1.0)翻译人笨猪
    388
    END
    分析
    在这个例子中是把当前的指针所指的行的对应数据填入变量id_num和name中这两
    个变量是在DECLARE部分中定义的
    CLOSE
    如果你已经在一个块中结束了对指针的使用时你应该将这个指针关闭与你通常在
    读完一本书以后要将书合上一样你应该使用CLOSE命令来关闭指针
    语法
    BEGIN
    openemployee_cursor;
    statement1;
    statement2;
    .
    .closeemployee_cursor;
    END
    分析
    当关闭一个指针以后查询的结果集就不复存在了如果你想访问结果集中的数据你
    必须重新打开指针才行
    条件语句
    现在我们得到了非常有用的东西来控制我们的SQL语句的运行在PL/SQL中的条件
    语句与大多数第三代编程语言是类似的
    IFTHEN
    在大多数编程中IFTHEN语句可能是得常用的语句了它决定了对于特定的条件
    应当执行哪一部分的操作其结构如下
    语法
    SQL21日自学通(V1.0)翻译人笨猪
    389
    IFcondition1THEN
    statement1;
    ENDIF
    如果你需要对这两种情况进行分别处理那么你可以将语句形式写成下边的样子
    语法
    IFcondition1THEN
    statement1
    ELSE
    statement2
    ENDIF
    如果你需要进行判断的条件多于两个那么语句可以写成下边样子
    语法
    IFcondition1THEN
    statement1
    ELSIFcondition2THEN
    statement2
    ELSE
    statement3
    ENDIF
    分析
    在最后一个例子中如果满足条件1那么就执行语句1如果满足条件2那么就会
    执行语句2否则的话就会执行语句3条件语句也可以嵌于其他语句和LOOP循环中
    LOOPS循环
    LOOPS在PL/SQL的语句块中将不断地执行过程直到指定的条件满足为止一共有三
    种循环
    LOOP本身是一个无限的循环它经常在指针中使用如果你想终止这种循环你必
    须指定在什么时候退出例如在循环中翻阅指针的时候你可以指定当指针处于最后一行
    的时候退出循环见下例
    SQL21日自学通(V1.0)翻译人笨猪
    390
    输入
    BEGIN
    openemployee_cursor
    LOOP
    FETCHemployee_cursorintoemployee_record
    EXITWHENemployee_cursor%NOTFOUND
    statement1
    ENDLOOP
    closeemployee_cursor
    END
    %NOTFOUND是指针的一种属性它表明在当前指针中没有任何数据在上一个例
    子中如果指针没有发现数据就会退出循环假如你在循环中忽略了这条语句循环将会
    一
    直进行下去
    WHILE-LOOP则是在当条定条件满足时执行特定的语句而当条件不在满足时就会从
    循环中退出转而执行下一条语句
    输入
    DECLARE
    cursorpayment_cursoris
    selectcust_id,payment,total_duefrompayment_table
    cust_idpayment_table.cust_id%TYPE
    paymentpayment_table.payment%TYPE
    total_duepayment_table.total_due%TYPE
    BEGIN
    openpayment_cursor
    WHILEpayment    FETCHpayment_cursorintocust_id,payment,total_due
    EXITWHENpayment_cursor%NOTFOUND
    insertintounderpay_table
    values(cust_id,'STILLOWES')
    SQL21日自学通(V1.0)翻译人笨猪
    391
    ENDLOOP
    closepayment_cursor
    分析
    在上一个例子中使用了WHILE-LOOP来对指针进行翻阅并且在当条件
    payment    在上一个例子中你也可以使用FOR-LOOP来限定当前的指针所指定的行的数值处于已
    给定的数值内
    输入
    DECLARE
    cursorpayment_cursoris
    selectcust_id,payment,total_duefrompayment_table
    cust_idpayment_table.cust_id%TYPE
    paymentpayment_table.payment%TYPE
    total_duepayment_table.total_due%TYPE
    BEGIN
    openpayment_cursor
    FORpay_recINpayment_cursorLOOP
    IFpay_rec.payment    insertintounderpay_table
    values(pay_rec.cust_id,'STILLOWES')
    ENDIF
    ENDLOOP
    closepayment_cursor
    END
    分析
    在这个例子中使用了FOR-LOOP翻阅指针它是默认的FETCH下执行该语句被省
    略了而且在这里%NOTFOUND属性也被省略了该属性在FOR-LOOP循环中也是默认
    的所以这个例子与上一个例子的结果将是相同的
    SQL21日自学通(V1.0)翻译人笨猪
    392
    EXCEPTION部分
    在PL/SQL语句块中这一部分是可以选择的如果在这一部分被省略而遇到异常的时
    候该语句块就会终止了由于一些异常在出现时也许不需要将语句块终止所以
    EXCEPTION可以用一定的方式来捕获指定的异常或用户定义的异常异常可以由用户来
    定义尽管许多的异常已经在ORACLE中进行了预定义
    激活EXCEPTION异常
    在语句块中的异常可以由RAISE语句来激活异常可以由程序员进行准确地激活然
    而当数据库产生内部错误时它会被自动激活或由默认的数据库服务来调用
    语法
    BEGIN
    DECLARE
    exception_nameEXCEPTION
    BEGIN
    IFconditionTHEN
    RAISEexception_name
    ENDIF
    EXCEPTION
    WHENexception_nameTHEN
    Statement
    END
    END
    分析
    这个例子给出了对异常进行准确激活的基本方法首先exception_name要在
    EXCEPTION语句中进行了定义在PROCEDURE部分当给定的条件满足时这个异常就
    由RAISE语句激活了然后RAISE语句将会引用EXCEPTION语句中的对应异常部分以
    进行适当的工作
    SQL21日自学通(V1.0)翻译人笨猪
    393
    异常的处理
    在上例中捕获了在EXCEPTION部分中的一个异常在PL/SQL中错误是非常容易捕
    获的在进行了异常处理以后PL/SQL可以在
    错误状态下继续运行或是以下种合理的方
    式来终止
    语法
    EXCEPTION
    WHENexception1THEN
    statement1
    WHENexception2THEN
    statement2
    WHENOTHERSTHEN
    statement3
    分析
    这个例子告诉了你当你有多于一个的异常时应该如何在EXCEPTION部分中进行安
    排在这个例子中的块在运行时有两个预料中的异常exception1和exception2如果在
    该语句中产生了其他的异常就会调用WHENOTHERS它对你的语句块中的其它的错误进
    行了处理
    运行一个PL/SQL语句块
    PL/SQL通常在一个主机的编辑器上创建而它的运行则与常规的SQL脚本文件一样
    PL/SQL在语句块中的每一条语句——从变量的赋值到数据操作命令——使用分号结束
    在SQL的脚本中正斜线/但是在PL/SQL也使用正斜线来表明脚本的结束最为
    容易的运行PL/SQL语句块的方法是使用START命令或简写为STA或@
    你的PL/SQL脚本可能会像下边这样
    语法
    /*Thisfileiscalledproc1.sql*/
    BEGIN
    DECLARE
    ...
    BEGIN
    SQL21日自学通(V1.0)翻译人笨猪
    394
    ...
    statements;
    ...
    EXCEPTION
    ...
    END;
    END;
    /
    你可以像下边这样执行PL/SQL脚本
    SQL>startproc1or
    SQL>staproc1or
    SQL>@proc1
    注PL/SQL脚本语言可以使用START命令或@字符来运行它也可以被其它的PL/SQL
    脚本SHELL脚本或其它的程序调用
    将输入返回给用户
    尤其是在捕获了错误的时候你可以会希望输出信息给用户告诉他出现了什么错误
    你可以转送已有的错误信息你也可以显示你所定制的错误信息对于用户来说这会与错
    误代码更容易理解也许你想的是当在错误产生时让他们与数据库管理员联系而不是给他
    们尽可以准确的信息
    PL/SQL在它的语法部分中并没有提供直接的方式来显示输出但是它可以让你来调
    用一个对该语句块服务的包这个包是由DBMS_OUTPUT来调用的
    EXCEPTION
    WHENzero_divideTHEN
    DBMS_OUTPUT.put_line('ERROR:DIVISORISZERO.SEEYOURDBA.')
    分析
    ZERO_DIVIDE是ORACLE的一个预定义的异常有许多在程序运行中产生的常见的
    错误都被预定义为异常并且可以被默认地激活也就是说你不必在编程的过程中手动将其
    激活
    SQL21日自学通(V1.0)翻译人笨猪
    395
    如果在这个语句块运行的过程中产生的异常用户将会看到
    INPUT
    SQL>@block1
    ERROR:DIVISORISZERO.SEEYOURDBA.
    PL/SQLproceduresuccessfullycompleted.
    是不是这样的错误信息比下边的错误信息更友好
    输入/输出
    SQL>@block1
    begin
    *
    ERRORatline1:
    ORA-01476:divisorisequaltozero
    ORA-06512:atline20
    在PL/SQL中的事务控制
    在第11天中的事务控制中我们已经讨论了事务控制命令COMMITROLLBACK
    SAVEPOINT这些命令可以让程序员在在事务向数据库中进行写操作时加以控制在多数
    时候所进行的操作是需要撤消
    语法
    BEGIN
    DECL
    ARE
    ...
    BEGIN
    statements...
    IFconditionTHEN
    COMMIT;
    ELSE
    ROLLBACK;
    ENDIF;
    SQL21日自学通(V1.0)翻译人笨猪
    396
    ...
    EXCEPTION
    ...
    END;
    END;
    PL/SQL的一个好处就是你可以用自动地执行事务控制命令来代替对大型事务的不断
    监控——这是非常单调和乏味的
    让所有的事在一起工作
    到目前为止我们已经介绍了PL/SQL你已经熟悉了它所支持的数据类型以及PL/SQL
    语句块的主要特性你已经知道了如何定义一个局部变量常量和指针你也已经知道了
    如何在一个PROCDURE部分指针的操作部分和异常部分嵌入SQL语句当指针在使用
    时你应该清楚地知道如何在异常部分捕获它现在你已经可以使用BEGINEND语
    句块来进行了实际工作在今天的结束部分你将会彻底明白PL/SQL语句块之间的相同
    关系
    示例表及数据
    在我们创建的PL/SQL语句块中使用两个表PAYMENT_TABLE确定了一个客户她
    /他的付款是多少应得的总数是多少PAY_STATUS_TABLE最初实际上没有任何数据
    数据将会依据PAYMENT_TABLE中的特定条件插入到PAY_STATUS_TABLE表中
    输入
    SQL>select*frompayment_table;
    输出
    CUSTOMERPAYMENTTOTAL_DUE
    ABC90.50150.99
    AAA79.0079.00
    BBB950.001000.00
    CCC27.5027.50
    DDD350.00500.95
    EEE67.8967.89
    SQL21日自学通(V1.0)翻译人笨猪
    397
    FFF555.55455.55
    GGG122.36122.36
    HHH26.750.00
    输入
    SQL>describepay_status_table
    输出
    NameNull?Type
    CUST_IDNOTNULLCHAR(3)
    STATUSNOTNULLVARCHAR2(15)
    AMT_OWEDNUMBER(8,2)
    AMT_CREDITNUMBER(8,2)
    分析
    DESCRIBE是一个ORACLESQL它可以不通过查询数据字典就可以显示一个表的结
    构它与其它的ORACLESQL*PLUS命令将会在第20天SQL*PLUS中提到
    一个简单的PL/SQL语句块
    这个PL/SQL的脚本内容如下所示
    输入
    setserveroutputon
    BEGIN
    DECLARE
    AmtZeroEXCEPTION;
    cCustIdpayment_table.cust_id%TYPE;
    fPaymentpayment_table.payment%TYPE;
    fTotalDuepayment_table.total_due%TYPE;
    cursorpayment_cursoris
    selectcust_id,payment,total_due
    frompayment_table;
    fOverPaidnumber(8,2);
    fUnderPaidnumber(8,2);
    BEGIN
    SQL21日自学通(V1.0)翻译人笨猪
    398
    openpayment_cursor;
    loop
    fetchpayment_cursorinto
    cCustId,fPayment,fTotalDue;
    exitwhenpayment_cursor%NOTFOUND;
    if(fTotalDue=0)then
    raiseAmtZero;
    endif;
    if(fPayment>fTotalDue)then
    fOverPaid:=fPayment-fTotalDue;
    insertintopay_status_table(cust_id,status,amt_credit)
    values(cCustId,'OverPaid',fOverPaid);
    elsif(fPayment    fUnderPaid:=fTotalDue-fPayment;
    insertintopay_status_table(cust_id,status,amt_owed)
    values(cCustId,'StillOwes',fUnderPaid);
    else
    insertintopay_status_table
    values(cCustId,'PaidinFull',null,null);
    endif;
    endloop;
    closepayment_cursor;
    EXCEPTION
    whenAmtZerothen
    DBMS_OUTPUT.put_line('ERROR:amountisZero.Seeyoursupervis
    or.');
    whenOTHERSthen
    DBMS_OUTPUT.put_line('ERROR:unknownerror.SeetheDBA');
    END;
    END;
    /
    SQL21日自学通(V1.0)翻译人笨猪
    399
    分析
    DECLARE部分定义了六个局部变量与被称为payment_cursor指针一样PROCEDURE
    从第二个BEGIN语句开始并先打开了这个游标并开始循环而FETCH命令则将当前指针
    所指向的记录的内容存入在DECLARE部分定义的变量中当在指针中发现记录以后语
    句会将客户的支付与他应付的总数进行比较根据支付的的数量来计算已付款的人数和未
    付款的人数然后将计算过的数据插入到PAY_STATUS_TABLE表中当循环终止以后
    关闭指针异常用于处理在这一部分可以发生的错误
    现在我们来运行一个这个脚本看一个他的结果
    INPUT:
    SQL>@block1
    OUTPUT:
    Inputtruncatedto1characters
    ERROR:amountisZero.Seeyoursupervisor.
    PL/SQLproceduresuccessfullycompleted.
    现在看来你在应得总数上有一个数值是不正确的你应该修正这个数量然后再运行脚
    本
    输入/输出
    SQL>updatepayment_tablesettotal_due=26.75wherecust_id='HHH';
    1rowupdated.
    SQL>commit;
    Commitcomplete.
    SQL>truncatetablepay_status_table;
    Tabletruncated.
    注在上例中我们清除了pay_status_table中的内容在下一次运行这个语句块时表将会被
    重新写入你也许会想把清除语句也加入到语句块中吧
    输入/输出
    SQL>@block1
    Inputtruncatedto1characters
    PL/SQLproceduresuccessfullycompleted.
    SQL21日自学通(V1.0)翻译人笨猪
    400
    现在你可以对PAY_STATUS_TABLE表执行SELECT语句看一下每一个客户的支付
    情况
    输入/输出
    SQL>select*frompay_status_tableorderbystatus;
    CUSTOMERSTATUSAMT_OWEDAMT_CREDIT
    FFFOverPaid100.00
    AAAPaidinFull
    CCCPaidinFull
    EEEPaidinFull
    GGGPaidinFull
    HHHPaidinFull
    ABCStillOwes60.49
    DDDStillOwes150.95
    BBBStillOwes50.00
    分析
    从PAYMENT_TABLE获得的数据中有一行被插入到了PAY_STATUS_TABLE表中
    如果用户的付款金额比应付金额更多那么差额将会被输入到AMT_CREDIT列中如果
    用户的支付金额少于应付金额那么将会在AMT_OWED中输入一个信息如果客户已经
    全部支付完毕那么这两列中就不会有任何数据
    又一个程序
    在这个例子中使用的表叫PAY_TABLE
    输入
    SQL>descpay_table
    输出
    NameNull?Type
    NAMENOTNULLVARCHAR2(20)
    PAY_TYPENOTNULLVARCHAR2(8)
    PAY_RATENOTNULLNUMBER(8,2)
    EFF_DATENOTNULLDATE
    PREV_PAYNUMBER(8,2)
    先来看一下数据
    SQL21日自学通(V1.0)翻译人笨猪
    401
    输入
    SQL>select*frompay_tableorderbypay_type,pay_ratedesc;
    输出
    NAMEPAY_TYPEPAY_RATEEFF_DATEPREV_PAY
    SANDRASAMUELSHOURLY12.5001-JAN-97
    ROBERTBOBAYHOURLY11.5015-MAY-96
    KEITHJONESHOURLY10.0031-OCT-96
    SUSANWILLIAMSHOURLY9.7501-MAY-97
    CHRISSYZOESSALARY50000.0001-JAN-97
    CLODEEVANSSALARY42150.0001-MAR-97
    JO
    HNSMITHSALARY35000.0015-JUN-96
    KEVINTROLLBERGSALARY27500.0015-JUN-96
    现实情况由于销售情况很好你需要给为你工作的时间超过了六个月的个人增加薪
    金符合条件的钟点工的薪金增加4%而符全条件的雇员的薪金需要增加5%
    今天的日期是
    输入/输出
    SQL>selectsysdatefromdual
    SYSDATE
    20-MAY-97
    在对下边的PL/SQL语句块进行检查之前我们要对PAY_TABLE表进行手工的选择
    以找出都有哪些人需要增加薪金
    输入
    SQL>selectname,pay_type,pay_rate,eff_date,
    2'YES'due
    3frompay_table
    4whereeff_date    5UNIONALL
    6selectname,pay_type,pay_rate,eff_date,
    7'No'due
    8frompay_table
    9whereeff_date>=sysdate-180
    SQL21日自学通(V1.0)翻译人笨猪
    402
    10orderby2,3desc;
    输出
    NAMEPAY_TYPEPAY_RATEEFF_DATEDUE
    SANDRASAMUELSHOURLY12.5001-JAN-97No
    ROBERTBOBAYHOURLY11.5015-MAY-96YES
    KEITHJONESHOURLY10.0031-OCT-96YES
    SUSANWILLIAMSHOURLY9.7501-MAY-97No
    CHRISSYZOESSALARY50000.0001-JAN-97No
    CLODEEVANSSALARY42150.0001-MAR-97No
    JOHNSMITHSALARY35000.0015-JUN-96YES
    KEVINTROLLBERGSALARY27500.0015-JUN-96YES
    DUE列的内容是确定每一个人是否有增加工资的资格下边是PL/SQL的脚本
    输入
    setserveroutputon
    BEGIN
    DECLARE
    UnknownPayTypeexception;
    cursorpay_cursoris
    selectname,pay_type,pay_rate,eff_date,
    sysdate,rowid
    frompay_table;
    IndRecpay_cursor%ROWTYPE;
    cOldDatedate;
    fNewPaynumber(8,2);
    BEGIN
    openpay_cursor;
    loop
    fetchpay_cursorintoIndRec;
    exitwhenpay_cursor%NOTFOUND;
    cOldDate:=sysdate-180;
    if(IndRec.pay_type='SALARY')then
    SQL21日自学通(V1.0)翻译人笨猪
    403
    fNewPay:=IndRec.pay_rate*1.05;
    elsif(IndRec.pay_type='HOURLY')then
    fNewPay:=IndRec.pay_rate*1.04;
    else
    raiseUnknownPayType;
    endif;
    if(IndRec.eff_date    updatepay_table
    setpay_rate=fNewPay,
    prev_pay=IndRec.pay_rate,
    eff_date=IndRec.sysdate
    whererowid=IndRec.rowid;
    commit;
    endif;
    endloop;
    closepay_cursor;
    EXCEPTION
    whenUnknownPayTypethen
    dbms_output.put_line('=======================');
    dbms_output.put_line('ERROR:Abortingprogram.');
    dbms_output.put_line('UnknownPayTypeforName');
    whenothersthen
    dbms_output.put_line('ERRORDuringProcessing.SeetheDBA.');
    END;
    END;
    /
    你是否已经决定了要给这四个雇员增加工资在上边的SELECT语句中有四个人有
    YES标记为什么不呢让我们给所有的这四个人加薪吧你可以通过运行名字叫
    block2.sql的脚本来自动为这四个人进行合理的加薪
    输入/输出
    SQL21日自学通(V1.0)翻译人笨猪
    404
    SQL>@block2
    Inputtruncatedto1characters
    PL/SQLproceduresuccessfullycompleted.
    你可以作一个快速的检查也确定对于每个人的薪金的增加比率是多少
    输入
    SQL>select*frompay_tableorderbypay_type,pay_ratedesc
    输出
    NAMEPAY_T
    YPEPAY_RATEEFF_DATEPREV_PAY
    SANDRASAMUELSHOURLY12.5001-JAN-97
    ROBERTBOBAYHOURLY11.9620-MAY-9711.5
    KEITHJONESHOURLY10.4020-MAY-9710
    SUSANWILLIAMSHOURLY9.7501-MAY-97
    CHRISSYZOESSALARY50000.0001-JAN-97
    CLODEEVANSSALARY42150.0001-MAR-97
    JOHNSMITHSALARY36750.0020-MAY-9735000
    KEVINTROLLBERGSALARY28875.0020-MAY-9727500
    分析
    四个雇员的薪金已经增加了如果将现在的输出和原来的SELECT的输出做比较的话
    你会发现相应的改变当前的薪金率的变化反映和薪金的增加原有的薪金率被插入到了
    PREV_PAY列中而有效日期则被更新为当前的日期没有符合资格的人的情况则没有任
    何变化
    请等一下我们没有看到定义的异常工作的机会你可以向PAY_TABLE表中插入一
    个不合法的记录来对异常部分进行检测
    输入
    SQL>insertintopay_tablevalues
    2('JEFFJENNINGS','WEEKLY',71.50,'01-JAN-97',NULL);
    输出
    1rowcreated.
    输入/输出
    SQL>@block2
    SQL21日自学通(V1.0)翻译人笨猪
    405
    Inputtruncatedto1characters
    =======================
    ERROR:Abortingprogram.
    UnknownPayTypefor:JEFFJENNINGS
    PL/SQLproceduresuccessfullycompleted.
    分析
    错误信息表明JEFFJENNINGS的薪金支付方式不是HOURLY和SALARY这就是异
    常所捕获到的错误信息
    存储过程包和触发机制
    使用PL/SQL你可以创建存储对象来代替日复一日的输入单调和枯燥的代码过程
    是一些可以执行一些特定类型的存储工作的代码块相关的过程可以组合和存储在一起
    这称为包触发机制是一种在其它的事务中使用的数据库对象你也许对一个叫ORDERS
    的表建立了一个触发机制以使得每次当ORDERS表接受到数据时都向HISTORY表中插入
    数据这些对象的基本语法如下
    过程示例
    语法
    PROCEDUREprocedure_nameIS
    variable1datatype;
    ...
    BEGIN
    statement1;
    ...
    EXCEPTION
    when...
    ENDprocedure_name;
    SQL21日自学通(V1.0)翻译人笨猪
    406
    示例包
    语法
    CREATEPACKAGEpackage_nameAS
    PROCEDUREprocedure1(global_variable1datatype,...);
    PROCEDUREprocedure2(global_variable1datatype,...);
    ENDpackage_name;
    CREATEPACKAGEBODYpackage_nameAS
    PROCEDUREprocedure1(global_variable1datatype,...)IS
    BEGIN
    statement1;
    ...
    ENDprocedure1;
    PROCEDUREprocedure2(global_variable1datatype,...)IS
    BEGIN
    statement1;
    ...
    ENDprocedure2;
    ENDpackage_name;
    示例触发机制
    SYNTAX:
    CREATETRIGGERtrigger_name
    AFTERUPDATEOFcolumnONtable_name
    FOREACHROW
    BEGIN
    statement1;
    ...
    END;
    SQL21日自学通(V1.0)翻译人笨猪
    407
    下边的例子在当对PAY_TABLE表的数据进行更新时使用触发机制向一个事务表中插
    入数据事务表如下所示
    INPUT:
    SQL>describetrans_table
    OUTPUT:
    NameNull?Type
    ACTION(10)VARCHAR2
    NAMEVARCHAR2(20)
    PREV_PAYNUMBER(8,2)
    CURR_PAYNUMBER(8,2)
    EFF_DATEDATE
    示例行的数据如下
    输入/
    输出
    SQL>select*frompay_tablewherename='JEFFJENNINGS';
    NAMEPAY_TYPEPAY_RATEEFF_DATEPREV_PAY
    JEFFJENNINGSWEEKLY71.5001-JAN-97
    现在创建一个触发机制
    SQL>CREATETRIGGERpay_trigger
    2AFTERupdateonPAY_TABLE
    3FOREACHROW
    4BEGIN
    5insertintotrans_tablevalues
    6('PAYCHANGE',:new.name,:old.pay_rate,
    7:new.pay_rate,:new.eff_date);
    8END;
    9/
    然后对PAY_TABLE进行更新操作这会导致触发机制的运行
    输入/输出
    SQL>updatepay_table
    2setpay_rate=15.50,
    3eff_date=sysdate
    SQL21日自学通(V1.0)翻译人笨猪
    408
    4wherename='JEFFJENNINGS';
    SQL>select*frompay_tablewherename='JEFFJENNINGS';
    NAMEPAY_TYPEPAY_RATEEFF_DATEPREV_PAY
    JEFFJENNINGSWEEKLY15.5020-MAY-97
    SQL>select*fromtrans_table
    ACTIONNAMEPREV_PAYCURR_PAYEFF_DATE
    PAYCHANGEJEFFJENNINGS71.515.520-MAY-97
    分析
    在PAY_TABE表中的PREV_PAY中是空的但是在TRANS_TABLE中则存在数值
    你是不是糊涂了PAY_TABLE是不需要PREV_PAY的因为每小时的薪金为71.5在这里
    很明显是一个错误的数值由于更新操作是一个事务所以我们把PREV_PAY的数值插入
    到了TRANS_TABLE表中它的目的是为所以的用PAY_TABLE工作的表保存记录
    注如果你工作在类似的网络环境中你也许会注意到PL/SQL与JAVA的存储过程有一
    些类似但是你要注意到他们的不同之处PL/SQL是对标准的SQL的增强它是
    一种过程型语言JAVA比它有更多的先进的特性它允许程序写出比PL/SQL更为复
    杂的程序PL/SQL是基于指定的数据库的增强型SQL而JAVA则在CPU级上工作
    的程序大多数的过程型语言如PL/SQL是针对特定的平台开发的而JAVA则比过
    程型语言更高级它可以在交叉的平台上工作并可以实现标准化
    总结
    PL/SQL对标准的SQL进行了扩展PL/SQL所执行的基本功能与第三代语言相同
    它可以使用局部变量来支持动态代码也就是说块内的数值可以根据用户的输入指定的
    条件和指针的内容的变化而变化PL/SQL使用标准的过程语言来对语句进行控制IF
    THEN和LOOP可以让你按指定的条件搜索你也可以使用LOOP来对指定的指针的内容
    进行翻阅
    在任何程序中都会有各种错误产生PL/SQL通过异常可以让你对产生错误后的行为
    进行控制许多异常是预定义过的如被零除错误异常可以在程序运行时根据指定的条
    件激活并按程序员所定义的方式进行处理
    在今天也介绍一些对PL/SQL的实际应用数据库对象如触发机制存储过程包可
    以自动完成许多功能在今天的例子中我们也应用了一些在前一天中所提到的概念
    SQL21日自学通(V1.0)翻译人笨猪
    409
    问与答
    问在第18天中我是否已经学习了我需要对PL/SQL所掌握的所有内容
    答当然不是像今天的介绍只是提及到了一些表层的一些与SQL相关的东
    西我们
    只是提及了一些SQL的非常明显的特性使你对PL/SQL有一个基本的了解
    问我不用PL/SQL行不行
    答当然你不使用它也是可以的但是如果你不使用它你会为达到相同的目的而不
    得不在第三代编程语言中使用更多的时间和代码如果你没有使用ORACLE那
    么请检查你的解释器以找到与PL/SQL类似的过程方法
    校练场
    1如何在数据库中使用触发机制
    2是否可以将相关的过程存储在一起
    3可以在PL/SQL中使用数据操作语言对不对
    4可以在PL/SQL中使用数据定义语言对不对
    5在PL/SQL的语法中是否支持直接的文本输出
    6给出PL/SQL语句块的三个主要部分
    7请给出与指针控制相关的命令
    练习
    1请定义一个变量使它可以接受的最大数值为99.99
    2请定义一个指针它的内容包括CUSTOMER_TABLE表中的所有CITY为
    INDIANAPOLIS的客户
    3定义一个名字为UnknownCode的异常
    4请写一个语句使得在AMOUNT_TABLE中的AMT当CODE为A时其值为10
    当CODE为B时其值为20当CODE既不是A也不是B时激活一个名字叫
    UnknownCode的异常表中的内容只有一行
    SQL21日自学通(V1.0)翻译人笨猪
    
  • 上一篇资讯: 天堂二技术资料
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师