编程论坛's Archiver

marydan 发表于 2006-2-24 11:50

[分享]PL/SQL的基本特点(初学者请进)

1. PL/SQL的块结构<BR/><BR/>P L / S Q L程序的基本结构是块。所有的P L / S Q L程序都是由块组成的,这些块之间还可以相互<BR/>嵌套。通常,程序中的每一块都实现一个逻辑操作,从而把不同的任务进行分割,由不同的块<BR/>来实现。P L / S Q L的块结构如下所示:<BR/>DECLARE<BR/>/* Declarative section - PL/SQL variables, types, cursors,<BR/>and local subprograms go here. */<BR/>BEGIN<BR/>/* Executable section - procedural and SQL statements go here.<BR/>This is the main section of the block and the only one<BR/>that is required. */<BR/>EXCEPTION<BR/>/* Exception-handling section - error-handling statements go<BR/>here. */<BR/>END;<BR/>在上面演示的块结构中,只有执行部分是必须的,声明部分和异常处理部分都是可选的。<BR/>块结构中的执行部分至少要有一个可执行语句。P L / S Q L块采用的这种分段结构将P L / S Q L程序的<BR/>不同功能各自独立出来。<BR/>P L / S Q L的这种特点是仿效第三代程序设计语言A d a采用的程序结构。在A d a语言中使用的很<BR/>多程序结构包括A d a使用的块结构都适用于P L / S Q L语言。除此之外,在P L / S Q L语言中还可以发<BR/>现A d a语言使用的异常处理方法、过程和函数声明以及包的定义的语法等特征。<BR/><BR/><BR/>2. 错误处理<BR/>P L / S Q L块中的异常处理部分是用来响应应用程序运行中遇到的错误。把程序的主体部分与<BR/>错误处理部分代码相互隔离,这样,程序的结构看起来十分清晰。例如,下面的P L / S Q L块演示<BR/>了将异常发生的时间及将遇到该异常错误的用户名记录在日志表的处理过程。<BR/>节选自在线代码Error.sql<BR/>DECLARE<BR/>v_ErrorCode NUMBER; -- Code for the error<BR/>v_ErrorMsg VARCHAR2(200); -- Message text for the error<BR/>v_CurrentUser VARCHAR2(8); -- Current database user<BR/>v_Information VARCHAR2(100); -- Information about the error<BR/>BEGIN<BR/>/* Code that processes some data here */<BR/>EXCEPTION<BR/>WHEN OTHERS THEN<BR/>-- Assign values to the log variables, using built-in<BR/>-- functions.<BR/>v_ErrorCode := SQLCODE;<BR/>v_ErrorMsg := SQLERRM;<BR/>v_CurrentUser := USER;<BR/>v_Information := 'Error encountered on ' ||<BR/>TO_CHAR(SYSDATE) || ' by database user ' || v_CurrentUser;<BR/>-- Insert the log message into log_table.<BR/>INSERT INTO log_table (code, message, info)<BR/>VALUES (v_ErrorCode, v_ErrorMsg, v_Information);<BR/>END;<BR/>注意上面的例子和许多其他例程都在本书的联机发布信息中。读者如要了解有关详细<BR/>信息,请参阅1 . 3 . 3的内容。<BR/><BR/>3. 变量和类型<BR/>信息在数据库与P L / S Q L程序之间是通过变量进行传递的。所谓变量就是可以由程序读取或<BR/>赋值的存储单元。在上面的例子中, v _ C u r r e n t U s e r, v _ E r r o r C o d e ,和v _ I n f o r m a t i o n都是变量。通<BR/>常,变量是在P L / S Q L块的声明部分定义的。<BR/>每个变量都有一个特定的类型与其关联。变量的类型定义了变量可以存放的信息类别。如<BR/>下所示,P L / S Q L变量可以与数据库列具有同样的类型:<BR/>DECLARE<BR/>v_StudentName VARCHAR2(20);<BR/>v_CurrentDate DATE;<BR/>v_NumberCredits NUMBER(3);<BR/>P L / S Q L变量也可以是其他类型:<BR/>DECLARE<BR/>v_LoopCounter BINARY_INTEGER;<BR/>v_CurrentlyRegistered BOOLEAN;<BR/>除此之外, P L / S Q L还支持用户自定义的数据类型,如记录类型、表类型等。使用用户自定<BR/>义的数据类型可以让你定制程序中使用的数据类型结构。下面是一个用户自定义的数据类型例<BR/>子:<BR/>DECLARE<BR/>TYPE t_StudentRecord IS RECORD (<BR/>FirstName VARCHAR2(10),<BR/>LastName VARCHAR2(10),<BR/>CurrentCredits NUMBER(3)<BR/>);<BR/>v_Student t_StudentRecord;<BR/><BR/>4. 循环结构<BR/>P L / S Q L支持多种循环结构。所谓循环就是指可以重复执行的同一代码段。例如,下面的程<BR/>序块使用一个简单的循环来把数字1~5 0插入到表t e m p _ t a b l e中:<BR/>节选自在线代码SimpleLoop.sql<BR/>DECLARE<BR/>v_LoopCounter BINARY_INTEGER := 1;<BR/>BEGIN<BR/>LOOP<BR/>INSERT INTO temp_table (num_col)<BR/>VALUES (v_LoopCounter);<BR/>v_LoopCounter := v_LoopCounter + 1;<BR/>EXIT WHEN v_LoopCounter &gt; 50;<BR/>END LOOP;<BR/>END;<BR/>P L / S Q L中还提供了一种使用F O R的循环结构,这种循环的结构更简单。如下所示,我们可<BR/>以使用这种F O R循环来实现上面的循环操作:<BR/>节选自在线代码NumricLoop.sql<BR/>BEGIN<BR/>FOR v_LoopCounter IN 1..50 LOOP<BR/>INSERT INTO temp_table (num_col)<BR/>VALUES (v_LoopCounter);<BR/>END LOOP;<BR/>END;<BR/><BR/>5. 游标<BR/>游标是用来处理使用S E L E C T语句从数据库中检索到的多行记录的工具。借助于游标的功能,<BR/>数据库应用程序可以对一组记录逐个进行处理,每次处理一行。例如,下面的程序块可以检索<BR/>到数据库中所有学生的名和姓:<BR/>节选自在线代码CursorLoop.sql<BR/>DECLARE<BR/>v_FirstName VARCHAR2(20);<BR/>v_LastName VARCHAR2(20);<BR/>-- Cursor declaration. This defines the SQL statement to<BR/>-- return the rows.<BR/>CURSOR c_Students IS<BR/>SELECT first_name, last_name<BR/>FROM students;<BR/>BEGIN<BR/>-- Begin cursor processing.<BR/>OPEN c_Students;<BR/>LOOP<BR/>-- Retrieve one row.<BR/>FETCH c_Students INTO v_FirstName, v_LastName;<BR/>-- Exit the loop after all rows have been retrieved.<BR/>EXIT WHEN c_Students%NOTFOUND;<BR/>/* Process data here */<BR/>END LOOP;<BR/>-- End processing.<BR/>CLOSE c_Students;<BR/>END;<BR/><BR/><BR/>

marydan 发表于 2006-2-24 11:58

下面这个游标的使用是我自己总结的,其中可选项都没有写,大家可以在联机文档里查,sql server的那个实例也是联机文档的,oracle的那个,我自己写的,照葫芦画瓢的:)<BR/><BR/><BR/><BR/>sql server中定义cursor:<BR/><BR/>  DECLARE cursor_name  CURSOR <BR/>  FOR select_statement <BR/><BR/><BR/><BR/>oracle中定义cursor:<BR/><BR/>  DECLARE <BR/>     CURSOR  cursor_name IS<BR/>     select_statement;<BR/><BR/><BR/><BR/><BR/>sql server中使用cursor:<BR/><BR/>    OPEN cursor_name<BR/>    FETCH NEXT FROM cursor_name INTO var_name<BR/>    WHILE @@FETCH_STATUS=0<BR/>    print var_name<BR/>    CLOSE cursor_name<BR/>    DEALLOCATE cursor_name<BR/><BR/><BR/>实例:<BR/><BR/>下例显示如何嵌套游标以生成复杂的报表。为每个作者声明内部游标。<BR/><BR/>SET NOCOUNT ON<BR/><BR/>DECLARE <BR/>         @au_id varchar(11),<BR/>         @au_fname varchar(20), <BR/>         @au_lname varchar(40),<BR/>           @message varchar(80),<BR/>         @title varchar(80)<BR/><BR/>PRINT "-------- Utah Authors report --------"<BR/><BR/>DECLARE authors_cursor CURSOR FOR <BR/>SELECT au_id, au_fname, au_lname<BR/>FROM authors<BR/>WHERE state = "UT"<BR/>ORDER BY au_id<BR/><BR/>OPEN authors_cursor<BR/><BR/>FETCH NEXT FROM authors_cursor <BR/>INTO @au_id, @au_fname, @au_lname<BR/><BR/>WHILE @@FETCH_STATUS = 0<BR/>BEGIN<BR/>   PRINT " "<BR/>   SELECT @message = "----- Books by Author: " + <BR/>      @au_fname + " " + @au_lname<BR/><BR/>   PRINT @message<BR/><BR/>   -- Declare an inner cursor based <BR/>     -- on au_id from the outer cursor.<BR/><BR/>   DECLARE titles_cursor CURSOR FOR <BR/>   SELECT t.title<BR/>   FROM titleauthor ta, titles t<BR/>   WHERE ta.title_id = t.title_id AND<BR/>   ta.au_id = @au_id   -- Variable value from the outer cursor<BR/><BR/>   OPEN titles_cursor<BR/>   FETCH NEXT FROM titles_cursor INTO @title<BR/><BR/>   IF @@FETCH_STATUS &lt;&gt; 0 <BR/>      PRINT "         &lt;&lt;No Books&gt;&gt;" <BR/>    <BR/>   WHILE @@FETCH_STATUS = 0<BR/>   BEGIN<BR/>            SELECT @message = "         " + @title<BR/>      PRINT @message<BR/>      FETCH NEXT FROM titles_cursor INTO @title<BR/>      END<BR/><BR/>   CLOSE titles_cursor<BR/>   DEALLOCATE titles_cursor<BR/>      -- Get the next author.<BR/>   FETCH NEXT FROM authors_cursor <BR/>   INTO @au_id, @au_fname, @au_lname<BR/>END<BR/><BR/>CLOSE authors_cursor<BR/>DEALLOCATE authors_cursor<BR/>GO<BR/><BR/>-------- Utah Authors report --------<BR/> ----- Books by Author: Anne Ringer<BR/>         The Gourmet Microwave<BR/>         Is Anger the Enemy?<BR/> ----- Books by Author: Albert Ringer<BR/>         Is Anger the Enemy?<BR/>         Life Without Fear<BR/><BR/><BR/><BR/><BR/>oracle中使用游标的格式:<BR/>   BEGIN<BR/>   OPEN cursor_name;<BR/>   LOOP<BR/>      FETCH cursor_name INTO var_name<BR/>   EXIT WHEN cursor_name%NOTFOUND;<BR/><BR/>   END LOOP;<BR/>   CLOSE cursor_name;<BR/>   END<BR/><BR/>       <BR/><BR/><BR/>oracle的游标实例:<BR/>下例显示如何嵌套游标以生成复杂的报表。为每个作者声明内部游标。<BR/><BR/>declare <BR/>              v_au_id varchar2(11);<BR/>        v_au_fname varchar2(20);<BR/>         v_au_lname varchar2(40);<BR/>         v_title varchar2(80);<BR/>        cursor authors_cursor is<BR/>        select au_id, au_fname, au_lname<BR/>        from authors<BR/>        where state = "UT"<BR/>        order by  au_id;<BR/>begin<BR/>        open authors_cursor;<BR/><BR/>        loop<BR/>        fetch authors_cursor into v_au_id,v_au_fname,v_au_lname;<BR/>        exit when authors_cursor%notfound ;<BR/>        dbms_output.put_line( '----- Books by Author: ' ||v_au_fname || '  ' || v_au_lname);<BR/><BR/>        begin<BR/>                        declare  cursor titles_cursor is <BR/>                     select  t.title<BR/>           from  titleauthor ta, titles t<BR/>           where ta.title_id = t.title_id and<BR/>          ta.au_id = v_au_id;<BR/><BR/>        begin <BR/>        open titles_cursor;<BR/><BR/>        loop<BR/><BR/>        fetch titles_cursor into v_title;<BR/>         exit when titles_cursor%notfound<BR/>        dbms_output.put_line(v_title);<BR/>                                end loop<BR/>        end<BR/>        end<BR/>        end loop<BR/> end
[align=right][color=#000066][此贴子已经被作者于2006-2-24 13:05:47编辑过][/color][/align]

孙大圣 发表于 2006-3-30 16:30

不错[em04]

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.