表
表的命名约束
- 必须是以字母开头。
- 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中的约束类型:
- NOT NULL
- UNIQUE
- PRIMARY KEY
- FOREIGN KEY
- CHECK
列约束 vs 表约束
列约束:ename VARCHAR2(10) NOT NULL
表约束:CONSRAINT 约束名 约束类型(字段名)
eg: CONSTRAINT emp_deptno_fk FOREIGN KEY(deptno) REFERENCES dept(deptno);
视图
简单与复杂视图
特点 | 简单视图 | 复杂视图 |
---|---|---|
表的个数 | 1 | 1个或多个 |
是否包含函数 | 否 | 是 |
是否包含数据分组 | 否 | 是 |
是否允许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 个数字截断。 |
日期函数
Function | Description |
---|---|
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):=# --用户任意给定的一个整数
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):=#
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):=#
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时才被执行。
触发器的激发顺序
- 执行BEFORE语句级触发器(如果有的话)。
- 对于受语句影响的每一行:
-
执行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;
参数模式
IN | OUT | IN 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];
- return_datatype是函数返回的数值的类型,不能对数据类型的SIZE进行限定。
- 在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));