当前位置: 首页 > news >正文

07-PL/SQL基础(if语句,case语句,循环语句)

本章主要内容:

1.PL/SQL的基本构成:declare,begin,exception,end;

2.结构控制语句:IF语句,CASE语句

3.循环结构:loop循环,for loop循环,while loop循环

PL/SQL的基本构成

特点

  PL/SQL语言是SQL语言的扩展,具有为程序开发而设计的特性,如数据封装、异常处理、面向对象等特性。PL/SQL是嵌入到Oracle服务器和开发工具中的,所以具有很高的执行效率和同Oracle数据库的完美结合。在PL/SQL模块中可以使用查询语句和数据操纵语句(即进行DML操作),这样就可以编写具有数据库事务处理功能的模块。

    至于数据定义(DDL)和数据控制(DCL)命令的处理,需要通过Oracle提供的特殊的DBMS_SQL来进行。PL/SQL还可以用来编写过程、函数、包及数据库触发器。过程和函数也称为子程序,在定义时要给出相应的过程名和函数名。它们可以存储在数据库中成为存储过程和存储函数,并可以由程序来调用,它们在结构上同程序模块类似。

  PL/SQL过程化结构的特点是:可将逻辑上相关的语句组织在一个程序块内;通过嵌入或调用子块,构造功能强大的程序;可将一个复杂的问题分解成为一组便于管理、定义和实现的小块。

块结构和基本语法要求

PL/SQL程序的基本单元是块(BLOCK),块就是实现一定功能的逻辑模块。一个PL/SQL程序由一个或多个块组成。块有固定的结构,也可以嵌套。一个块可以包括三个部分,每个部分由一个关键字标识。

  块中各部分的作用解释如下:

  (1)  DECLARE:声明部分标志。

  (2)  BEGIN:可执行部分标志。

  (3)  EXCEPTION:异常处理部分标志。

  (4)  END;:程序结束标志。

        在以下的训练中,将使用函数DBMS_OUTPUT.PUT_LINE显示输出结果。DBMS_OUTPUTOracle提供的包,该包有如下三个用于输出的函数,用于显示PL/SQL程序模块的输出信息。

  第一种形式:

  DBMS_OUTPUT.PUT(字符串表达式)

  用于输出字符串,但不换行,括号中的参数是要输出的字符串表达式。

  第二种形式:

  DBMS_OUTPUT.PUT_LINE(字符串表达式)

  用于输出一行字符串信息,并换行,括号中的参数是要输出的字符串表达式。

第三种形式:

  DBMS_OUTPUT.NEW_LINE

  用来输出一个换行,没有参数。

  调用函数时,在包名后面用一个点.和函数名分隔,表示隶属关系。

  要使用该方法显示输出数据,在SQL*Plus环境下要先执行一次如下的环境设置命令:

  SET SERVEROUTPUT ON [SIZE n]

  用来打开DBMS_OUTPUT.PUT_LINE函数的屏幕输出功能,系统默认状态是OFF。其中,n表示输出缓冲区的大小。n的范围在20001 000 000之间,默认为2000。如果输出内容较多,需要使用SIZE n来设置较大的输出缓冲区。

        在PL/SQL模块中可以使用查询语句和数据操纵语句(即进行DML操作),所以PL/SQL程序是同SQL语言紧密结合在一起的。在PL/SQL程序中,最常见的是使用SELECT语句从数据库中获取信息,同直接执行SELECT语句不同,在程序中的SELECT语句总是和INTO相配合,INTO后跟用于接收查询结果的变量,形式如下:

  SELECT 列名1,列名2... INTO 变量1,变量2... FROM 表名 WHERE 条件;

注意:接收查询结果的变量类型、顺序和个数同SELECT语句的字段的类型、顺序和个数应该完全一致。并且SELECT语句返回的数据必须是一行,否则将引发系统错误。当程序要接收返回的多行结果时,可以采用后面介绍的游标的方法。

  使用INSERTDELETEUPDATE的语法没有变化,但在程序中要注意判断语句执行的状态,并使用COMMITROLLBACK进行事务处理。

  以下训练包含了按照标准结构书写的一个包含SELECT语句的PL/SQL程序示例。

训练1】  查询雇员编号为7788的雇员姓名和工资。

        步骤1:用SCOTT账户登录SQL*Plus。步骤2:在输入区输入以下程序:/*这是一个简单的示例程序*/SET SERVEROUTPUT ONDECLARE--定义部分标识v_name  VARCHAR2(10);	--定义字符串变量v_namev_sal   NUMBER(5);	--定义数值变量v_salBEGIN			--可执行部分标识SELECT	 ename,sal INTO v_name,v_sal FROM	emp WHERE empno=7788; 			--在程序中插入的SQL语句DBMS_OUTPUT.PUT_LINE('7788号雇员是:'||v_name||',工资为:'||to_char(v_sal));--输出雇员名和工资END;								--结束标识步骤3:按执行按钮或F5快捷键执行程序。输出的结果是:7788号雇员是:SCOTT,工资为:3000PL/SQL 过程已成功完成。

        以上程序的作用是,查询雇员编号为7788的雇员姓名和工资,然后显示输出。这种方法同直接在SQL环境下执行SELECT语句显示雇员的姓名和工资比较,程序变得更复杂。那么两者究竟有什么区别呢?SQL查询的方法,只限于SQL环境,并且输出的格式基本上是固定的。而程序通过把数据取到变量中,可以进行复杂的处理,完成SQL语句不能实现的功能,并通过多种方式输出。

--是注释符号,后边是程序的注释部分。该部分不编译执行,所以在输入程序时可以省略。/*......*/中间也是注释部分,同--注释方法不同,它可以跨越多行进行注释。

  PL/SQL程序的可执行语句、SQL语句和END结束标识都要以分号结束。

数据类型

变量的基本数据类型同SQL部分的字段数据类型相一致,但是也有不同,如表所示。

变量的数据类型

 数据类型说明

NUMBERVARCHAR2是最常用的数据类型。

  VARCHAR2是可变长度的字符串,定义时指明最大长度,存储数据的长度是在最大长度的范围自动调节的,数据前后的空格,Oracle 9i会自动将其删去。

  NUMBER型可以定义数值的总长度和小数位,如NUMBER(10,3)表示定义一个宽度为10、小数位为3的数值。整个宽度减去小数部分的宽度为整数部分的宽度,所以整数部分的宽度为7

CHAR数据类型为固定长度的字符串,定义时要指明宽度,如不指明,默认宽度为1。定长字符串在显示输出时,有对齐的效果。

     DATE类型用于存储日期数据,内部使用7个字节。其中包括年、月、日、小时、分钟和秒数。默认的格式为DD-MON-YY,如:07-8-03表示200387日。

  BOOLEAN为布尔型,用于存储逻辑值,可用于PL/SQL的控制结构。

  LOB数据类型可以存储视频、音频或图片,支持随机访问,存储的数据可以位于数据库内或数据库外,具体有四种类型:BFILEBLOBCLOBNCLOB。但是操纵大对象需要使用Oracle提供的DBMS_LOB包。

变量定义

  1.变量定义

  变量的作用是用来存储数据,可以在过程语句中使用。变量在声明部分可以进行初始化,即赋予初值。变量在定义的同时也可以将其说明成常量并赋予固定的值。变量的命名规则是:以字母开头,后跟其他的字符序列,字符序列中可以包含字母、数值、下划线等符号,最大长度为30个字符,不区分大小写。不能使用Oracle的保留字作为变量名。变量名不要和在程序中引用的字段名相重,如果相重,变量名会被当作列名来使用。

变量的作用范围是在定义此变量的程序范围内,如果程序中包含子块,则变量在子块中也有效。但在子块中定义的变量,仅在定义变量的子块中有效,在主程序中无效。

  变量定义的方法是:

  变量名 [CONSTANT] 类型标识符 [NOT NULL][:=|DEFAULT ];

  关键字CONSTANT用来说明定义的变量是常量,如果是常量,必须有赋值部分进行赋值。

  关键值NOT NULL用来说明变量不能为空。

∶=DEFAULT用来为变量赋初值。

  变量可以在程序中使用赋值语句重新赋值。通过输出语句可以查看变量的值。

  在程序中为变量赋值的方法是:

  变量名:=值 或 PL/SQL 表达式;

  以下是有关变量定义和赋值的练习。

训练1】  变量的定义和初始化。

输入和运行以下程序:SET SERVEROUTPUT ON DECLARE		--声明部分标识v_job		VARCHAR2(9);v_count	BINARY_INTEGER DEFAULT 0;v_total_sal	NUMBER(9,2) := 0;v_date		DATE := SYSDATE + 7;c_tax_rate	CONSTANT NUMBER(3,2) := 8.25;v_valid		BOOLEAN NOT NULL := TRUE;BEGINv_job:='MANAGER';		--在程序中赋值DBMS_OUTPUT.PUT_LINE(v_job);	--输出变量v_job的值DBMS_OUTPUT.PUT_LINE(v_count);--输出变量v_count的值DBMS_OUTPUT.PUT_LINE(v_date);	--输出变量v_date的值DBMS_OUTPUT.PUT_LINE(c_tax_rate);	--输出变量c_tax_rate的值END;

执行结果:

  MANAGER

  0

  18-4-03

  8.25

  PL/SQL 过程已成功完成。

  说明:本训练共定义了6个变量,分别用:=赋值运算符或DEFAULT 关键字对变量进行了初始化或赋值。其中:c_tax_rate为常量,在数据类型前加了 CONSTANT 关键字;v_valid变量在赋值运算符前面加了关键字NOT NULL,强制不能为空。如果变量是布尔型,它的值只能是TRUEFALSENULL。本练习中的变量v_valid布尔变量的值只能取TRUEFALSE

  2.根据表的字段定义变量

  变量的声明还可以根据数据库表的字段进行定义或根据已经定义的变量进行定义。方法是在表的字段名或已经定义的变量名后加 %TYPE,将其当作数据类型。定义字段变量的方法如下:

  变量名 表名.字段名%TYPE;

  【训练2】  根据表的字段定义变量。

输入并执行以下程序:SET SERVEROUTPUT ON DECLAREv_ename	emp.ename%TYPE;--根据字段定义变量
BEGINSELECT	enameINTO		v_enameFROM		empWHERE	empno = 7788;DBMS_OUTPUT.PUT_LINE(v_ename);	--输出变量的值END;执行结果:SCOTTPL/SQL 过程已成功完成。

说明:变量v_ename是根据表empename字段定义的,两者的数据类型总是一致的。

  如果我们根据数据库的字段定义了某一变量,后来数据库的字段数据类型又进行了修改,那么程序中的该变量的定义也自动使用新的数据类型。使用该种变量定义方法,变量的数据类型和大小是在编译执行时决定的,这为书写和维护程序提供了很大的便利。

3.结合变量的定义和使用

  我们还可以定义SQL*Plus环境下使用的变量,称为结合变量。结合变量也可以在程序中使用,该变量是在整个SQL*Plus环境下有效的变量,在退出SQL*Plus之前始终有效,所以可以使用该变量在不同的程序之间传递信息。结合变量不是由程序定义的,而是使用系统命令VARIABLE定义的。在SQL*Plus环境下显示该变量要用系统的PRINT命令。

  在SQL*Plus环境下定义结合变量的方法如下:

  VARIABLE  变量名 数据类型

训练3】  定义并使用结合变量。

步骤1:输入和执行下列命令,定义结合变量g_ename:VARIABLE  g_ename VARCHAR2(100) 步骤2:输入和执行下列程序:SET SERVEROUTPUT ON BEGIN:g_ename:=g_ename|| 'Hello~ ';		--在程序中使用结合变量DBMS_OUTPUT.PUT_LINE(:g_ename);	--输出结合变量的值END;
输出结果:Hello~PL/SQL 过程已成功完成。步骤3:重新执行程序。输出结果:Hello~ Hello~PL/SQL 过程已成功完成。

步骤4:程序结束后用命令显示结合变量的内容:

    PRINT g_ename

  输出结果:

  G_ENAME

  -----------------------------------------------

  Hello~ Hello~  

  说明:g_ename为结合变量,可以在程序中引用或赋值,引用时在结合变量前面要加上。在程序结束后该变量的值仍然存在,其他程序可以继续引用。

4.记录变量的定义

  还可以根据表或视图的一个记录中的所有字段定义变量,称为记录变量。记录变量包含若干个字段,在结构上同表的一个记录相同,定义方法是在表名后跟%ROWTYPE。记录变量的字段名就是表的字段名,数据类型也一致。

  记录变量的定义方法是:

  记录变量名 表名%ROWTYPE

  获得记录变量的字段的方法是:记录变量名.字段名,如emp_record.ename

  如下练习中定义并使用了记录变量。

训练4】  根据表定义记录变量。

输入并执行如下程序:SET SERVEROUTPUT ON DECLAREemp_record		emp%ROWTYPE;--定义记录变量BEGINSELECT * INTO	emp_recordFROM			empWHERE		mpno = 7788;--取出一条记录DBMS_OUTPUT.PUT_LINE(emp_record.ename);	--输出记录变量的某个字段 END;
执行结果为:SCOTTPL/SQL 过程已成功完成。 

说明:在以上的练习中定义了记录变量emp_record,它是根据表emp的全部字段定义的。SELECT语句将编号为7788的雇员的全部字段对应地存入该记录变量,最后输出记录变量的雇员名称字段emp_record.ename的内容。如果要获得其他字段的内容,比如要获得编号为7788的雇员的工资,可以通过变量emp_record.sal获得,依此类推。

5TABLE类型变量

  在PL/SQL中可以定义TABLE类型的变量。 TABLE数据类型用来存储可变长度的一维数组数据,即数组中的数据动态地增长。要定义TABLE变量,需要先定义TABLE数据类型。通过使用下标来引用TABLE变量的元素。

  TABLE数据类型的定义形式如下:

  TYPE 类型名 IS TABLE OF 数据类型[NOT NULL] INDEX BY BINARY_INTEGER;

  此数据类型自动带有BINARY_INTEGER型的索引。

训练5】  定义和使用TABLE变量:

SET SERVEROUTPUT ON DECLARETYPE type_table IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER;  --类型说明v_t	  type_table;     --定义TABLE变量BEGINv_t(1):='MONDAY';v_t(2):='TUESDAY';v_t(3):='WEDNESDAY';v_t(4):='THURSDAY';v_t(5):='FRIDAY';DBMS_OUTPUT.PUT_LINE(v_t(3));  --输出变量的内容END;执行结果为:WEDNESDAYPL/SQL 过程已成功完成。

说明:本例定义了长度为10的字符型TABLE变量,通过赋值语句为前五个元素赋值,最后输出第三个元素。

运算符和函数

  PL/SQL常见的运算符和函数包括以下方面(这里只做简单的总结,可参见SQL部分的例子)

  * 算术运算:加(+)、减(-)、乘(*)、除(/)、指数(**)

  * 关系运算:小于(<)、小于等于(<=)、大于(>)、大于等于(>=)、等于(=)、不等于(!=<>)

  * 字符运算:连接(||)

  * 逻辑运算:与(AND)、或(OR)、非(NOT)

  还有如表所示的特殊运算。

IS NULLIS NOT NULL用来判断运算对象的值是否为空,不能用=去判断。另外,对空值的运算也必须注意,对空值的算术和比较运算的结果都是空,但对空值可以进行连接运算,结果是另外一部分的字符串。例如:

  NULL+5的结果为NULL

  NULL>5的结果为NULL

  NULL|| 'ABC' 的结果为'ABC'

  在PL/SQL中可以使用绝大部分Oracle函数,但是组函数(AVG( )MIN( )MAX( ))只能出现在SQL语句中,不能在其他语句中使用。还有GREATEST( )LEAST( )也不能使用。类型转换在很多情况下是自动的,在不能进行自动类型转换的场合需要使用转换函数。

结构控制语句

分支结构

  分支结构是最基本的程序结构,分支结构由IF语句实现。

  使用IF语句,根据条件可以改变程序的逻辑流程。IF语句有如下的形式:

IF 条件1 THEN

语句序列1

[ELSIF 条件2 THEN

语句序列2

ELSE

语句序列n]

END IF;

其中:

条件部分是一个逻辑表达式,值只能是真(TRUE)、假(FALSE)或空(NULL)

  语句序列为多条可执行的语句。

  根据具体情况,分支结构可以有以下几种形式:

  IF-THEN-END IF

  IF-THEN-ELSE-END IF

  IF-THEN-ELSIF-ELSE-END IF

1IF-THEN-END IF形式

  这是最简单的IF结构,练习如下:

  训练1】  如果温度大于30℃,则显示温度偏高

输入并执行以下程序:SET SERVEROUTPUT ONDECLAREV_temprature		NUMBER(5):=32;V_result         	BOOLEAN:=false;BEGINV_result:= v_temprature >30;IF V_result THEN DBMS_OUTPUT.PUT_LINE('温度'|| V_temprature ||'度,偏高');END IF; END;执行结果为:温度32度,偏高PL/SQL过程已成功完成。

说明:该程序中使用了布尔变量,初值为false,表示温度低于30℃。表达式v_temprature >30返回值为布尔型,赋给逻辑变量V_result。如果变量v_temprature的值大于30,则返回值为真,否则为假。V_result值为真就会执行IFEND IF之间的输出语句,否则没有输出结果。

  试修改温度的初值为25℃,重新执行,观察结果。

2IF-THEN-ELSE-END IF形式

  这种形式的练习如下:

  训练2】  根据性别,显示尊称。

输入并执行以下程序:
SET SERVEROUTPUT ON
DECLAREv_sex	VARCHAR2(2);v_titil  	VARCHAR2(10);
BEGINv_sex:='男';IF v_sex ='男' THENv_titil:='先生';ELSEv_titil:='女士';END IF; DBMS_OUTPUT.PUT_LINE(v_titil||'您好!');
END;执行结果为:先生您好!PL/SQL 过程已成功完成。

说明:该程序根据性别显示尊称和问候,无论性别的值为何,总会有显示结果输出。如果V_sex的值不是,那么输出结果会是什么?

  练习1】对以上程序进行补充修改,在ELSE部分嵌入一个IF结构,如果V_sex的值不是'',则显示朋友你好

3IF-THEN-ELSIF-ELSE-END IF形式

  这种形式的练习如下:

  训练3】  根据雇员工资分级显示税金。

输入并运行以下程序:
SET SERVEROUTPUT ON
DECLAREv_sal  NUMBER(5);v_tax  NUMBER(5,2);
BEGINSELECT sal INTO v_salFROM empWHERE empno=7788;IF v_sal >=3000 THEN V_tax:= v_sal*0.08;--税率8%ELSIF v_sal>=1500 THENV_tax:= v_sal*0.06; --税率6%ELSEV_tax:= v_sal*0.04; --税率4%END IF;DBMS_OUTPUT.PUT_LINE('应缴税金:'||V_tax);
END;执行结果为:应缴税金:240PL/SQL 过程已成功完成。

说明:该程序根据工资计算7788号雇员应缴税金,不同工资级别的税率不同。

选择结构

CASE语句适用于分情况的多分支处理,可有以下三种用法。

  1.基本CASE结构

  语句的语法如下: 

CASE 选择变量名

  WHEN 表达式1 THEN

    语句序列1

  WHEN 表达式2 THEN

    语句序列2

WHEN 表达式n THEN

    语句序列n

  ELSE

    语句序列n+1

  END CASE;

在整个结构中,选择变量的值同表达式的值进行顺序匹配,如果相等,则执行相应的语句序列,如果不等,则执行ELSE部分的语句序列。

  以下是一个使用CASE选择结构的练习。

训练1】  使用CASE结构实现职务转换。

输入并执行程序:
SET SERVEROUTPUT ON
DECLARE
v_job  VARCHAR2(10);
BEGIN
SELECT job INTO v_job
FROM emp
WHERE empno=7788;
CASE v_job
WHEN 'PRESIDENT' THEN DBMS_OUTPUT.PUT_LINE('雇员职务:总裁');
WHEN 'MANAGER' THEN  DBMS_OUTPUT.PUT_LINE('雇员职务:经理');
WHEN 'SALESMAN' THEN  DBMS_OUTPUT.PUT_LINE('雇员职务:推销员');
WHEN 'ANALYST' THEN  DBMS_OUTPUT.PUT_LINE('雇员职务:系统分析员');
WHEN 'CLERK' THEN  DBMS_OUTPUT.PUT_LINE('雇员职务:职员');
ELSE  DBMS_OUTPUT.PUT_LINE('雇员职务:未知');
END CASE;
END;执行结果:雇员职务:系统分析员PL/SQL 过程已成功完成。 

说明:以上实例检索雇员7788的职务,通过CASE结构转换成中文输出。

  练习1】将雇员号修改成其他已知雇员号,重新执行。

2.表达式结构CASE语句

  在Oracle中,CASE结构还能以赋值表达式的形式出现,它根据选择变量的值求得不同的结果。

它的基本结构如下:

  变量=CASE 选择变量名

  WHEN 表达式1 THEN 1

  WHEN 表达式2 THEN 2

  WHEN 表达式n THEN n

  ELSEn+1

  END;

训练2】  使用CASE的表达式结构。

        SET SERVEROUTPUT ONDECLAREv_grade	VARCHAR2(10);v_result	VARCHAR2(10);BEGINv_grade:='B';v_result:=CASE v_gradeWHEN 'A' THEN '优'WHEN 'B' THEN '良'WHEN 'C' THEN '中'WHEN 'D' THEN '差'ELSE '未知'END;DBMS_OUTPUT.PUT_LINE('评价等级:'||V_result);END;执行结果为:评价等级:良PL/SQL 过程已成功完成。

说明:该CASE表达式通过判断变量v_grade的值,对变量V_result赋予不同的值。

3.搜索CASE结构

  Oracle还提供了一种搜索CASE结构,它没有选择变量,直接判断条件表达式的值,根据条件表达式决定转向。

CASE

  WHEN 条件表达式1 THEN

    语句序列1

  WHEN 条件表达式2 THEN

    语句序列2

WHEN 条件表达式n THEN

  语句序列

ELSE

  语句序列n+1

END CASE;

训练3】  使用CASE的搜索结构。

        SET SERVEROUTPUT ONDECLAREv_sal	NUMBER(5);BEGINSELECT sal INTO v_sal FROM emp  WHERE empno=7788;CASE WHEN v_sal>=3000 THEN DBMS_OUTPUT.PUT_LINE('工资等级:高');WHEN v_sal>=1500 THENDBMS_OUTPUT.PUT_LINE('工资等级:中');ELSEDBMS_OUTPUT.PUT_LINE('工资等级:低');END CASE;END;执行结果为:工资等级:高PL/SQL 过程已成功完成。

说明:此结构类似于IF-THEN-ELSIF-ELSE-END IF结构。本训练判断7788雇员的工资等级。

循环结构

  循环结构是最重要的程序控制结构,用来控制反复执行一段程序。比如我们要进行累加,则可以通过适当的循环程序实现。PL/SQL循环结构可划分为以下3种:

  * 基本LOOP循环。

  * FOR LOOP循环。

  * WHILE LOOP循环。

1.基本LOOP循环

  基本循环的结构如下:

  LOOP   --循环起始标识

    语句1;

     语句2;

    EXIT [WHEN 条件];

  END LOOP;   --循环结束标识

  该循环的作用是反复执行LOOPEND LOOP之间的语句。

  EXIT用于在循环过程中退出循环,WHEN用于定义EXIT的退出条件。如果没有WHEN条件,遇到EXIT语句则无条件退出循环。

训练1】 求:1+3+5+...+15 的值。

输入并执行以下程序:SET SERVEROUTPUT ONDECLAREv_total		NUMBER(5):=0;v_count		NUMBER(5):=1;BEGINLOOPv_total:=v_total+v_count**2;EXIT WHEN v_count=15;--条件退出v_count:=v_count+2;END LOOP;DBMS_OUTPUT.PUT_LINE(v_total);END;输出结果为:680PL/SQL 过程已成功完成。

说明:基本循环一定要使用EXIT退出,否则就会成为死循环。

  练习1】1*2*3*4*...*10的值。

2FOR LOOP循环

  FOR循环是固定次数循环,格式如下:

  FOR 控制变量 in [REVERSE] 下限..上限

  LOOP

    语句1;

    语句2;

     END LOOP;

  循环控制变量是隐含定义的,不需要声明。

  下限和上限用于指明循环次数。正常情况下循环控制变量的取值由下限到上限递增,REVERSE关键字表示循环控制变量的取值由上限到下限递减。

  以下是FOR循环结构的练习。

训练2】  FOR循环输出图形。

        SET SERVEROUTPUT ONBEGINFOR I IN 1..8 LOOPDBMS_OUTPUT.PUT_LINE(to_char(i)||rpad('*',I,'*'));END LOOP;END;
输出结果为:
1*
2**
3***
4****
5*****
6******
7*******
8********PL/SQL 过程已成功完成。 

说明:该程序在循环中使用了循环控制变量I,该变量隐含定义。在每次循环中根据循环控制变量I的值,使用RPAD函数控制显示相应个数的*

练习2】为以上程序增加REVERSE关键字,观察执行结果。

  训练3】  输出一个空心三角形。

        BEGIN FOR I IN 1..9LOOP IF I=1 OR I=9 THENDBMS_OUTPUT.PUT_LINE(to_char(I)||rpad(' ',12-I,' ')||rpad('*',2*i-1,'*')); ELSEDBMS_OUTPUT.PUT_LINE(to_char(I)||rpad(' ',12-I,' ')||'*'||rpad(' ',I*2-3,' ')||'*'); END IF;END LOOP; END;
输出结果为:
1           *
2          * *
3         *   *
4        *     *
5       *       *
6      *         *
7     *           *
8    *             *
9   *****************
PL/SQL 过程已成功完成。

说明:该实例采用循环和IF结构相结合,对第1行和第9(I=1 OR I=9)执行同样的输出语句,其他行执行另外的输出语句。

  练习3】修改程序,输出一个实心三角形。

3WHILE LOOP循环

  WHILE循环是有条件循环,其格式如下:

  WHILE 条件

  LOOP

    语句1;

    语句2;

  END LOOP;

  当条件满足时,执行循环体;当条件不满足时,则结束循环。如果第一次判断条件为假,则不执行循环体。

  以下是WHILE循环结构的练习。

训练3】 使用WHILE 循环向emp表连续插入5个记录。

步骤1:执行下面的程序:
SET SERVEROUTPUT ON
DECLARE
v_count	NUMBER(2) := 1;
BEGINWHILE v_count <6 LOOPINSERT INTO emp(empno, ename)VALUES (5000+v_count, '临时');
v_count := v_count + 1;END LOOP;COMMIT;
END;
输出结果为:
PL/SQL 过程已成功完成。
步骤2:显示插入的记录:
SELECT empno,ename FROM emp WHERE ename='临时';
输出结果为:EMPNO ENAME------------------ ----------5001 临时5002 临时5003 临时5004 临时5005 临时已选择5行。
步骤3:删除插入的记录:DELETE FROM emp WHERE ename='临时';COMMIT;输出结果为:已删除5行。提交完成。

说明:该练习使用WHILE循环向emp表插入5个新记录(雇员编号根据循环变量生成),并通过查询语句显示新插入的记录,然后删除。

4.多重循环

  循环可以嵌套,以下是一个二重循环的练习。

  训练4】 使用二重循环求1+2+...+10!的值。

步骤1:第1种算法:
SET SERVEROUTPUT ON
DECLAREv_total	NUMBER(8):=0;v_ni	NUMBER(8):=0;J		NUMBER(5);
BEGIN
FOR I IN 1..10LOOPJ:=1;v_ni:=1;WHILE J<=ILOOPv_ni:= v_ni*J;J:=J+1;END LOOP;--内循环求n!v_total:=v_total+v_ni;END LOOP;--外循环求总和DBMS_OUTPUT.PUT_LINE(v_total);
END;
输出结果为:
4037913
PL/SQL 过程已成功完成。步骤2:第2种算法:
SET SERVEROUTPUT ON
DECLAREv_total		NUMBER(8):=0;v_ni		NUMBER(8):=1;
BEGINFOR I IN 1..10LOOPv_ni:= v_ni*I;	--求n!v_total:= v_total+v_ni;END LOOP;		--循环求总和DBMS_OUTPUT.PUT_LINE(v_total);
END;输出结果为:409114PL/SQL 过程已成功完成。

说明:第1种算法的程序内循环使用WHILE循环求阶层,外循环使用FOR循环求总和。第2种算法是简化的算法,根据是:n!=n*(n?1)!

阶段训练

【训练1】  插入雇员,如果雇员已经存在,则输出提示信息。SET SERVEROUTPUT ON DECLAREv_empno NUMBER(5):=7788;v_num VARCHAR2(10); i NUMBER(3):=0;BEGIN		SELECT count(*) INTO v_num FROM SCOTT.emp WHERE empno=v_empno;IF v_num=1 THENDBMS_OUTPUT.PUT_LINE('雇员'||v_empno||'已经存在!');ELSEINSERT INTO emp(empno,ename) VALUES(v_empno,'TOM');COMMIT;DBMS_OUTPUT.PUT_LINE('成功插入新雇员!');END IF; END;

说明:在本程序中,使用了一个技巧来判断一个雇员是否存在。如果一个雇员不存在,那么使用SELECT...INTO来获取雇员信息就会失败,因为SELECT...INTO形式要求查询必须返回一行。但如果使用COUNT统计查询,返回满足条件的雇员人数,则该查询总是返回一行,所以任何情况都不会失败。COUNT返回的统计人数为0说明雇员不存在,返回的统计人数为1说明雇员存在,返回的统计人数大于1说明有多个满足条件的雇员存在。本例在雇员不存在时进行插入操作,如果雇员已经存在则不进行插入。

【训练2】  输出由符号“*”构成的正弦曲线的一个周期(0~360°)。SET SERVEROUTPUT ON SIZE 10000
SET LINESIZE 100
SET PAGESIZE 100
DECLAREv_a	NUMBER(8,3);v_p 	NUMBER(8,3);
BEGINFOR I IN 1..18LOOPv_a:=I*20*3.14159/180;--生成角度,并转换为弧度v_p:=SIN(v_a)*20+25;--求SIN函数值,20为放大倍数,25为水平位移DBMS_OUTPUT.PUT_LINE(to_char(i)||lpad('*',v_p,' '));--输出记录变量的某个字段END LOOP;END;
输出结果如下:
1                               *
2                                     *
3                                         *
4                                            *
5                                            *
6                                         *
7                                     *
8                               *
9                        *
10                 *
11           *
12       *
13    *
14    *
15       *
16           *
17                 *
18                        *
PL/SQL 过程已成功完成。

说明:在本程序中使用到了固定次数的循环以及SINLPAD函数,通过正确地设置步长、幅度和位移的参数,在屏幕上可正确地显示图形。

本人从事软件项目开发20多年,2005年开始从事Java工程师系列课程的教学工作,录制50多门精品视频课程,包含java基础,jspweb开发,SSH,SSM,SpringBoot,SpringCloud,人工智能,在线支付等众多商业项目,每门课程都包含有项目实战,上课PPT,及完整的源代码下载,有兴趣的朋友可以看看我的在线课堂

讲师课堂链接:https://edu.csdn.net/lecturer/893

相关文章:

07-PL/SQL基础(if语句,case语句,循环语句)

本章主要内容&#xff1a; 1.PL/SQL的基本构成&#xff1a;declare,begin,exception,end; 2.结构控制语句:IF语句,CASE语句 3.循环结构&#xff1a;loop循环&#xff0c;for loop循环&#xff0c;while loop循环 PL/SQL的基本构成 特点 PL/SQL语言是SQL语言的扩展&#xff…...

信捷 XDH Ethercat A_VELMOVE

本文描述信捷 EthercatA_VELMOVE指令&#xff0c;以设定的速度持续运行 上图中&#xff0c;在M100的上升沿&#xff0c;执行A_VELMOVE指令。A_VELMOVE HD100 D100 M101 K0HD100输入参数起始地址 &#xff0c;HD118输入参数末尾地址HD100~HD103,双精度浮点数&#xff08;64位&am…...

【专项训练】分治、回溯

分治、回溯其实就是递归,只是是递归的一个细分,是一种特殊的递归 碰到一个题目,你就找他的重复性 最近重复性:根据重复性怎么构造以及如何分解,包括:分治、回溯 最优重复性:动态规划 本质:找重复性、分解问题、组合子问题的结果 回溯:试错! 50. Pow(x, n) https:…...

Linux上安装配置ZooKeeper

Linux上安装配置ZooKeeper 下载压缩文件 将压缩文件拷贝到指定目录下 执行命令 tar -zxvf [apache-zookeeper-3.5.7-bin.tar.gz] -C [/opt/module/]注&#xff1a;第一个括号里面是压缩文件名称&#xff0c;第二个括号里面是解压到指定的目录 进入到解压后的文件夹当中&am…...

idea leetcode插件无法登录

em 2022某天 leetcode-cn.com 改为了 leetcode.cn so , 如果是版本比较老idea leetcode插件, 就无法使用了. 因为用的旧域名 先说解决办法: 2.0 先把旧版本卸载了 2.1 ideaplugin官网找到本地idea版本下可安装的最高版本的leetcode.cn 假设是 leetcode-editor-6.9.zip 2.2 下…...

VR会议不断升级,为商务会谈打造云端洽谈服务!

VR会议不断升级&#xff0c;为商务会谈打造云端洽谈服务。在商务合作中&#xff0c;对客户需求的理解以及与客户讲解方案都需要建立在一个有效的沟通上&#xff0c;因此VR会议的用武之地就有了&#xff0c;以VR全景技术为核心&#xff0c;通过同屏互动和全景通信技术&#xff0…...

Ubuntu系统开机自动挂载NTFS硬盘【超实用】

由于跑深度学习实验(图像分割)f非常消耗内存&#xff0c;系统盘sda1内存小&#xff0c;配置了一个大容量得出NTFS机械盘&#xff0c;网上招了一些资料如何挂在&#xff0c;但是每次开机得手动挂载一遍才能使用硬盘&#xff0c;非常不方便&#xff0c;还容易造成数据丢失。 Step…...

淘宝十年资深架构师吐血总结淘宝的数据库架构设计和采用的技术手段。

淘宝十年资深架构师吐血总结淘宝的数据库架构设计和采用的技术手段。 文章目录淘宝十年资深架构师吐血总结淘宝的数据库架构设计和采用的技术手段。本文导读1.分库分表2.数据冗余3.异步复制4.读写分离总结本文导读 淘宝的数据库架构设计采用了分布式数据库技术&#xff0c;通过…...

训练自己的GPT2-Chinese模型

文章目录效果抢先看准备工作环境搭建创建虚拟环境训练&预测项目结构模型预测续写训练模型遇到的问题及解决办法显存不足生成的内容一样文末效果抢先看 准备工作 从GitHub上拉去项目到本地&#xff0c;准备已训练好的模型百度网盘&#xff1a;提取码【9dvu】。 gpt2对联训…...

springcloud3 fegin服务超时的配置和日志级别的配置2

一 fegin的概述 1.1 fegin的默认超时时间 默认fegin客户端只等待1秒钟&#xff0c;超过1秒钟&#xff0c;直接会返回错误。 1.2 架构图 1.2.1 说明 1.2.2 启动操作 1.先启动9001,9002 eureka 2.启动9003 服务提供者 3.启动9006消费者 1.3 情况验证 1.3.1 正常默认情…...

华为机试 HJ48 从单向链表中删除指定值的节点

题目链接 描述 输入一个单向链表和一个节点的值&#xff0c;从单向链表中删除等于该值的节点&#xff0c;删除后如果链表中无节点则返回空指针。 链表的值不能重复。 构造过程&#xff0c;例如输入一行数据为: 6 2 1 2 3 2 5 1 4 5 7 2 2 则第一个参数6表示输入总共6个节点&a…...

华为机试 HJ1 字符串最后一个单词的长度

华为机试 HJ1 字符串最后一个单词的长度 文章目录华为机试 HJ1 字符串最后一个单词的长度一、题目描述二、方法一 Java lastIndexOf() 方法三、方法二 Java split()方法使用Java的lastIndexOf()和split()解决求取方法字符串最后一个单词的长度的问题 一、题目描述 计算字符串最…...

从入门到精通MongoDB数据库系列之二:深入了解MongoDB基本概念文档、集合、数据库、数据类型、MongoDB shell

从入门到精通MongoDB数据库系列之二:深入了解MongoDB基本概念文档、集合、数据库、数据类型、MongoDB shell 一、MongoDB基本概念二、文档三、集合1.动态模式2.命名四、数据库五、MongoDB shell1.运行shell2.连接远程MongoDB数据库3.shell中的基本操作六、数据类型1.基本数据类…...

前端实用技巧,JS压缩、美化、JS混淆加密

作为一名前端开发者&#xff0c;关注JavaScript代码的安全性和隐私性&#xff0c;或者需要对JavaScript代码进行美化、格式化、压缩等操作&#xff0c;帮助你提高开发效率和代码质量&#xff0c;利用一个好的工具非常重要。 如果不想让自己的代码被恶意篡改和盗用&#xff0c;作…...

synchronized轻量级锁优化

synchronized优化轻量级锁 使用场景 如果一个对象虽然有多个线程访问&#xff0c;但多线程访问时间是错开的&#xff0c;也就是没有竞争&#xff0c;那么可以使用轻量级锁优化&#xff1b; 原理 1、每个线程的栈帧中有锁记录 包括&#xff1a;记录锁对象的地址Object refer…...

python 日期转换 日期字符相关

python中时间日期格式化符号&#xff1a; import datetime # Fri, 24 Feb 2023 22:23:18 0000 ret datetime.datetime.strptime("Fri, 24 Feb 2023 22:23:18 0000", "%a, %d %b %Y %H:%M:%S %z").strftime("%Y-%m-%d %H:%M:%S") print(ret)%y …...

使用sm4js进行加密和国密sm4的总结

最近在开发过程中&#xff0c;用到了sm4国密加密&#xff0c;因为之前没有用过&#xff0c;所以就想总结一下。 先说一下怎么安装使用&#xff08;vue项目&#xff09; 1、先安装sm4js npm i sm4js在package.json中显示sm4js的版本如下&#xff1a; "dependencies&quo…...

c语言面试题目整理

1、static有什么用途&#xff1f; 在C语言中&#xff0c;static主要定义全局静态变量&#xff0c;定义局部静态变量&#xff0c;定义静态函数 限制变量的作用域&#xff0c;设置变量的存储域。 static 关键字主要有两种作用&#xff1a; 第一&#xff0c;为某特定数据类型或对…...

【嵌入式Bluetooth应用开发笔记】第三篇:初探BLUE ALSA应用开发

概述 BlueALSA(Bluetooth Audio ALSA)是一种将蓝牙音频设备连接到 ALSA 音频系统的桥接程序。它提供了一个蓝牙音频设备的 ALSA 插件,允许使用 ALSA API 直接从蓝牙音频设备读取和写入音频数据,从而使得蓝牙音频设备能够以与其他 ALSA 兼容设备相同的方式工作。 BlueALSA …...

C++基础了解-21-C++ 继承

C 继承 一、C 继承 面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类&#xff0c;这使得创建和维护一个应用程序变得更容易。这样做&#xff0c;也达到了重用代码功能和提高执行效率的效果。 当创建一个类时&#xff0c;不需要重新编写新的…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...