先上一张实用的图:用于转义字符的。
SQL> select chr(42) ||'is what?' from dual;
CHR(42)||
---------
*is what?
想转义哪个就转义哪个字符。
转义单引号的方法:1.使用两个单引号;2使用chr函数。
SQL> select '"It''s a pen",she said.'from dual;
'"IT''SAPEN",SHESAID.'
----------------------
"It's a pen",she said.
绑定变量的目的是重复利用SQL语句。
VARIABLE bd VARCHAR2(100)
BEGIN
:bd:='hello you!'; --绑定变量实用的时候要在前面加一个:号, :=是赋值。
END;
PRINT bd;
一、预定义PL/SQL数据类型
1,标量类型(Scalar,就是标准的数据类型)
2,复合类型(Composite)复合类型包含了能够被单独操作的内部组件
3,引用类型(Reference)引用类型类似于3G语言中的指针
4,LOB类型(Large Object)LOB类型的值就是一个Lob定位器。
标量类型
数字型:
BINARY_INTEGER 存储有符号整数,
PLS_INTEGER 存储有符号整数采用硬件运算,速度更快。
BINARY_FLOAT 单精度浮点数,
BINARY_DOUBLE双精度浮点数,
NUMBER存储整数或小数,范围送1E-130到1.0E126.
字符型:
CHAR 定长字符串,最大长度为32767字节,
VARCHAR 变长字符串,最大长度为32767字节,
RAW存储二进制数据或字节串,比较像VARCHAR2类型,但PL/SQL不解析它,
NCHAR存储定长国家字符集数据,
NVARCHAR2变长国家字符集数据,
LONG存储二进制数据或二进制字符串,最大长度是32760字节,已逐渐被LOB替换,不建议使用,
LONG RAW 逐渐被LOB替换。
ROWID 存储行的逻辑地址
UROWID存储行的物理地址
布尔型 BOOLEAN(真TRUE 假 FALSE)
日期型:
DATE 日期时间,
TIMESTAMP时间戳,比DATE更加精确,
TIMESTAMP WITH TIME ZONE 有时区的时间戳
TIMESTAMP WITH LOACL ZONE 本地时区的时间戳
INTERVAL YEAR TO MONTH 存储时间间隔,单位是年和月,
INTERVAL DAY TO SECOND 单位是天和秒。
Composite类型:
NESTED TABLE 嵌套表
VARRAY 可变数组(变长数组)
TABLE 表(这里不是普通的表,是一种数据类型)
RECORD 记录
Reference类型:
REF CURSOR 游标类型
LOB类型:
BFILE 存储二进制对象,实际内容存放在操作系统的文件中
BLOB存储大的二进制数据
CLOB 存储大的字符数据
NCLOB 存储大的国家字符集数据
二、用户自定义PL/SQL子类型
其实就是其他数据类型的子集。
格式:
SUBTYPE 子类型的名字 IS 基本数据类型 [(constraint)] [NOT NULL];
DELCARE
SUBTYPE sub_num IS NUMBER(5,1);
v2 sub_num;
BEGIN
NULL;
END;
here,sub_num就是NUMBER的一个子类型,并且成为了一种新的数据类型,使用这个新的数据类型可以定义变量v2。
在PL/SQL中使用SELECT语句,必须把查询结果赋予变量,into后面指定变量的名字
eg,SELECT ID,NAME INTO v_id,v_name FROM tt;
在PL/SQL中可以直接使用DML语句(insert、update、delete)和事物控制语句(commit、rollback)等
自定义异常:
PRAGMA EXCEPTION_INIT(execption_name,-Oracle_error_number);
有三种方式触发异常:
1,由oracle自动触发异常;
2,使用RAISE语句手工触发;
3,调用存储过程RAISE_APPLICATION_ERROR手工触发。
DECLARE
myecp EXCEPTION;
BEGIN
...
RAISEmyecp;
...
EXCEPTION WHEN myecp THEN
....
dbms_output.put_line('myecp error,....');
END;
DECLARE
myecp2 EXCEPTION;
PRAGMA EXCEPTION_INIT(myecp2,-20002);
BEGIN
RAISE_APPLICATION_ERROR(-20002,'data is out of list');
EXCEPTION when myecp2 THEN
DBMS_OUTPUT.PUT_LINE('Error code:' || SQLCODE ||' '||SQLERRM);
END;
Error code:-20002 ORA-20002: data is out of list
PL/SQL 过程已成功完成。
游标:
如果对多行数据进行处理,则要用到游标。一个游标是一个指定的私有SQL区(Private SQL Area)的句柄,或者是一个命名的私有SQL区,这片区域存放解析过的语句 和其他信息。
游标分为显式游标和隐式游标。
隐式游标又叫SQL游标,是在执行插入DML操作(INSERT、DELETE、UPDATE)和SELECT语句返回单条记录时由PL/SQL自动、隐含定义。隐式游标由PL/SQL自动定义、自动打开、自动关闭、不需要用户的参与。
游标属性用于返回DML和DDL执行的信息。四大属性:%FOUND、%NOTFOUND、%ISOPEN、%ROWCOUNT。%ROWCONUT的结果为整数,其他为BOOLEAN型。
%FOUND 用于判断DML语句是否该表了行,(或者判断SELECT INTO是否返回了一行或多行数据);
%NOTFOUND与found相反;
%ISOPEN,判断游标是否打开,隐式游标自动关闭,该值永远是False。
%ROWCOUNT 判断DML语句影响了多少行。
BEGIN
DELETE FROM myorder;
IF SQL%FOUND THEN
COMMIT;
ElSE
DBMS_OUTPUT.PUT_LINE('not commit');
END IF;
END;
BEGIN
INSERT INTO myorder VALUES
(12,'rice','rice that is nice');
DBMS_OUTPUT.PUT_LINE (TO_CHAR(SQL%ROWCOUNT));
END;
/
显示游标:
定义 CURSOR cursor_name IS SELECT_statement;
eg,
DECLARE
CURSOR ct IS SELECT ORDER_NAME FROM myorder;
name VARCHAR2(20);
BEGIN
OPEN ct;
LOOP
FETCH ct INTO name;
EXIT WHEN ct%NOTFOUND OR ct%NOTFOUND IS NULL;
DBMS_OUTPUT.PUT_LINE('the name is:'||to_char(name));
END LOOP;
CLOSE ct;
END;
/
the name is:rice
the name is:apple
the name is:cup
PL/SQL 过程已成功完成。
Oracel引入FOR循环,优点在于,忽略了显式的打开游标、关闭游标、从游标中提取数据等的过程。使用隐式游标,系统隐含定义了一个%ROWYTPE类型的记录。
FOR record_name IN
(cursor_name) | (query_difinition)
LOOP
statements;
END LOOP;
(query_difinition)表示如果不指定游标的名字,可以指定一个查询。
eg,
DECLARE
CURSOR ct IS SELECT ORDER_NAME FROM myorder;
name VARCHAR2(20);
BEGIN
FOR item in ct
LOOP
DBMS_OUTPUT.PUT_LINE(item.order_name);
END LOOP;
END;
/
运行结果:
rice
apple
cup
PL/SQL 过程已成功完成。
CREATE OR REPLACE PROCEDURE p_cur(p_phone1 NUMBER) --p_phone1 is the phone
AS
v_id student.id%TYPE;
v_name student.name%TYPE;
v_phone student.phone%TYPE;
CURSOR c_s(p_phone2 NUMBER) IS
SELECT id,name,phone
FROM student
WHERE phone=p_phone2;
BEGIN
OPEN c_s(p_phone1);
LOOP
FETCH c_s INTO v_id,v_name,v_phone;
EXIT WHEN c_s%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_id ||' '||v_name||' '||v_phone);
END LOOP;
CLOSE c_s;
END;
SQL> SELECT * FROM student;
ID NAME PHONE
---------- ---------- ----------
2 cat 1234
1 pig 2341201
1 Ding 1234
已选择3行。
该procedure的目的是要把phone=‘1234’的行打印出来。
SQL> EXEC p_cur('1234');--‘1234’是传入的参数。
2 cat 1234
1 Ding 1234
PL/SQL 过程已成功完成。
游标变量
其实就是指针,只是这个指针可以指向不同的查询工作区(Query Work Area),而普通游标(显示游标)总是指向相同的查询工作区。
简单的说,游标变量是一个变量,这个变量可以动态指向不同的游标,因此称为动态游标;显示游标则称为静态游标。
游标变量可以作为函数和存储过程的参数。
1 定义:
定义CURSOR类型的指针,然后再声明游标变量。
TYPE ref_type_name IS REF CURSOR [return return_type]
return_type是可选的,用于指定游标变量返回值的类型,它必须是一个记录类型(RECORD)或行类型(ROWTYPE),如果有返回类型,称之’强REF CURSOR‘,若使用强REF CURSOR,只允许把游标变量与特定查询进行关联。反之,’弱REF CURSOR‘,可以关联任何查询。
触发器是基于table、view、schema、database的,据此可以分为:
行级触发器和语句级触发器(Row Trigger,Statement Trigger)
BEFORE和AFTE
R触发器
复合触发器(Compound Trigger)
INSTEAD OF触发器
系统级触发器(Triggers on System Event)
用户级触发器(Triggers on User Events)
1 CREATE OR REPLACE PROCEDURE p_cursor (choice INT) AS 2 TYPE newcursor_type IS REF CURSOR; 3 v_cursor newcursor_type; 4 v_rec test_order%ROWTYPE; 5 BEGIN 6 IF choice = 1 THEN 7 OPEN v_cursor FOR 8 SELECT * FROM test_order; 9 ELSIF choice = 2 THEN 10 OPEN v_cursor FOR 11 SELECT * FROM fitness_member; 12 ELSIF choice = 3 THEN 13 OPEN v_cursor FOR 14 SELECT * FROM student; 15 END IF; 16 17 LOOP 18 FETCH v_cursor 19 INTO v_rec; 20 EXIT WHEN v_cursor%NOTFOUND; 21 DBMS_OUTPUT.PUT_LINE(v_rec.name); 22 END LOOP; 23 CLOSE v_cursor; 24 END;
执行:
SQL> EXEC p_cursor(1);
phone
pen
PL/SQL 过程已成功完成。
动态SQL 解决DDL语句编译出错的问题:
1 CREATE OR REPLACE PROCEDURE create_table 2 AS 3 Pstring VARCHAR2(2000); 4 BEGIN 5 Pstring := 'CREATE TABLE tp(id int, name VARCHAR2(20))'; 6 EXECUTE IMMEDIATE Pstring; 7 END;
EXECUTE create_table;
表即可创建成功。