- 浏览: 148954 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
hk_581:
这个有java实现吗
SSDP协议 -
堕落星辰:
太谢谢了! 找了好久 就你这个例子能显示
Extjs TreeGrid加载数据报未组织好 -
lizhuang:
毫秒数算起来应该比这个好
Java 返回两个时间段的小时数和分钟数 -
love_nana:
这个方法是有问题的吧,2012-05-16 12:30 ~~~ ...
Java 返回两个时间段的小时数和分钟数 -
猫小小质:
找了好几天 就你这个例子能运行起来,爱死你了
Extjs TreeGrid加载数据报未组织好
一、PL/SQL控制结构一览
根据结构定理(structure theorem),任何计算机程序都可以用下图中的基本控制结构来表示。它们可以任意组合来解决问题。
选择结构是用于测试条件的,根据条件的真假,执行一系列语句。一个条件语句可以是任何能够返回布尔值(TRUE或FALSE)的变量或表达式。循环结构能在条件满足的情况下反复执行。序列结构只是简单的按照顺序执行语句。
二、条件控制:IF和CASE语句
有时候,我们需要根据具体的条件来采取不同的对策。IF语句就能让我们按条件来执行语句序列。也就是说,语句序列的执行与否取决于某个给定的条件。有三种IF语句:IF-THEN、IF-THEN-ELSE和IF-THEN-ELSIF。CASE语句是条件判断的精简形式,它能计算条件表达式的值并在多个对应动作中做出选择。
1、IF-THEN语句
IF语句最简单的形式就是把一个条件和一个语句序列用关键字THEN和END IF关联起来:
IF condition THEN
sequence_of_statements
END IF ;
只有在条件值为真的时候语句序列才能被执行。如果条件值为假或是空,IF语句就什么都不做。无论哪种情况,控制权最后还是会被传递到下一个语句,如下例:
IF sales > QUOTA THEN
compute_bonus(empid);
UPDATE payroll
SET pay = pay + bonus
WHERE empno = emp_id;
END IF ;
如果我们把IF语句放到一行,就可以像下面这样编写:
IF x > y THEN high := x; END IF ;
2、IF-THEN-ELSE语句
第二种形式的IF语句使用关键字ELSE添加了一个额外的处理选项,如下:
IF condition THEN
sequence_of_statements1
ELSE
sequence_of_statements2
END IF ;
当条件为假或空时,ELSE子句中的语句序列就会被执行。下例中,第一个UPDATE语句在条件为真的情况下执行,而第二个UPDATE语句在条件为假或为空的情况下才会被执行:
IF trans_type = 'CR' THEN
UPDATE accounts
SET balance = balance + credit
WHERE ...
ELSE
UPDATE accounts
SET balance = balance - debit
WHERE ...
END IF ;
THEN和ELSE子句中也可以包含IF语句。就是说IF语句能够被嵌套使用,如下例所示:
IF trans_type = 'CR' THEN
UPDATE accounts
SET balance = balance + credit
WHERE ...
ELSE
IF new_balance >= minimum_balance THEN
UPDATE accounts
SET balance = balance - debit
WHERE ...
ELSE
RAISE insufficient_funds;
END IF ;
END IF ;
3、IF-THEN-ELSIF语句
有时我们可能需要从几个选项中选择一个,这时我们就需要使用第三种IF语句,添加一个ELSIF关键字提供额外的条件选项,使用方法如下:
IF condition1 THEN
sequence_of_statements1
ELSIF condition2 THEN
sequence_of_statements2
ELSE
sequence_of_statements3
END IF ;
如果第一个条件为假或空,ELSIF子句就会检测另外一个条件。一个IF语句可以有多个ELSIF子句;最后一个ELSE子句是可选的。条件表达式从上而下的计算。只要有满足的条件,与它关联的语句就会执行,然后控制权转到下一个语句。如果所有的条件都为假或是空,ELSE部分的语句就会执行。看一下下面的例子:
BEGIN
...
IF sales > 50000 THEN
bonus := 1500;
ELSIF sales > 35000 THEN
bonus := 500;
ELSE
bonus := 100;
END IF ;
INSERT INTO payroll
VALUES (emp_id, bonus, ...);
END ;
如果sales的值大于50000的话,第一个和第二个条件就为真。然而,bonus只会被赋予1500的值,因为第二个条件并没有执行到。当第一个条件为真的话,它关联的语句就会执行,然后控制权转到INSERT语句。
4、CASE语句
同IF语句一样,CASE语句也是选出一个语句序列来执行。但是,为了选择出合适的语句序列,CASE会使用一个选择器,而不是多个布尔表达式。想要比较IF和CASE语句的话,请看下面对学校成绩的描述信息:
IF grade = 'A' THEN
DBMS_OUTPUT.put_line('Excellent' );
ELSIF grade = 'B' THEN
DBMS_OUTPUT.put_line('Very Good' );
ELSIF grade = 'C' THEN
DBMS_OUTPUT.put_line('Good' );
ELSIF grade = 'D' THEN
DBMS_OUTPUT.put_line('Fair' );
ELSIF grade = 'F' THEN
DBMS_OUTPUT.put_line('Poor' );
ELSE
DBMS_OUTPUT.put_line('No such grade' );
END IF ;
请注意这五个布尔表达式,在每一个实例中,我们只对同一变量的值进行检测,看它的分数值是否等于"A"、"B"、"C"、"D"、"E"或"F"。下面我们用CASE语句重新编写上面的程序:
CASE grade
WHEN 'A' THEN
DBMS_OUTPUT.put_line('Excellent' );
WHEN 'B' THEN
DBMS_OUTPUT.put_line('Very Good' );
WHEN 'C' THEN
DBMS_OUTPUT.put_line('Good' );
WHEN 'D' THEN
DBMS_OUTPUT.put_line('Fair' );
WHEN 'F' THEN
DBMS_OUTPUT.put_line('Poor' );
ELSE
DBMS_OUTPUT.put_line('No such grade' );
END CASE ;
CASE语句的可读性高而且高效,所以,如果可能的话,尽量把IF-THEN-ELEIF都改写成CASE语句。
CASE语句以关键字CASE开头,然后跟上一个选择器,也就是上例中的变量grade。选择器表达式可能是很复杂的。例如,它有可能是一个函数调用。但在通常情况下,它只是一个独立的变量。选择器表达式只被计算一次。它的值可以是除BLOB、BFILE、对象类型、PL/SQL记录、索引表、变长数组或嵌套表之外的任何有效的PL/SQL数据类型。
选择器后面跟着一个或多个WHEN子句,它们是按顺序检测的。选择器的值决定了哪个子句被执行。如果选择器的值等于WHEN子句的表达式值, WHEN子句中的语句序列就会被执行。例如在上面例子中,如果grade等于"C",程序就会输出"Good"。当WHEN子句中的语句序列被执行完毕,控制权会转到下一个语句,而不会再执行后续的WHEN子句。
ELSE子句的工作原理与IF中的类似。上例子中,如果grade的值不与任何一个WHEN子句匹配,ELSE部分就会被执行,"No such grade"就会被输出。ELSE子语是可选的。但是,如果我们省略了ELSE子句,PL/SQL就会为我们添加隐式的ELSE子句:
ELSE RAISE CASE_NOT_FOUND;
如果CASE语句选择了隐式的ELSE子句,PL/SQL就会抛出预定义异常CASE_NOT_FOUND。所以,即使我们省略了ELSE子句,ELSE也会有一个默认的动作。
关键字END CASE是CASE语句结束的标志。这两个关键字必须用空格分开。形式如下:
[<<label_name>>]
CASE selector
WHEN expression1 THEN
sequence_of_statements1;
WHEN expression2 THEN
sequence_of_statements2;
...
WHEN expressionn THEN
sequence_of_statementsn;
[ELSE sequence_of_statementsN+1;]
END CASE [label_name];
同PL/SQL块一样,CASE语句也是可以加标签的。标签是一个未声明的标识符,必须出现在CASE语句的开头,用双尖括号夹起来。标签的名称也可以出现在CASE语句的结尾处,但不是必须的。
CASE语句中的异常会按正常的方法处理,就是说正常的执行语句停止,控制权转到PL/SQL块或子程序的异常控制部分。
- 搜寻式CASE语句
PL/SQL还提供下面搜寻形式的CASE语句:
[<<label_name>>]
CASE
WHEN search_condition1 THEN
sequence_of_statements1;
WHEN search_condition2 THEN
sequence_of_statements2;
...
WHEN search_conditionn THEN
sequence_of_statementsn;
[ELSE sequence_of_statementsN+1;]
END CASE [label_name];
搜寻式CASE语句没有选择器。并且,它的WHEN子句只能包含结果为布尔类型的表达式,产生其它类型结果的表达式是不允许的。示例如下:
CASE
WHEN grade = 'A' THEN
DBMS_OUTPUT.put_line('Excellent' );
WHEN grade = 'B' THEN
DBMS_OUTPUT.put_line('Very Good' );
WHEN grade = 'C' THEN
DBMS_OUTPUT.put_line('Good' );
WHEN grade = 'D' THEN
DBMS_OUTPUT.put_line('Fair' );
WHEN grade = 'F' THEN
DBMS_OUTPUT.put_line('Poor' );
ELSE
DBMS_OUTPUT.put_line('No such grade' );
END CASE ;
搜寻条件是按顺序计算的。每个搜寻条件的布尔值决定了哪个WHEN子句被执行。一旦WHEN子句被执行,控制权就会被交给下一个语句,后续的搜寻条件就不会被考虑。
如果没有找到搜寻条件为TRUE的子句,ELSE子句就会执行。ELSE虽然是可选的,但是,如果省略了ELSE,PL/SQL就会添加隐式的ELSE子句:
ELSE RAISE CASE_NOT_FOUND;
如果执行过程中有异常发生,我们可以在块或子程序的异常控制部分捕获到。
5、PL/SQL条件控制语句使用准则
我们不应该像下面这样使用笨拙的IF语句:
IF new_balance < minimum_balance THEN
overdrawn := TRUE ;
ELSE
overdrawn := FALSE ;
END IF ;
...
IF overdrawn = TRUE THEN
RAISE insufficient_funds;
END IF ;
上面的代码忽视了两个地方。首先,布尔表达式的值可以直接赋给布尔变量。所以我们可以把第一个IF语句简化成下面的语句形式:
overdrawn := new_balance < minimum_balance;
第二,布尔变量本身就是TRUE或FALSE。所以,在IF的条件表达式中直接使用变量本身即可:
IF overdrawn THEN ...
尽可能地使用ELSIF子句代替嵌套IF语句。这样我们的代码就更易读易理解。比较下面两个IF语句:
IF condition1 THEN
statement1;
ELSE
IF condition2 THEN
statement2;
ELSE
IF condition3 THEN
statement3;
END IF ;
END IF ;
END IF ;IF condition1 THEN
statement1;
ELSIF condition2 THEN
statement2;
ELSIF condition3 THEN
statement3;
END IF ;
这两个语句在逻辑上是等价的,但第一个语句看起来有些混乱,而第二个就较为明显。
如果把单独一个表达式与多个值进行比较的话,我们可以使用CASE语句来代替多个ELSIF子句。
三、循环控制:LOOP和EXIT语句
LOOP语句能让我们反复执行一个语句序列。有三种形式的LOOP语句:LOOP,WHILE-LOOP和FOR-LOOP。
1、LOOP
LOOP语句最简单的形式就是把语句序列放到关键字LOOP和END LOOP之间,语法如下:
LOOP
sequence_of_statements;
END LOOP ;
在每一个循环中,语句序列都会被顺序执行,然后再返回循环顶部从头执行。如果不想继续执行,可以使用EXIT语句退出循环。我们可以把一个或多个EXIT语句放到循环里,但不能放到循环外面。有两种形式的EXIT语句:EXIT和EXIT-WHEN。
- EXIT
EXIT语句会强迫循环无条件终止。当遇到EXIT语句时,循环会立即终止,并把控制权交给下面的语句。示例如下:
LOOP
...
IF credit_rating < 3 THEN
...
EXIT ; -- exit loop immediately
END IF ;
END LOOP ;
-- control resumes here
下面再举一个不能在PL/SQL块中使用EXIT语句的例子:
BEGIN
...
IF credit_rating < 3 THEN
...
EXIT ; -- not allowed
END IF ;
END ;
记住,EXIT语句必须放在循环内。如果想在PL/SQL块正常到达程序结尾之前而终止执行,可以使用RETURN语句。
- EXIT-WHEN
EXIT-WHEN语句可以根据给定的条件跳出循环。当遇到EXIT语句时,WHEN子句中的表达式值就会被计算。如果条件满足,循环就会被终止,控制权转到循环语句之后的语句。示例如下:
LOOP
FETCH c1
INTO ...
EXIT WHEN c1%NOTFOUND; -- exit loop if condition is true
...
END LOOP ;
CLOSE c1;
在条件满足之前,循环是不会结束的。所以,循环里的语句必须要改变循环条件的值。上例中,如果FETCH语句返回了一行值,WNEN子句中的条件就为假;如果不能返回结果,WNEN子句中的条件就为真,循环就会结束,控制权转入CLOSE语句。
EXIT-WHEN语句可以替代简单的IF语句,例如,比较下面两段代码:
IF count > 100 THEN
EXIT ;
END IF ;EXIT WHEN count > 100;
这两个语句在逻辑上是等价的,但EXIT-WHEN语句更容易阅读和理解。
- 循环标签
跟PL/SQL块一样,循环也是可以添加标签。标签必须出现在LOOP语句的开端,语法如下:
<<label_name>>
LOOP
sequence_of_statements
END LOOP ;
而在LOOP语句结束部分出现的标签名称是可选的,语法如下:
<<my_loop>>
LOOP
...
END LOOP my_loop;
在LOOP结束部分使用标签名称能够改善可读性。
无论使用哪种EXIT语句形式,都可以结束一个封闭的LOOP块,而不仅仅局限于当前的LOOP块。只要在我们想结束的封闭LOOP块上添加一个标签,然后像下面这样在EXIT语句中使用这个标签就可以了:
<<outer>>
LOOP
...
LOOP
...
EXIT outer WHEN ... -- exit both loops
END LOOP ;
...
END LOOP outer;
2、WHILE-LOOP
WHILE-LOOP语句用关键字LOOP和END LOOP把语句序列封闭起来并与一个布尔条件表达式相关联:
WHILE condition LOOP
sequence_of_statements
END LOOP ;
每次循环之前,程序都是计算布尔表达式的值。如果条件为真,语句序列就会被执行,然后重新返回循环顶部计算布尔表达式的值;如果布尔表达式的值为假或空,控制权就会被交给循环之后的语句。下面看一个例子:
WHILE total <= 25000 LOOP
...
SELECT sal
INTO salary
FROM emp
WHERE x = x; ...
total := total + salary;
END LOOP ;
循环的次数是与条件相关的,而且在循环结束之前是未知的。由于条件是在循环顶部测试的,所以语句序列有可能一次都没有执行。在上面的例子中,如果total的初始值比25000大,那么条件值就是假,循环就会被跳过。
有些语言有LOOP UNTIL或是REPEAT UNTIL这样的结构,在底部测试条件表达式的值。这样,语句序列就会至少执行一次。PL/SQL没有这样的结构,但我们可以变通地使用下面的方法来实现这样的功能:
LOOP
sequence_of_statements
EXIT WHEN boolean_expression;
END LOOP ;
要保证WHILE循环至少执行一次,在条件表达式中使用初始化过的布尔变量,如下例所示:
done := FALSE ;
WHILE NOT done LOOP
sequence_of_statements;
done := boolean_expression;
END LOOP ;
在循环内的语句必须为布尔变量赋上一个新值。否则循环就会无限地执行下去。如下例的两个LOOP语句在逻辑上是等价的:
WHILE TRUE LOOP
...
END LOOP ;LOOP
...
END LOOP ;
3、FOR-LOOP
FOR语句会在指定的整数范围内进行循环操作。循环的内容被关键字FOR和LOOP封闭起来。两个"点"(..)作为范围操作符来使用。语法如下:
FOR counter IN [REVERSE ] lower_bound..higher_bound LOOP
sequence_of_statements
END LOOP ;
当首次进入FOR循环时,循环的范围就会被确定下来,并且不会重新计算。如下例所示,语句序列会执行三次,每执行一次,循环因子就会增加1。
FOR i IN 1 .. 3 LOOP -- assign the values 1,2,3 to i
sequence_of_statements -- executes three times
END LOOP ;
下例演示了如果下界值等于上界值,循环中的语句序列只执行一次:
FOR i IN 3 .. 3 LOOP -- assign the values 3 to i
sequence_of_statements -- executes one time
END LOOP ;
默认情况下,循环总是从下界到上界。不过也可以使用REVERSE关键字,让循环从上界往下界执行。但是要记住,范围的书写格式仍旧是递增顺序的。
FOR i IN REVERSE 1 .. 3 LOOP -- assign the values 3,2,1 to i
sequence_of_statements -- executes three times
END LOOP ;
FOR循环里,循环计数器只能当作常量来引用且不能为它赋值,如下例:
FOR ctr IN 1 .. 10 LOOP
IF NOT finished THEN
INSERT INTO ...
VALUES (ctr); -- legal
factor := ctr * 2; -- legal
ELSE
ctr := 10; -- not allowed
END IF ;
END LOOP ;
- 迭代法
循环范围的边界可以是文字、变量或表达式,但它们都必须是数字。否则PL/SQL会抛出预定义异常VALUE_ERROR。如下例,下界不一定非得是1。但循环计数器只能是每次增加1。
j IN -5 .. 5
k IN REVERSE first..last
step IN 0..TRUNC(high/low) * 2
在PL/SQL内部,它会把边界值赋给一个临时的PLS_INTEGER变量,并在需要的时候把值转换成最接近的整数。PLS_INTEGER的范围是-2**31到2**31之间。所以,如果边界值超过这个范围,我们就会得到一个数字溢出错误:
DECLARE
hi NUMBER := 2 ** 32;
BEGIN
FOR j IN 1 .. hi LOOP -- causes a 鈥檔umeric overflow鈥?error
...
END LOOP ;
END ;
有些语言提供了STEP子句,它能让我们指定循环增量。PL/SQL没有这样的结构,但我们可以在FOR循环内扩大循环计数器的倍数来实现这样的功能。在下面的例子中,我们今天的日期赋给索引表的第一个、第五个和第十五个元素。
DECLARE
TYPE datelist IS TABLE OF DATE
INDEX BY BINARY_INTEGER ;
dates datelist;
k CONSTANT INTEGER := 5; -- set new increment
BEGIN
FOR j IN 1 .. 3 LOOP
dates(j * k) := SYSDATE ; -- multiply loop counter by increment
END LOOP ;
...
END ;
- 动态范围
PL/SQL允许我们在运行时决定循环的范围,如下例所示:
SELECT COUNT(empno)
INTO emp_count
FROM emp;
FOR i IN 1 .. emp_count LOOP
...
END LOOP ;
emp_count在运行时是未知的;SELECT语句在运行时才返回结果值。
如果循环范围中的下界值超过上界值会怎样呢?如下例所示,循环内的语句序列就不会被执行,控制权直接交给下一个语句:
-- limit becomes 1
FOR i IN 2 .. LIMIT LOOP
sequence_of_statements -- executes zero times
END LOOP ;
-- control passes here
- 作用域规则
循环计数器只在循环内部定义,我们不能在循环外引用它。循环退出后,循环计数器就会失效,如下例:
FOR ctr IN 1 .. 10 LOOP
...
END LOOP ;
sum := ctr - 1; -- not allowed
我们不需要显式声明循环计数器,因为它会被隐式地声明为INTEGER类型本地变量。下面的例子中本地声明覆盖了全局声明:
DECLARE
ctr INTEGER ;
BEGIN
...
FOR ctr IN 1 .. 25 LOOP
...
IF ctr > 10 THEN ... -- refers to loop counter
END LOOP ;
END ;
如果想在上例中引用全局变量,我们就得借助标签和点标志,例如:
<<main>>
DECLARE
ctr INTEGER ;
...
BEGIN
...
FOR ctr IN 1 .. 25 LOOP
...
IF main.ctr > 10 THEN -- refers to global variable
...
END IF ;
END LOOP ;
END main;
同样的作用域规则也适用于嵌套FOR循环。如下面的例子,两个循环计数器的名字相同,所以,用从内层循环引用外层循环的循环计数器,就必须使用标签和点标志:
<<outer>>
FOR step IN 1 .. 25 LOOP
FOR step IN 1 .. 10 LOOP
...
IF outer.step > 15 THEN ...
END LOOP ;
END LOOP outer;
- 使用EXIT语句
EXIT语句可以立即结束一个FOR循环。例如,下面的循环语句正常情况应该执行十次,但是,如果FETCH语句取得数据失败,循环就会立即终止,无论它执行过多少次:
FOR j IN 1 .. 10 LOOP
FETCH c1 INTO emp_rec;
EXIT WHEN c1%NOTFOUND;
...
END LOOP ;
在使用EXIT时,我们可以结束任何封闭循环,而不仅仅是当前循环。只要在我们想结束的封闭循环上加上标签,然后在EXIT语句中引用它,就能结束做过标记的FOR循环了,如下例:
<<outer>>
FOR i IN 1 .. 5 LOOP
...
FOR j IN 1 .. 10 LOOP
FETCH c1 INTO emp_rec;
EXIT outer WHEN c1%NOTFOUND; -- exit both FOR loops
...
END LOOP ;
END LOOP outer;
-- control passes here
四、顺序控制:GOTO和NULL语句
与IF和LOOP语句不通,GOTO和NULL语句对PL/SQL编程来说不是必须的。PL/SQL结构中很少用到GOTO语句。有时,它就是用于简化逻辑的。NULL用于改善可读性使条件语句看起来更加清晰。
滥用GOTO能使结构混乱,不易理解和维护(有时被称为意大利面条式代码 - spaghetti code)。所以,GOTO语句的使用一定要有节制。例如,要从一个深嵌套中跳到异常控制块,要用异常抛出而不是使用GOTO语句。
1、GOTO语句
GOTO语句可以无条件跳到一个标签处。标签名称在它所处的作用范围内必须是唯一的。执行的时候,GOTO语句会把控制权交给一个做了标记的语句或块。GOTO语句可以向上或向下跳转,示例如下:
BEGIN
...
GOTO insert_row;
...
<<insert_row>>
INSERT INTO emp VALUES ...
END ;
再看一个向上跳转的例子:
BEGIN
...
<<update_row>>
BEGIN
UPDATE emp SET ...
...
END ;
...
GOTO update_row;
...
END ;
下例中的标签end_loop是不允许的,因为它并没有到达一个处理语句:
DECLARE
done BOOLEAN ;
BEGIN
...
FOR i IN 1 .. 50 LOOP
IF done THEN
GOTO end_loop;
END IF ;
...
<<end_loop>> -- not allowed
END LOOP ; -- not an executable statement
END ;
改进方法很简单,只需添加一个NULL语句即可:
FOR i IN 1 .. 50 LOOP
IF done THEN
GOTO end_loop;
END IF ;
...
<<end_loop>>
NULL ; -- an executable statement
END LOOP ;
GOTO语句还能从当前块跳入一个封闭的块中:
DECLARE
my_ename CHAR (10);
BEGIN
<<get_name>>
SELECT ename
INTO my_ename
FROM emp
WHERE ...
BEGIN
...
GOTO get_name; -- branch to enclosing block
END ;
END ;
- 约束
有些情况下,GOTO语句是不能使用的。特别是想用GOTO语句跳到IF、CASE、LOOP或子块。例如,下面的GOTO语句是不允许的:
BEGIN
...
GOTO update_row; -- can’t branch into IF statement
...
IF valid THEN
...
<<update_row>>
UPDATE emp SET ...
END IF ;
END ;
如下例所示,GOTO不能从一个IF的一个分支跳到另一个分支。同样,也不能从CASE的一个WHEN子句跳到另一个WHEN子句。
BEGIN
...
IF valid THEN
...
GOTO update_row; -- can’t branch into ELSE clause
ELSE
...
<<update_row>>
UPDATE emp SET ...
END IF ;
END ;
下例中演示了GOTO语句不能从封闭的块跳入它的子块:
BEGIN
...
IF status = 'OBSOLETE' THEN
GOTO delete_part; -- can’t branch into sub-block
END IF ;
...
BEGIN
...
<<delete_part>>
DELETE FROM parts WHERE ...
END ;
END ;
同样,GOTO也不能跳出子程序:
DECLARE
...
PROCEDURE compute_bonus(emp_id NUMBER ) IS
BEGIN
...
GOTO update_row; -- can’t branch out of subprogram
END ;
BEGIN
...
<<update_row>>
UPDATE emp SET ...
END ;
最后,GOTO不能从异常控制部分跳入当前块。例如,下面的GOTO语句就是不允许的:
DECLARE
...
pe_ratio REAL ;
BEGIN
...
SELECT price / NVL(earnings, 0)
INTO pe_ratio
FROM ...
<<insert_row>>
INSERT INTO stats
VALUES (pe_ratio, ...);
EXCEPTION
WHEN ZERO_DIVIDE THEN
pe_ratio := 0;
GOTO insert_row; -- can't branch into current block
END ;
但是,GOTO语句可以从一个异常控制程序中跳转到一个封闭块。
2、NULL语句
NULL语句本身什么都不做,只是简单的把控制权交给下一个语句而已。在控制结构中,NULL只是告诉阅读者一个可能会被考虑到的情况,而实际的没有任何动作。下面的例子中演示了忽视未命名异常的操作:
EXCEPTION
WHEN ZERO_DIVIDE THEN
ROLLBACK ;
WHEN VALUE_ERROR THEN
INSERT INTO errors VALUES ...
COMMIT ;
WHEN OTHERS THEN
NULL ;
在IF语句中或其他一些需要至少有一个可执行语句的地方,NULL语句就会被使用来满足这种语法。下例中,NULL语句强调了只有顶级(top-rated)雇员才能得到红利:
IF rating > 90 THEN
compute_bonus(emp_id);
ELSE
NULL ;
END IF ;
在程序设计时,NULL语句很容易创建stub程序。stub程序是一段虚设的子程序,它能让我们推迟函数或过程的实现。因为子程序的可执行部分至少需要一句可执行语句,NULL语句就会派上用场,充当占位语句,如下例:
PROCEDURE
debit_account(acct_id INTEGER
, amount REAL
) IS
BEGIN
NULL
;
END
debit_account;
发表评论
-
PL\SQL用户指南与参考12结束篇 转载
2011-04-22 17:02 966第十二章 PL/SQL应用程序性能调优 一、P ... -
PL\SQL用户指南与参考11 转载
2011-04-22 17:01 1048第十一章 本地动态SQL 一、什么是动态SQL 大多数PL ... -
PL\SQL用户指南与参考10.2 转载
2011-04-22 17:00 9775、对象类型实例:实数 有理数能够表现成两个整数相除的形式, ... -
PL\SQL用户指南与参考10.1 转载
2011-04-22 16:59 759第十章 PL/SQL对象类型 一、抽象的角色 抽象是对一 ... -
PL\SQL用户指南与参考9.2 转载
2011-04-22 16:58 971九、系统包一览 Oracle和各种Oracle工具都提供了系 ... -
PL\SQL用户指南与参考9.1 转载
2011-04-22 16:57 920第九章 PL/SQL包 一、什么是PL/SQL包 ... -
PL\SQL用户指南与参考8 转载
2011-04-22 16:56 961第八章 PL/SQL子程序 一、什么是子程序 ... -
PL\SQL用户指南与参考7.2 转载
2011-04-22 16:55 887八、处理PL/SQL异常 异常抛出时,PL/SQL块或子程序 ... -
PL\SQL用户指南与参考7.1 转载
2011-04-22 16:54 896第七章 控制PL/SQL错误 ... -
PL\SQL用户指南与参考6.3 转载
2011-04-22 16:53 1446八、PL/SQL中的事务处理 ... -
PL\SQL用户指南与参考6.2 转载
2011-04-22 16:52 1607其它的OPEN-FOR语句可以使用不同的查询打开同样的游标变量 ... -
PL\SQL用户指南与参考6.1 转载
2011-04-22 16:49 1082第六章 PL/SQL与Oracle间交互 一、PL/SQ ... -
PL\SQL用户指南与参考5.2.2 转载
2011-04-22 09:53 1066十五、什么是记录 记录就是相关的数据项集中存储在一个单元中, ... -
PL\SQL用户指南与参考5.2.1 转载
2011-04-22 09:52 812六、集合的赋值 集合可以用INSERT、UPDATE、FET ... -
PL\SQL用户指南与参考5.1.2 转载
2011-04-22 09:50 917六、集合的赋值 集合可以用INSERT、UPDATE、FET ... -
PL\SQL用户指南与参考5.1.1 转载
2011-04-22 09:50 1074第五章 PL/SQL集合与记录 ... -
PL\SQL用户指南与参考3 转载
2011-04-20 17:41 1458第三章 PL/SQL数据类型 ... -
PL\SQL用户指南与参考2 转载
2011-04-19 09:25 1134第二章 PL/SQL基础 一、字符集 ... -
PL\SQL用户指南与参考 转载
2011-04-18 17:58 1024第一章 PL/SQL一览 一、理解PL/SQL的主要特性 ...
相关推荐
内容概要:本文详细介绍了利用C++编程和Comsol软件进行锂电池内部枝晶生长过程的多物理场耦合仿真。首先探讨了枝晶生长对浓度场、电场、温度场以及应力场的敏感性,并展示了相应的数学模型和C++代码实现。接着讨论了采用元胞自动机(CA)和格子玻尔兹曼方法(LBM)来模拟枝晶的非均匀生长特性,特别是通过引入偏心正方算法改进了传统CA模型的方向局限性。此外,文中还涉及了如何将多种物理场(如浓度场、电场、温度场、应力场和流场)耦合在一起,形成完整的多物理场仿真系统。最后,作者分享了一些实用的经验和技术细节,比如参数调整技巧、避免常见错误的方法等。 适合人群:从事锂电池研究的专业人士,尤其是对电池安全性和性能优化感兴趣的科研工作者和技术开发者。 使用场景及目标:适用于希望深入了解锂电池内部枝晶生长机制的研究人员,旨在帮助他们构建更加精确的仿真模型,从而更好地理解和解决枝晶引起的电池安全隐患。 其他说明:文章不仅提供了理论分析,还包括具体的代码实例,便于读者动手实践。同时强调了多物理场耦合的重要性,指出这是提高仿真精度的关键因素之一。
# 基于STM32F10x微控制器的综合驱动库 ## 项目简介 本项目是一个基于STM32F10x系列微控制器的综合驱动库,旨在为开发者提供一套全面、易于使用的API,用于快速搭建和配置硬件资源,实现高效、稳定的系统功能。项目包含了STM32F10x系列微控制器的基本驱动和常用外设(如GPIO、SPI、Timer、RTC、ADC、CAN、DMA等)的驱动程序。 ## 项目的主要特性和功能 1. 丰富的外设驱动支持支持GPIO、SPI、Timer、RTC、ADC、CAN、DMA等外设的初始化、配置、读写操作和中断处理。 2. 易于使用的API接口提供统一的API接口,简化外设操作和配置,使开发者能够专注于应用程序逻辑开发。 3. 全面的时钟管理功能支持系统时钟、AHB时钟、APB时钟的生成和配置,以及时钟源的选择和配置。 4. 电源管理功能支持低功耗模式、电源检测和备份寄存器访问,帮助实现节能和延长电池寿命。
# 基于Python和TensorFlow的甲骨文识别系统 ## 项目简介 本项目是一个基于Python和TensorFlow的甲骨文识别系统,旨在利用深度学习技术,尤其是胶囊网络(Capsule Network)来识别甲骨文图像。项目包括数据集准备、模型构建、训练、测试以及评估等关键步骤。 ## 主要特性和功能 1. 数据准备项目提供了数据集的下载、预处理以及分割为训练集、验证集和测试集的功能。 2. 模型构建实现了基于胶囊网络的甲骨文识别模型,包括基本的CapsNet模型、分布式CapsNet模型以及支持多任务学习的CapsNet模型。 3. 训练与测试提供了训练模型、评估模型性能以及可视化训练过程的功能。 4. 性能评估通过测试集评估模型的识别准确率,并提供了测试结果的详细分析。 ## 安装使用步骤 1. 环境准备安装Python和TensorFlow,以及相关的依赖库。 2. 数据准备 下载MNIST或CIFAR数据集
# 基于C++的Arduino BLE设备交互库 ## 项目简介 本项目是一个用于与BLE(蓝牙低能耗)设备交互的Arduino库。它为使用Arduino平台的开发者提供了与BLE设备通信所需的功能,能让开发者更轻松地将BLE设备集成到自己的项目中。 ## 项目的主要特性和功能 1. 初始化BLE设备调用begin()方法,可初始化BLE设备并启动通信。 2. 扫描和连接设备利用scan()方法扫描附近的BLE设备,通过connect()方法连接特定设备。 3. 读取和写入数据使用read()和write()方法,实现从BLE设备读取数据或向其写入数据。 4. 处理事件通过setEventHandler()方法注册回调函数,处理BLE事件,如连接成功、断开连接等。 5. 控制广播和广告使用advertise()和stopAdvertise()方法,控制BLE设备的广播和广告功能。
内容概要:本文详细探讨了利用ANSYS Fluent对增材制造中激光熔覆同轴送粉技术的熔池演变进行模拟的方法。文中介绍了几个关键技术模块,包括高斯旋转体热源、VOF梯度计算、反冲压力和表面张力的UDF(用户自定义函数)实现。通过这些模块,可以精确模拟激光能量输入、熔池内的多相流行为以及各种物理现象如表面张力和反冲压力的作用。此外,文章展示了如何通过调整参数(如激光功率)来优化制造工艺,并提供了具体的代码示例,帮助读者理解和实现这些复杂的物理过程。 适合人群:从事增材制造领域的研究人员和技术人员,尤其是那些希望深入了解激光熔覆同轴送粉技术背后的物理机制并掌握相应模拟工具的人群。 使用场景及目标:适用于需要对增材制造过程中的熔池演变进行深入研究的情景,旨在提高制造质量和效率。具体目标包括但不限于:理解熔池内部的温度场和流场分布规律,评估不同参数对熔池形态的影响,预测可能出现的问题并提出解决方案。 其他说明:文章不仅提供了详细的理论背景介绍,还包括了大量的代码片段和实例解析,使读者能够在实践中更好地应用所学知识。同时,通过对实际案例的讨论,揭示了增材制造过程中的一些常见挑战及其应对策略。
内容概要:本文详细介绍了在COMSOL中构建三维激光切割过程中涉及的热流耦合模型的方法和技术要点。主要内容涵盖水平集物理场用于追踪材料界面变形、流体传热用于描述熔池流动和热传导的相互作用以及层流分析用于处理熔融金属流动。文中提供了具体的MATLAB代码片段,展示了如何设置材料属性、热源加载、熔融金属流动方程、求解器配置及后处理步骤。此外,还讨论了常见问题及其解决方案,如界面过渡区厚度的选择、热源加载的技术细节、表面张力系数的设置、求解器配置的技巧等。 适合人群:从事激光切割工艺研究、仿真建模的研究人员和工程师,尤其是熟悉COMSOL Multiphysics平台的用户。 使用场景及目标:适用于希望深入了解并优化激光切割过程中的热流耦合仿真的研究人员和工程师。主要目标是提高仿真精度,优化切割参数,改善切割质量和效率。 其他说明:文章不仅提供理论指导,还包括大量实用的操作建议和调试技巧,帮助用户更好地理解和应用COMSOL进行复杂物理现象的模拟。
# 基于PythonDjango和Vue的美多电商平台 ## 项目简介 本项目是一个基于PythonDjango和Vue的B2C电商平台,名为美多商城,专注于销售自营商品。系统前台具备商品列表展示、商品详情查看、商品搜索、购物车管理、订单支付、评论功能以及用户中心等核心业务功能系统后台涵盖商品管理、运营管理、用户管理和系统设置等系统管理功能。同时,项目新增了统一异常处理、状态码枚举类等设计,避免使用魔法值,提升了项目的可扩展性和可维护性。 ## 项目的主要特性和功能 ### 前台功能 1. 商品相关提供商品列表展示、商品详情查看以及商品搜索功能,方便用户查找心仪商品。 2. 购物车支持用户添加、管理商品,方便集中结算。 3. 订单支付集成阿里支付,支持订单创建、支付及支付结果处理。 4. 评论用户可对商品进行评价,分享购物体验。 5. 用户中心支持用户注册、登录、密码修改、邮箱验证、地址管理等操作。 ### 后台功能
目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛 目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛~ 目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛 目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛 目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛,目前最火的C/C++和Java蓝桥杯竞赛练习题,充分备战竞赛
# 基于Python和Nonebot框架的HoshinoBot ## 项目简介 HoshinoBot是一个基于Python和Nonebot框架的开源QQ机器人项目,专为公主连结Re:Dive(PCR)和舰队收藏(KanColle)玩家设计。它提供了丰富的功能,旨在增强玩家的游戏体验和社区互动。 ## 项目的主要特性和功能 转蛋模拟支持单抽、十连抽和抽一井功能,模拟游戏中的抽卡体验。 竞技场解法查询提供竞技场解法查询,支持按服务器过滤,并允许用户反馈点赞或点踩。 竞技场结算提醒自动提醒竞技场结算时间,帮助玩家及时参与。 公会战管理提供详细的公会战管理功能,包括成员管理、战斗记录等。 Rank推荐表搬运自动搬运和更新Rank推荐表,帮助玩家选择最佳角色。 常用网址速查提供常用游戏网址的快速查询,方便玩家访问。 官方推特转发自动转发官方推特消息,确保玩家不会错过任何重要更新。 官方四格推送定期推送官方四格漫画,增加玩家的娱乐性。
图书管理小项目完结(完善新增页面)
# 基于Arduino的超声波距离测量系统 ## 项目简介 本项目是一个基于Arduino平台的超声波距离测量系统。系统包含四个超声波传感器(SPS)模块,用于测量与前方不同方向物体的距离,并通过蜂鸣器(Buzz)模块根据距离范围给出不同的反应。 ## 项目的主要特性和功能 1. 超声波传感器(SPS)模块每个模块包括一个超声波传感器和一个蜂鸣器。传感器用于发送超声波并接收回波,通过计算超声波旅行时间来确定与物体的距离。 2. 蜂鸣器(Buzz)模块根据超声波传感器测量的距离,蜂鸣器会给出不同的反应,如延时发声。 3. 主控制器(Arduino)负责控制和管理所有传感器和蜂鸣器模块,通过串行通信接收和发送数据。 4. 任务管理通过主控制器(Arduino)的 loop() 函数持续执行传感器任务(Task),包括测距、数据处理和蜂鸣器反应。 ## 安装使用步骤 1. 硬件连接
题目:基于单片机的幼儿安全监控报警系统设计 主控:STM32F103C8T6 显示:OLED ESP32 红外对管 火焰传感器 烟雾传感器 按键 继电器+水泵 蜂鸣器+led小灯 电源 1.实时监控:系统能够实时监控幼儿的活动区域,了解幼儿的活动情况。 2.入侵检测:系统可以设置安全区域,当有陌生人或动物进入该区域时, 系统会立即发出警报。 3.紧急呼叫:幼儿在遇到紧急情况时,可以通过按下紧急呼叫按钮触发声光报警, 通知教师或监护人。 4.远程监控与通知:教师或监护人可以通过手机远程监控幼儿的安全状况 5.火灾报警:当检测到着火点且烟雾浓度高于阈值,启动声光报警并自动打开水泵抽水进行灭火
内容概要:该MATLAB函数 `robot_calc.m` 实现了一个12维机器人系统的动力学模型计算,主要用于模拟机器人的运动状态。它基于拉格朗日动力学方程,通过质量矩阵 `M`、科里奥利力/向心力矩阵 `N`、约束矩阵 `C` 和输入矩阵 `E` 描述机器人的运动方程。函数接收当前时间和状态向量作为输入,输出状态导数,包括速度和加速度。控制输入通过外部扭矩 `tau` 模拟,数值求解采用伪逆方法确保稳定性。核心步骤包括参数定义、矩阵计算、动力学方程求解和状态导数输出。; 适合人群:具备一定MATLAB编程基础和机器人动力学理论知识的研究人员、工程师和高校学生。; 使用场景及目标:①机器人控制仿真,测试控制算法(如PID、轨迹跟踪)的表现;②运动规划,模拟机器人在给定扭矩下的运动轨迹;③参数优化,通过调整物理参数优化机器人动态性能。; 其他说明:需要注意的是,当前扭矩 `tau` 是硬编码的,实际应用中应替换为控制器的输出。此外,代码中部分参数单位不一致,需确保单位统一。建议改进方面包括动态输入扭矩、添加可视化功能和参数化管理物理参数。
内容概要:本文介绍了一种创新的光伏数据分类预测方法,采用CPO(冠豪猪优化算法)、Transformer和LSTM三种技术相结合的方式。首先进行数据预处理,包括数据加载、标准化和构建数据迭代器。然后详细介绍了模型架构,包括Transformer编码器捕捉特征间的关系,LSTM处理时间序列模式,以及CPO用于优化关键参数如隐藏层节点数、学习率等。实验结果显示,该模型在处理突变数据方面表现出色,特别是在光伏功率预测和异常检测任务中,相比传统LSTM模型有显著提升。 适合人群:具有一定机器学习基础的研究人员和技术开发者,尤其是关注光伏预测和时序数据分析的人士。 使用场景及目标:适用于需要处理复杂时序数据的任务,如光伏功率预测、电力负荷预测、故障诊断等。主要目标是提高预测准确性,尤其是在面对突变数据时的表现。 其他说明:文中提供了详细的代码示例和优化技巧,如数据预处理、模型结构调整、早停机制等。此外,还给出了可视化工具和一些实用的避坑指南,帮助初学者更好地理解和应用这一模型。
内容概要:本文详细介绍了如何利用Matlab对传统人工势场法(APF)进行改进,以解决其在路径规划中存在的局部极小值和目标不可达问题。主要改进措施包括重构斥力函数,在靠近目标时使斥力随目标距离衰减,以及引入模拟退火算法用于跳出局部极小值。文中提供了详细的代码示例,展示了传统APF与改进版APF在不同障碍物布局下的表现对比,验证了改进算法的有效性和鲁棒性。 适合人群:具有一定编程基础并熟悉Matlab环境的研究人员、工程师和技术爱好者。 使用场景及目标:适用于需要进行路径规划的机器人导航系统或其他自动化设备,旨在提高路径规划的成功率和效率,特别是在复杂环境中。 其他说明:文章不仅提供了理论解释,还有具体的代码实现和测试案例,帮助读者更好地理解和应用改进后的APF算法。同时,附带的场力可视化工具使得势场分布更加直观易懂。
内容概要:本文介绍了一款用于将Simulink模型自动转换为PDF文档的脚本工具。该工具能够自动化生成文档,提取模型中各模块的注释并转化为PDF中的说明文字,整合来自Excel的数据并生成表格,分模块分层打印模型图片,最终生成结构清晰的PDF文档。通过递归遍历模型结构,确保文档的章节结构与模型层次保持一致。此外,还包括自动检测未注释模块等功能,极大提高了文档生成效率和准确性。 适合人群:从事Simulink模型开发和维护的工程师,尤其是那些需要频繁编写和更新模型文档的人员。 使用场景及目标:适用于需要快速生成高质量模型文档的场合,如项目交付、技术评审等。主要目标是提高文档编写效率,减少手动操作带来的错误,确保文档与模型的一致性。 其他说明:该工具采用MATLAB和Python混合开发,支持Windows和Linux平台,可通过持续集成(CI/CD)管道自动化运行,进一步提升工作效率。
# 基于Python和树莓派的智能语音闹钟 ## 项目简介 “RaspberryClock”是一个基于树莓派4B的智能语音闹钟项目,使用Python 3.8开发。该项目集成了时间显示、温湿度监测、天气查询、语音提醒以及与图灵机器人对话等功能,旨在为用户提供一个功能丰富且易于使用的智能闹钟解决方案。 ## 项目的主要特性和功能 1. 时间显示实时显示当前时间。 2. 温湿度监测通过DHT11温湿度传感器读取并显示环境温湿度数据。 3. 天气查询通过API查询并显示当前天气信息。 4. 语音提醒支持语音播放和录音功能,用户可以设置语音提醒。 5. 与图灵机器人对话支持语音输入并与图灵机器人进行对话。 6. 用户界面使用Qt库创建友好的用户界面,操作便捷。 ## 安装使用步骤 假设用户已经安装了树莓派和Python环境,以下是项目的安装和使用步骤 1. 下载项目将项目文件下载并解压到树莓派的指定目录。
# 基于PaddleDetection和Docker的深度学习模型部署系统 ## 项目简介 本项目旨在利用Docker容器技术,将PaddleDetection训练的深度学习模型进行快速部署和推理。通过Docker镜像的制作和发布,用户可以在不安装复杂依赖的情况下,轻松实现模型的推理任务。项目特别适用于需要快速部署深度学习模型的场景,如工业检测、图像识别等。 ## 项目的主要特性和功能 1. 模型训练与推理基于PaddleDetection框架训练深度学习模型,支持PPYOLOE等目标检测模型。 2. Docker容器化部署通过Docker将训练好的模型和运行环境打包成镜像,实现一键化部署。 3. 图像推理支持对本地图像进行推理,并将结果保存到指定目录。 4. 镜像发布与测试支持将Docker镜像发布到阿里云等容器镜像服务,并支持从云端拉取镜像进行测试。 ## 安装使用步骤 ### 1. 安装Docker
内容概要:本文介绍了一种将PCA(主成分分析)和BP(反向传播)神经网络相结合的多变量回归预测方法,并提供了完整的Matlab代码实现。主要内容包括数据预处理、PCA降维、BP神经网络构建与训练、预测结果可视化以及性能评估。文中详细展示了如何通过PCA降维减少数据维度并计算原始特征的贡献率,同时利用BP神经网络进行回归预测,最终生成预测效果对比图、误差分布直方图等多种图表,并计算了多个评价指标如R²、MAE、RMSE等。 适用人群:适用于具有一定Matlab基础的数据分析师、机器学习爱好者及科研工作者。 使用场景及目标:①用于处理高维数据集,降低维度的同时保留重要特征;②通过BP神经网络实现高效的回归预测任务;③提供详细的代码注释和可视化工具,帮助用户快速理解和应用。 其他说明:代码中包含了多种实用的功能,如自动保存关键参数到Excel、自动生成多种类型的图表等。此外,还给出了常见的错误避免建议和技术细节说明。
高频电子线路-实验四:二极管平衡调幅电路仿真实验(Multisim仿真)