Oracle 学习PL/SQL

先上一张实用的图:用于转义字符的。

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;

表即可创建成功。

原文地址:https://www.cnblogs.com/happinessqi/p/3351879.html