Oracle笔记

本文围绕Oracle数据库展开,介绍了表的命名约束、数据类型、创建与更改操作,视图和序列的创建,以及DML操作。还详细阐述了PL/SQL的三种类型、数据类型、控制语句、游标、异常处理、触发器和过程函数等内容,包含大量语法示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

表的命名约束
  • 必须是以字母开头。
  • 1–30个字符长度
  • 仅能包含A–Z, a–z, 0–9, _, $ 和 #
  • 在同一个用户下表名不能重复。
  • 不能是Oracle保留字
数据类型
数据类型说明
VARCHAR2(size)存放可变长字符数据,最大长度为4000字符
CHAR(size)存放定长字符数据,最长2000个字符
NUMBER(p,s)存放数值型数据,p代表总位数,s代表小数点后位数
LONG存放可变长字符数据,最大为2GB(gigabytes)
DATE存放日期,范围从公元前4712年的1月1日到 公元后9999年的12月31日
CLOB存放单字节字符数据,最大为4GB(gigabytes)
RAW and LONG RAW纯(Raw)二进制数据
BLOB二进制大对象,其最大长度为 4GB(gigabytes)
BFILE二进制大对象, 存放在外部文件中。最大长度为4GB(gigabytes)
创建表
CREATE TABLE t_name(
字段名 数据类型 ,
deptno 	NUMBER(2),
dname 	VARCHAR2(14)
);
更改表
增加列

ALTER TABLE t_name

ADD (job VARCHAR2(9));

删除列

ALTER TABLE t_name SET UNUSED COLUMN 列名;

ALTER TABLE t_name DROP UNUSED COLUMNS;

修改列

ALTER TABLE table modify (ename varchar(20));

删除表

DROP TABLE t_name;

修改表名称

RENAME t_name TO table;

在Oracle中的约束类型:
  1. NOT NULL
  2. UNIQUE
  3. PRIMARY KEY
  4. FOREIGN KEY
  5. CHECK
列约束 vs 表约束

列约束:ename VARCHAR2(10) NOT NULL
表约束:CONSRAINT 约束名 约束类型(字段名)

eg: CONSTRAINT emp_deptno_fk FOREIGN KEY(deptno) REFERENCES dept(deptno);

视图

简单与复杂视图

特点简单视图复杂视图
表的个数11个或多个
是否包含函数
是否包含数据分组
是否允许DML操作

创建视图

CREATE OR REPLACE view v_name
AS 子查询

*子查询不能包含ORDER BY子句。

创建序列

CREATE OR REPLACE SEQUENCE sequence 
INCREMENT BY 步长
START WITH 起始
MAXVALUE 最大值;
SELECT sequence.nextval from dual;
  • NEXTVAL返回下一个有效的序列值。
  • CURRVAL得到当前的序列值。
  • 第一次使用序列时必须首先调用NEXTVAL,否则CURRVAL 不会包含任何值。

DML操作

INSERT

单行插入

INSERT INTO t_name(,,,) values(,,,); 

多行插入

INSERT INTO t_name(,,,) SELECT ,,, FROM t_name WHERE condition;

*不能使用VALUES子句

UPDATE

更新指定行

UPDATE t_name SET column=value WHERE condition;  

更新所有行

UPDATE t_name SET column=value;

更新多列

UPDATE t_name set (c1,c2) = (SELECT c1, c2 FROM t_name WHERE condition)  WHERE condition;

DELETE

删除行

DELETE FROM t_name WHERE condition;

SELECT

NULL值

***在算术表达式中的NULL值,如果算术表达式中包含NULL值,则表达式的值也为NULL。

AS别名

如果别名中包含空格或特定的字符或需要区分大小写时,需要使用双引号

LIKE匹配规则

「 % 」可匹配0个或 多个字符 ,符号「 _ 」可匹配任何单一字符

where 优先级

所有比较操作符>NOT>AND>OR

ORDER BY

ASC:从小到大排序(default)
DESC:从大到小排序
ORDER BY子句在SELECT语句的最后

字符函数:常用函数列表
函数
LPAD(X, Y [,Z])在字符串X的左边加入字符Z(默认的字符是空格),加入字符的个数为Y。
RPAD(X, Y [,Z])在字符串X的右边加入字符Z(默认的字符是空格),加入字符的个数为Y。
LOWER(X)把字符串X所有的字符转换成小写。
UPPER(X)把字符串X所有的字符转换成大写
INITCAP(X)把字符串X的每个英文单词的第一个字符转换成大写,其它字符转换的成小写。
LENGTH(X)返回字符串X的长度。
SUBSTR(X, Y [,Z])从字符串X的第Y个字符开始,取出Z个字符(默认取出所有字符)。
INSTR(X, Y)字符串Y在字符串X中的位置。
CONCAT(X, Y)把字符串X和字符串Y连接在一起。
数值函数:常用函数列表
数值函数返回值
ABS(n)绝对值
ROUND(n[,m])返回将 n 四舍五入到小数点右边 m 位的值。当 m 忽略时,四舍五入到个位。当 m 为负时,四舍五入到下数点左边数字。
CEIL(n)返回大于或等于 n 的最小整数。
FLOOR(n)返回等于或小于 n 的最大整数。
MOD(m,n)返回 m 除以 n 的余数,如果 n=0,则返回 m。
SIGN(n)当 n<0,返回 -1,当 n=0,返回 0,当 n>0,返回 1。
SQRT(n)返回 n 的平方根。
TRUNC(n [,m])返回在 m 位截断的 n 值,当 m 忽略,在 0 位截断;m 为负,将小数点左边 m 个数字截断。
日期函数
FunctionDescription
MONTHS_BETWEEN(date1,date2)两个日期间相差的月数
ADD_MONTHS(date,number)增加number月的日期
NEXT_DAY(date,day)返回指定date后,由day命名的第一周的日期
LAST_DAY(date)返回date所在月份最后一天的日期
ROUND(date [,fmt])Round date
TRUNC(d [,fmt])Truncate date
CASE函数
CASE expr WHEN comparison_expr1 THEN return_expr1
         [WHEN comparison_expr2 THEN return_expr2
          WHEN comparison_exprn THEN return_exprn
          ELSE else_expr]
END
DECODE函数
DECODE(col|expression, search1, result1 
      			   [, search2, result2,...,]
      			   [, default])
树查询
SELECT [LEVEL], column, expr...
FROM table
[WHERE condition(s)]
[START WITH condition(s)]
[CONNECT BY PRIOR condition(s)]

*PRIOR位置决定查子树还是回溯

常用分组函数

AVG([DISTINCT|ALL] expression) 平均值
MAX ([DISTINCT|ALL] expression) 最大值
MIN ([DISTINCT|ALL] expression) 最小值
SUM ([DISTINCT|ALL] expression) 加总
COUNT ({ * | [DISTINCT|ALL] expression}) 含有非NULL的行数
STDDEV ([DISTINCT|ALL] expression) 统计标准差
VARIANCE ([DISTINCT|ALL] expression) 统计方差

*AVG, MAX, MIN, SUM在计算时会忽略NULL行

*AVG, MAX, MIN, SUM在全为NULL时计算结果为NULL

COUNT(*) 返回表中所有行

COUNT(expr)返回表中指定列的非NULL行数

PL/SQL

PL/SQL三种类型

匿名块
DECLARE

BEGIN
 --statements
EXCEPTION

END;
存储过程
CREATE OR REPLACE PROCEDURE p_name() 
IS
BEGIN
--statements
END p_name;
函数
CREATE OR REPLACE FUNCTION f_name()
RETURN datatype
IS
BEGIN
 --statements
  RETURN value;
END f_name;

基本标量数据类型

VARCHAR2 (maximum_length)

*varchar2的最大长度为32767字节

NUMBER [(p, s)]

*NUMBER(p,s)用来存储正负整数、分数和浮点型数据,有38位的精确度,p表示精度,用于指定数字的总位数;s用于指定小数点后的数字位数。

DATE
CHAR [(maximum_length)]
LONG
LONG RAW
BOOLEAN
BINARY_INTEGER

*定义常量时必须同时为它赋值,否则会出现错误。

引用类型

%TYPE 引用变量或数据库列的数据类型
%ROWTYPE 引用表中一行的记录类型

PL/SQL中使用SQL

SELECT语句
SELECT select_list
INTO	 {variable_name[, variable_name]...
	 | record_name}   
FROM	 table
WHERE	 condition;

select_list(选择列表):被选择的列(至少包含一列)或SQL表达式、行函数和组函数。
variable_name(输出变量):存放检索结果的标量变量。每个变量都应该与其关联的列相兼容,而且应该有相同数量的选择列表项和输出变量。
record_name(输出变量):用来替换变量列表。利用PL/SQL记录来存放检索结果,该记录应该包含与选择列表相对应的字段。
table 特定的数据库表名。
condition 查询条件,可以包含PL/SQL变量和常量

eg:

DECLARE
  --声明变量
  v_deptno number(2);
  v_loc  varchar2(15);
BEGIN
	--获取dept表中deptno, loc数据,将数据注入到v_deptno, v_loc变量中
	SELECT deptno, loc 
	INTO  v_deptno, v_loc
	FROM dept 
	WHERE dname ='SALE';
END;
INSERT语句

eg:

DECLARE 
   --定义类型为dept.deptno字段类型
   v_deptno dept.deptno%TYPE ;
   v_dname dept.dname%TYPE;
BEGIN
   --&no和’&name’ ,表示替代变量,当程序被执行时系统会提示为替代变量输入值。
   v_deptno:=&no;
   v_dname :='&name';
   INSERT INTO dept (deptno,dname) VALUES (v_deptno,v_dname);  
END;
UPDATE语句

eg:

DECLARE 
 --PL/SQL中赋值为 :=
 v_sal_increase   emp.sal%TYPE := 2000;   
BEGIN
--对工作为ANALYST的员工加工资
  UPDATE	emp
    SET	sal = sal + v_sal_increase
    WHERE	job = 'ANALYST';
END;
DELETE语句
DECLARE
  v_deptno   emp.deptno%TYPE := 10;               
BEGIN							
  DELETE FROM emp
    WHERE deptno = v_deptno;
END;

控制语句

构造逻辑条件(特殊)
  • NULL AND TRUE 为NULL
  • NULL AND FALSE 为FALSE
  • NULL OR TRUE 为TRUE
  • NULL OR FALSE 为NULL
IF逻辑结构

IF-THEN-END IF
IF-THEN-ELSE-END IF
IF-THEN-ELSIF-END IF

IF condition THEN
  statements;
[ELSIF condition THEN 
  statements;]
[ELSE 
  statements;]
EDN IF;
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 = 'E' THEN dbms_output.put_line('Poor');
ELSE
  dbms_output.put_line('No such grade');
END IF;
CASE表达式
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;

*为了避免CASE_NOT_FOUND异常,在编写CASE语句时应该带有ELSE语句。

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 'E' THEN  dbms_output.put_line('Poor');
ELSE dbms_output.put_line('No such grade');
END CASE;
Basic loop

语法

LOOP                      
  statement1;
  . . .
  EXIT [WHEN condition];
  statement2;
END LOOP;

eg:给定任意一个整数,计算该数的阶乘

DECLARE
  v_num NUMBER(2):=&num;  --用户任意给定的一个整数
  v_pro NUMBER(20):=1;  
  i NUMBER(2):=1;  --控制循环结束的循环变量
BEGIN
  IF v_num=0 THEN
    v_pro:=1;
  ELSE
    LOOP
      v_pro:=v_pro*i;  --计算给定整数的阶乘
      i:=i+1;
      EXIT WHEN i>v_num;
    END LOOP;
  END IF;
  dbms_output.put_line('num:'||v_num||'  factorial:'||v_pro);
END;
FOR loop

语法

FOR counter in [REVERSE] 
    lower_bound..upper_bound LOOP  
  statement1;
  statement2;
  . . .
END LOOP;
  • 在FOR Loop循环中不要声明计数器变量;计数器变量被隐式声明;
  • 计数器只能在Loop循环内使用;计数器不能在loop循环体外部定义
  • 可以在循环内部使用计数器的值
  • 不能把值分配给计数器

eg:

DECLARE
  v_num NUMBER(2):=&num;
  v_pro NUMBER(20):=1;
BEGIN
  IF v_num=0 THEN
    v_pro:=1;
  ELSE
    FOR i IN 1..v_num LOOP
      v_pro:=v_pro*i;      
    END LOOP;
  END IF;
  dbms_output.put_line('num:'||v_num||'  factorial:'||v_pro);
  --dbms_output.put('num:'||v_num);
  --dbms_output.put_line('  factorial:'||v_pro);
END;
WHILE loop

语法

WHILE condition LOOP
  statement1;
  statement2;
  . . .
END LOOP;

eg:

DECLARE
  v_num NUMBER(2):=&num;
  v_pro NUMBER(20):=1;
  i NUMBER(2):=1;
BEGIN
  IF v_num=0 THEN
    v_pro:=1;
  ELSE
    WHILE i<=v_num LOOP
      v_pro:=v_pro*i; 
      i:=i+1;
    END LOOP;
  END IF;
  dbms_output.put_line('num:'||v_num||'  factorial:'||v_pro);
END;

游标

语法

CURSOR cursor_name IS
     select_statement;      

eg:

DECLARE
  v_ename  emp.ename%TYPE;
  v_sal    emp.sal%TYPE;
  v_empRecord  emp%ROWTYPE;
--创建游标
  CURSOR cur_AllEmp IS
    SELECT *  FROM emp;  
BEGIN
  OPEN cur_AllEmp; --打开游标

  FETCH cur_AllEmp INTO v_empRecord; --提取游标数据
END;
游标提取FOR LOOP(常用)
FOR record_name IN cursor_name LOOP   
  statement1;
  statement2;
  . . .
END LOOP;

eg:游标查询emp表中的所有记录,并在程序块中输出工资最高的前五行记录。

DECLARE
   CURSOR cur IS SELECT * FROM scott.emp ORDER BY sal DESC;
BEGIN
   FOR rec IN cur  LOOP
      IF cur%ROWCOUNT<=5 THEN
                dbms_output.put_line('ename:'||rec.ename||’sal:'||rec.sal);
      ELSE 
        EXIT;
      END IF;
   END LOOP;
END;
不定义游标
BEGIN
  FOR emp_record IN ( SELECT empno, ename
	                      FROM   emp) LOOP
         -- implicit open and implicit fetch occur
    IF emp_record.empno = 7839 THEN
      ...
  END LOOP; -- implicit close occurs
END;
带参数游标

eg:定义参数游标,查询指定部门的员工姓名

DECLARE
--定义游标参数no,参数类型为number类型
CURSOR emp_cursor( no NUMBER) IS 
		SELECT ename FROM emp WHERE deptno=no;
emp_rec emp_cursor%ROWTYPE;
BEGIN
  --打开参数游标时,指明一个替代变量作为游标参数的值
  OPEN emp_cursor(&no); 
  LOOP
    FETCH emp_cursor INTO emp_rec;
    EXIT WHEN emp_cursor%NOTFOUND;     
    dbms_output.put_line('ename:'||emp_rec.ename);
  END LOOP;
  CLOSE emp_cursor;
END;

异常处理

*异常处理,仅用来处理PL/SQL运行时错误。

语法

EXCEPTION
  WHEN exception1 [OR exception2 . . .] THEN
    statement1;
    statement2;
    . . .
  [WHEN exception3 [OR exception4 . . .] THEN
    statement1;
    statement2;
    . . .]
  [WHEN OTHERS THEN
    statement1;
    statement2;
    . . .]
异常类型
  • 系统预定义异常 (隐式触发)
  • 系统非预定义异常(隐式触发)
  • 用户自定义异常(显示触发)
系统预定义异常

CASE_NOT_FOUND (ORA-06592)
NO_DATA_FOUND (ORA-1403)
TOO_MANY_ROWS (ORA-1422)
DUP_VAL_ON_INDEX (ORA-0001)
ZERO_DIVIDE (ORA-1476)
INVALID_CURSOR (ORA-1001)
VALUE_ERROR (ORA-6502)

eg:

DECLARE
  v_empRecord  emp%ROWTYPE; 
  v_empNo      emp.empno%TYPE; 
BEGIN  
  SELECT *  INTO v_empRecord  FROM emp;
  --SELECT *  INTO v_empRecord  FROM emp  WHERE empno = 12345789 ;
  --SELECT ename  INTO v_empNo  FROM emp  WHERE empno = 7369;
  EXCEPTION
    WHEN TOO_MANY_ROWS THEN
      dbms_output.put_line('TOO_MANY_ROWS EXCEPTION'); 
    WHEN NO_DATA_FOUND THEN
      dbms_output.put_line('NO_DATA_FOUND EXCEPTION'); 
    WHEN OTHERS THEN
      dbms_output.put_line('OTHERS EXCEPTION');
END;
系统非预定义异常

将一个经过命名的异常和一个特别的Oracle错误编号相关联。

DECLARE
  e_products_invalid	EXCEPTION;
  PRAGMA EXCEPTION_INIT (
		e_products_invalid, -2291); --将数字-2291与e_products_invalid相关联。
  v_message VARCHAR2(50);
BEGIN
. . .
EXCEPTION
  WHEN e_products_invalid THEN
    :g_message := 'Product code
		specified is not valid.';
. . .
END;

捕获Oracle服务器错误
将数字-2291与e_products_invalid相关联。(-2291表示违反了完整性约束)

用户自定义异常
[DECLARE]
  e_amount_remaining EXCEPTION;
. . .
BEGIN
. . .
  RAISE e_amount_remaining;
. . .
EXCEPTION
  WHEN e_amount_remaining  THEN
    :g_message := 'There is still an amount
	             in stock.';
. . .
END;

eg:向emp表中插入一条新记录,在执行的过程中捕获系统预定义异常、系统非预定义异常、用户自定义异常,并分别作相应的处理。

DECLARE  
  ex_null EXCEPTION; --系统非预定义异常的定义和关联
  PRAGMA EXCEPTION_INIT(ex_null,-01400);  
  ex_insert EXCEPTION; --用户自定义异常的定义  
  eno scott.emp.empno%TYPE:=&no; --定义程序块变量
  e_sal scott.emp.sal%TYPE:=&salary;
BEGIN
  IF e_sal>10000 THEN
    RAISE ex_insert;  --用户自定义异常的触发
  END IF;
  INSERT INTO scott.emp(empno,sal) VALUES(eno,e_sal);
  EXCEPTION
    WHEN DUP_VAL_ON_INDEX  THEN   --系统预定义异常的捕获和处理
      dbms_output.put_line('该员工已经存在!');
    WHEN ex_null THEN   --系统非预定义异常的捕获和处理
      dbms_output.put_line('职工编号不能为空!');
    WHEN ex_insert THEN   --用户自定义异常的捕获和处理
      dbms_output.put_line('员工的工资不能超过10000!');
END;

触发器

创建语法
CREATE [OR REPLACE] TRIGGER trigger_name
   {BEFORE | AFTER} triggering_event ON table_reference
   [FOR EACH ROW [WHEN trigger_condition]]
trigger_body;

trigger_name是触发器名,triggering_event指定了何时激发触发器, table_reference是定义触发器的表, trigger_body是触发器的主要处理代码。WHEN子句的trigger_condition如果被使用的话,将首先进行求值。触发器的主体仅当此条件求值为TRUE时才被执行。

触发器的激发顺序
  1. 执行BEFORE语句级触发器(如果有的话)。
  2. 对于受语句影响的每一行:
  • 执行BRFORE行级触发器(如果有的话)。

  • 执行DML语句(系统自动执行)

  • 执行AFTER行级触发器(如果有的话)。

    3.执行AFTER语句级触发器(如果有的话)。

eg:

CREATE OR REPLACE TRIGGER TR_STMBEFORE
BEFORE DELETE ON EMP
BEGIN
  DBMS_OUTPUT.PUT_LINE('STM BEFORE');
END TR_STMBEFORE;
/
CREATE OR REPLACE TRIGGER TR_STMAFTER
AFTER DELETE ON EMP
BEGIN
  DBMS_OUTPUT.PUT_LINE('STM AFTER');
END;
/
语句级触发器
CREATE OR REPLACE TRIGGER  secure_emp
BEFORE INSERT OR UPDATE OR DELETE  ON dept
BEGIN
 IF (TO_CHAR(SYSDATE, 'DY') IN ('星期六', '星期天')) 
           OR (TO_CHAR(SYSDATE, 'HH24') NOT BETWEEN '08' AND '18')
    THEN 
      IF DELETING THEN
          RAISE_APPLICATION_ERROR (-20502, 'You may delete from  EMP table only during business hours.');
       ELSIF INSERTING THEN
         RAISE_APPLICATION_ERROR (-20500,'You may insert into EMP table only during business hours.');
       ELSIF UPDATING ('SAL') THEN
         RAISE_APPLICATION_ERROR (-20503,'You may update SAL only during business hours.');
       ELSE
         RAISE_APPLICATION_ERROR (-20504,'You may update EMP table only during normal hours.');
       END IF;
    END IF;
END secure_emp; 

行级触发器
CREATE OR REPLACE TRIGGER restrict_salary
  BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW
    BEGIN
      IF NOT (:NEW.job IN ('PRESIDENT', 'MANAGER', 'ANALYST')) AND :NEW.sal > 2500
      THEN
        RAISE_APPLICATION_ERROR (-20202, 'Employee cannot earn this amount');
      END IF;
END;

在行级触发器中使用 :old和 :new
触发语句所处理的每一行都激发一次行级触发器。在触发器的内部,你可以访问当前正在被处理的行。这是通过“伪记录”——:old和:new实现的。它们的类型是table_reference%ROWTYPE。

过程函数

创建过程语法
CREATE OR REPLACE PROCEDURE procedure_name 
[(parameter1 [IN | OUT | IN OUT] data_type , parameter2 [IN | OUT | IN OUT] data­_type,)]
IS |AS
   [declaration_section;]
BEGIN
   executable_section;
[EXCEPTION
   exception_handlers;]
END [procedure_name];

注意与匿名块有三点区别:
1.无DECLARE关键字
2.在END后面可以加过程名 作为定义结束的标志
3.存储过程定义完成后需要调用才能执行过程内部的代码。

eg:创建存储过程,输出系统的日期和时间

CREATE OR REPLACE PROCEDURE display_time 
IS
BEGIN
   dbms_output.put_line(systimestamp);
END display_time;

使用三种方式调用上面创建的存储过程
方式一:使用sqlplus命令EXECUTE(简写EXEC) 调用
EXECUTE display_time;
方式二:使用sql命令CALL调用
CALL display_time( );
方式三:在PL/SQL块中调用
BEGIN
display_time;
END;

过程的形参

eg:

CREATE OR REPLACE PROCEDURE insert_emp 
(no  emp.empno%TYPE,			name  emp.ename%TYPE,
Job  emp.job%TYPE,				mgr  emp.mgr%TYPE,
hiredate emp.hiredate%TYPE ,	salary emp.sal%TYPE ,
comm emp.comm%TYPE ,		deptno emp.deptno%TYPE 
)
IS
BEGIN
INSERT INTO emp VALUES(no,name,job,mgr,hiredate,salary,comm,deptno);

调用过程

DECLARE
v_no  emp.empno%TYPE:=10000,
v_name  emp.ename%TYPE :=‘Jones’,
v_job  emp.job%TYPE := 'SALESMAN',
v_mgr  emp.mgr%TYPE :=7369,
v_hiredate emp.hiredate%TYPE :=SYSDATE,
v_salary emp.sal%TYPE := 800,
v_comm emp.comm%TYPE :=NULL,
v_deptno emp.deptno%TYPE :=10
BEGIN
 insert_emp(v_no, v_name, v_job, v_mgr, v_hiredate, v_salary, v_comm, v_deptno );
END;
参数模式
INOUTIN OUT
默认模式必须说明必须说明
调用过程时,实际参数取值被传递给过程。过程结束时,形参的内容将赋给实参。把值返回给调用环境。调用过程时,实际参数取值被传递给过程。过程结束时,形参的内容将赋给实参。把值返回给调用环境。
在过程内部,形式参数是常数,不能改变。形式参数不能被初始化,只能被赋值。当过程调用时,实参中具有的任何值将被忽略。实际参数变量必须初始化。
实际参数可以是直接量、常数、表达式和初始化了的变量。实际参数必需是变量实际参数必需是变量。
能够拥有缺省值不能分配缺省值不能分配缺省值

PL/SQL子程序程参数的三种模式及特点:
IN用于向程序传递数据,参数在程序内部不能赋值
OUT用于从程序内获取数据,参数在程序内部赋值前是null
IN OUT 用于向程序传递数据和从程序内获取数据

创建函数语法
CREATE [OR REPLACE] FUNCTION function_name 
[(argument1 [IN | OUT | IN OUT] data_type , argument2 [IN | OUT | IN OUT] data­_type,)]
RETURN data_type
IS |AS
   [declaration_section;]
BEGIN
   executable_section;
   RETURN expression;
[EXCEPTION
   exception_handlers;
RETURN expression;
END [function_name]; 
  1. return_datatype是函数返回的数值的类型,不能对数据类型的SIZE进行限定。
  2. 在PL/SQL块中,可以使用多个RETURN语句,但是必须保证至少有一条RETURN语句存在。函数每一次运行只有一个RETURN语句被执行。

eg:

CREATE OR REPLACE FUNCTION get_sal
      (p_id IN emp.empno%TYPE)
RETURN NUMBER
IS
      v_salary emp.sal%TYPE :=0;
BEGIN
     SELECT sal     INTO v_salary     FROM emp     WHERE empno = p_id;
     RETURN v_salary;
END get_sal;
方式一:SQLPLUS命令使用变量接收返回值
VAR salary NUMBER;
EXEC :salary:=get_sal(7369);
PRINT salary;
方式二:在SQL语句中直接调用函数
SELECT get_sal(7369) FROM DUAL;
方式三:使用DBMS_OUTPUT调用函数(表达式运算)
dbms_output.put_line('工资是:'|| get_sal(7369));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值