编写基本SQL语句
所有包含空值或与空值比较的表达式,结果为空值。
在各种数据类型中,只有NUMBER数据类型的默认显示是靠右对齐的,而CHAR, DATE和VARC
HAR2是靠左对齐的
DISTINCT关键字的位置紧跟在SELECT后,一旦使用,查询返回的数据不含冗余行。
当查询中包含带Primary Key 主键约束的列时,返回的数据不带冗余行,因为PK约束保证
了该列数据是不重复的。跟使用了DINSTICT关键字的作用是一样的。
SQL*PLUS 命令在SQL*PLUS环境中控制查询结果的格式,和操纵文件。
START 命令用以执行一个已储存的文件
SAVE命令用以创建一个文件
EDIT命令用以调用编辑器编辑已存文件的内容
CHANGE 是SQL*Plus的编辑命令,用于在当前一行把旧文段转换为新文段
DEL 命令用以删除文本中一行或多行文字
SPOOL命令用以把查询结果储存在一个已有文件中,注意与SAVE区别
GET命令用以一个文件的内容写进一个SQL块中
SPOOL OUT命令用以把文件的结果发送到系统打印机。
DML命令: UPDATE, INSERT, DELETE
DDL命令: ALTER, CREATE, DROP,TRUNCATE, RENAME,
DCL 命令: GRANT, REVOKE
当在限制语句NULL或NOT NULL 关键字时,不能写成 = NULL 或 <> NULL , 要写成 IS NU
LL。 因为NULL不是一个值。
Selection允许你选择表里的行(横向),Projection(投影)允许你选择表中的列(竖向)
ORDER BY 指令用于排序,如果指令中出现多列,先按第一列排序,然后第二列……
DESCRIBE 命令用于显示表和视图中的定义,包括列名,列的数据类型和长度,还有被赋以
NOT NULL约束的列。
NVL(expression1, expression2)
NVL 函数用以把一个空值转换为一个实值,如:
NVL(100/quantity, 0) ,要是quantity为空值,该函数返回一个0。
表达式中出现空值,或任何与空值比较结果都为空值
对数据进行限制和排序
当一个表被赋予表别名(不时列别名)时,应在所有能应用表别名的地方使用,包括SELE
CT,WHERE 和GROUP BY 子句。
列别名不能用于WHERE子句
运算符的计算次序:1 所有的比较运算符, 2 AND , 3 OR
NULL值不能跟任何值比较,所以不能使用=NULL,>NULL, !=NULL, 只能用IS NULL .
当ORDER BY 子句中对多列排序,会按先按紧跟其后的第一列升序排,再按第二列…….
在升序排列中,NULL值排在最后。
单行函数
常用的单行函数有:
LOWER(column/expression) ,UPPER(column/expression) ,INITCAP(column/expression)
,
CONCAT (column1/expression1,column2/expression2) ,SUBSTR (column/expression, m
[,n])
LENGTH(column/expression),NVL(column1/expression1, column2/expression2)
数字函数:ROUND(column/expression, n),TRUNC(column/expression,n), MOD(m,n)
日期函数:MONTHS_BETWEEN(date1, date2) , ADD_MONTHS(date, n) , NEXT_DAY(date,’
char’) , LAST_DAY(date) , ROUND , TRUNC
重点:
SUBSTR (column/expression, m[,n]) 用于对字符串进行截取操作,从第m个位置开始,把
其后的连续n个字符的部分截取下来,如果m位负值,则从末尾开始计算。
LENGTH(column/expression) 用于返回表达式中的字符数,注意返回的是NUMBER。
NVL(column1/expression1, column2/expression2)用于把列中的空值转化为另一个值,但
该值数据类型必须与列中数据类型一样,否则必须使用转换函数。如:NVL ( id,“no n
umber”)是错的, 正确:NVL (TO_CHAR( id),“no number”)
ROUND和TRUNC函数能用于NUMBER和DATE类型数据,不能用于字符型数据,
ROUND(order_date, 'YEAR')把 '23-MAY-00' 舍入为 '01-JAN-00'
ROUND(order_date, 'MONTH')把 '23-MAY-00' 舍入为 '01-MAY-00'
两个日期相减结果为天数,日期减天数结果为日期,天数减日期…….什么也不是,返回错
误,
日期中RR与YY的区别,RR格式对日期作类似于舍入的操作,YY格式对日期作类似于截取的
操作
Current year specified date RR format YY format
1995 27-oct-95 1995 1995
1995 27-oct-17 2017 1917
2001 27-oct-17 2017 2017
2001 27-oct-95 1995 2095
显示多个表中的数据
不等值连接的(+)加在不含对应值的一边,但返回的将是等号另一边列的不符合连接条
件的数据。
不等值连接的典型例子:与A表中的a列对应的B表中的b列包含有空值的行,而且这些行需
要显示。
要在SELECT语句中使用等值连接来连接n个表,最少的连接条件是n-1。
在外部连接中,关键字 =和and可以使用,in 和or 不可使用
使用组函数集合数据
常用组函数:AVG(DISTINCT| ALL | n) , COUNT (DISTINCT| ALL | expr) ,
MAX(DISTINCT| ALL | expr) , MIN(DISTINCT| ALL | expr) ,
STDDEV(DISTINCT| ALL | n) , SUM(DISTINCT| ALL | n) ,
VARIANCE(DISTINCT| ALL | n) ,
GROUP BY 子句中不能使用列别名
SELECT 子句中出现多个列和组函数时,组函数外的所有列必须出现在GROUP BY 子句中。
限制组函数不能用WHERE子句,只能用HAVING子句
WHERE子句对整个查询限制,HAVING只对组函数限制,
当MIN函数用于字符类型的列时,列中数据第一位字母最前的会显示。
查询语句的顺序
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
COUNT 函数所用的列包含空值时,空值行被忽略。
编写子查询
子查询中不能使用GROUP BY 子句
如果子查询返回的数据超过一行,则必须使用多行比较运算符(IN, NOT IN)
子查询不能用与INSERT语句的VALUES子句中,能用于WHERE, HAVING, FROM,
CREATE VIEW , CREATE TABLE 语法, INSERT 语句的INTO子句中 和UPDATE语句的SET子句
中
多列子查询
如果子查询返回数据包括空值,整个查询将不返回数据,为避免这种情况,可在子查询中
使用NVL函数。
!=ALL作用跟NOT IN 一样
在FROM子句里使用子查询等于定义了数据源,免除使用视图的必要。
使用SQL*PLUS产生可读输出
SQL*PLUS 命令中的START命令用于运行一个已存文件,用符号@可实现同样的功能。
SQL命令ACCEPT的典型用法
ACCEPT id PROMPT 'Please enter the student id:
注意不要漏了PRMOPT。
SET LINESIZE 50
这个语句的作用是把每行显示的字符值设置为50。
要指定每页显示的行的数值,用关键字PAGESIZE;要设置LONG类型数据显示的最大宽度,
用关键字LONG ;要设置查询返回记录的最大值,用关键字FEEDBACK。
&的用法
COLUMN product_name HEADING 'Product Name' FORMAT A20
这是编辑格式命令语句,实现了两项功能:1 把 PRODUCT_NAME 列设置为以 'Product Na
me'开头;2 把该列的显示宽度设置为20。
操纵数据
DCL 和DDL命令的执行会导致一次隐式提交,之前未提交的操作(包括DML 命令)都会提交
写入数据文件。
UPDATE table SET column 语句中使用子查询的典型用法:
UPDATE inventory SET price =
(SELECT price * 1.10 FROM inventory WHERE description = 'Cable')
WHERE description IN('Copper Wire', 'Cable');
注意由于使用了单行运算符“=”,这时子查询返回的数据必须为一行,否则会返回错误。
INSERT INTO table(column1,column2.......) VALUES value
该语句执行后,只会在表中插入一行数据。
在表中插入数据时要注意几项:1 表中带 NOT NULL约束的列,这些列必须在目标列中。
2 插入数据的数据类型必须跟表中的对应列相同。
3 数据长度不能超过对应列限定的最大值。
QUIT 是SQL*PLUS命令,用以结束一个SQL*PLUS的对话。
EXIT 是PL/SQL命令,用以结束一个循环。
DELETE命令会删除表中的行,是DML语句,提交后会永久删除,但表的结构会保留。
但你对一表执行了DML语句的INSERT操作时,但没有提交,别人可以同时访问该表,但看不
到你所作的修改,由于对象被加锁,所以别人不能作同样的修改。
数据库崩溃会导致一次自动回滚。
如果A表中的a列在B表中拥有一个外键约束,在你删除B表记录之前,你必须先删除A表中的
所有子记录。如果你尝试在A表中插入一个记录,而B表中不存在它的副记录的会得到一个
违反约束的错误。
创建和管理表
数据库会分配一定的空间从而定义表的大小,所以表的大小不用指定。表可容纳最多1000
列。表可在用户使用数据库的同时创建,而且表的结构可在表联机时修改。
如没有指定,数据类型为CHAR的列默认长度为1。这个长度的范围是1到2000。
当一个列中数据的精度未知(如可能是4,4.35或4.3567),定义这列的数据类型应使用N
UMBER数据类型,而不是NUMBER(p,s) 数据类型,NUMBER(p,s)用于定点数。LONG数据类型
用于长度不定,最大值为2G的字符型数据。
RENAME语句的语法 : RENAME old name TO new name; 注意要是表名中包含空格,符号或
数字,必须使用双引号。
TRUNCATE TABLE table 命令把表中的所有行删除,并存储容量参数重置为定义值,该命令
是DDL命令,不能回滚, DROP TABLE命令把表的行,相关的索引和表结构一并删除,但不能
释放存储空间。要成功执行TRUNCATE TABLE 命令,你必须拥有该表或拥有DELETE TABLE的
系统权限。
在CREATE TABLE子句中使用子查询,新表中的列数必须与子查询返回的列数相等,列位置
对应。另外,除NOT NULL约束外,新列不会继承源列的所有约束。
你不能对一列重命名。在表中添加一列时,你不能指定该列的位置,它会被默认放置在最
后。你可以为一列增加长度。 通常当一列包含数据时,你不能修改该列的数据类型,不能
减少一列的长度,但当列中包含空值或你不改变列的大小时,你可以把CHAR 转换为VARCH
AR2数据类型。
在DROP TABLE table命令后加上CASCADE CONSTRAINTS回把表中的相关约束一并删除。如命
令:"DROP TABLE employee CASCADE CONSTRAINTS;"会把employee表中的数据,结构,和
相关约束一并删除。
ORACLE的表名必须以字母开头,表名中可包含数字0-9,符号:“$”,“_”,“#”。表
名不是大小写敏感的,如没指定,在创建表时默认为大写。
同一个用户不能拥有两个同名的对象,即表的命名不能重复。
如在创建新表时通过子查询引用另一表的列,无需为新列定义数据类型,因为数据类型在
这里是可继承的,除非你在新表中把这些列改了名。
当你创建一个数据类型为VARCHAR2的列时,必须指定长度。
其他数据库对象
在创建同义词时,语句中出现PRIVATE 和OR REPLACE 是无效的。在你自己的方案(schem
a)中创建同义词时,方案名不是必须的。如果方案的主人希望所有用户能访问自己方案重
的表,应使用PUBILIC关键字。语法:
CREATE [PUBILIC] SYNONYM synonym
FOR object ;
CURRVAL伪列用于在当前序列中检索连续序列号,它能用在UPDATE语句的SET子句中和INSE
RT语句的VALUES子句中,还可以用在INSERT语句的子查询的SELECT列表中。但不能用于视
图的SELECT语句和带HAVING子句的SELECT语句中。
要删除一个自己的序列,你必须拥有DROP SEQUENCE权限,要删除别人的序列,你必须拥有
DROP ANY SEQUENCE权限。
如果创建序列时没有指定参数值,ORACLE服务器预分配的默认值20会使用。
定义序列的语法:
CREATE SEQUENCE name
[INCREMENT BY n] ;指定序列以n递增,如果没指定,默认值1会使用
[START WITH n] ;由n开始计数
[(MAXVALUE n | NOMAXVALUE)] ;设置最大值n或不设置最大值
[(MINVALUE n | NOMINVALUE)] ;设置最小值n或不设置最小值
[(CYCLE | NOCYCLE)] ;当达到最大值时循环或不循环
[(CACHE n | NOCACHE)] ;预分配缓存大小,默认为20
不是任何情况创建索引都能提高效率,要是在不适合创建索引的情况下创建了索引,反而
会降低效率。
应当创建索引的情况:
1 列中包含的值范围很大. 2 列中包含大量空值
3 在WHERE子句或连接条件中经常使用多个列 4 表很大,但经常查看的行不足2-4%。
不应当使用索引的情况:
1 表很小 2 某列在查询的条件中不常使用
3 经常查看的行大于2-4% 4 表经常更新。
由于序列号时独立于表存储的,所以一个序列可用于多个表中。
要显示一序列值的下一值,查询伪表SYS.DUAL,如:
SELECT parts_id.NEXTVAL FROM SYS.DUAL;
这里的parts_id是序列名。
创建索引语法:
CREATE INDEX index_name ON table_name (column[, column] . . .);
创建视图
修改一个视图最简单的方法是使用带OR REPLACE的 CREATE VIEW语句,这允许视图的旧版
本被代替,避免了删除视图和重建视图的必要,要是删除了视图,你必须在新视图上重新
给对象授权。
视图其实是提供一个窗口,让用户对视图所在的基表进行查询和数据操作,所以用户在视
图上的修改会影响基表,要避免这种情况,应在CREATE VIEW语句中使用WITH READ ONLY
选项,即把视图设置为只读。例如:
CREATE VIEW parts_456874_vu AS SELECT id_number, description, quantity
FROM inventory WHERE manufacturer_id = 456874 WITH READ ONLY;
要是WITH READ ONLY换成WITH CHECK OPTION,则指明只有允许被视图访问的行才能被插入
或更新。
当视图定义包含了GROUP BY子句,关键字DISTINCT,或视图中没有包括基表中所有带NOT
NULL 约束的列时,不能在视图上进行DML操作(包括删除,修改,插入数据)。
USER_VIEWS数据字典显示用户所拥有的视图的描述,ALL_VIEWS数据字典显示用户有权访问
的视图的描述,ALL_OBJECTS数据字典显示用户有权访问的对象(包括视图)的信息,USE
R_OBJECTS数据字典显示用户所拥有的对象的描述。
在视图中进行插入操作,必须注意基表中带NOT NULL 约束的列不被忽略。
DESCRIBE 是SQL*PLUS命令,用于显示表和视图的结构,同义词,或指定函数和过程的详述
。
视图实际上是一个逻辑表,可基于多个表或视图
定义视图时不能包括ORDER BY子句。
包含约束
只有NOT NULL约束只能在列级定义,PRIMARY KEY , FOREIGN KEY , UNIQUE和CHECK既能在
列级又能在表级定义。
ALTER TABLE inventory
DISABLE CONSTRAINT inventory_id_number_pk CASCADE;
在这里,DISABLE语法的作用是禁用inventory表中的 PRIMARY KEY约束,而添加CASCADE则
表示相关的完整性约束也一并禁用。
AKTER TABLE 命令可为一个现有的表添加一个约束,为一个列添加NOT NULL 约束,只能使
用MODIFY子句,但需注意的是,添加NOT NULL约束时,必须符合以下两个条件中的一个:
1.表中没有数据 2.添加约束的目标行没有空值。
PRIMARY KEY 约束所在列必须不包含空值和重复值,要是你试图在该列插入数据,系统会
返回一个错误。
控制用户访问
INDEX对象权限可被授予一个用户,但不能授予一个角色(role)。它允许用户使用CREAT
E INDEX
命令在一个表上创建索引。对象权限用于在表,视图,序列和过程上执行特殊操作。
CREATE SESSION, DROP USER, 和 BACKUP ANY TABLE,这些是系统权限,系统权限用于执行
数据定义和数据控制命令,和其他数据导向性行为。
要是你想通过是用PUBILIC关键字使所有用户能对表A进行SELECT查询,你必须拥有该表,
或被授予带WITH GRANT OPTION,对该表进行的SELECT查询的权限。要是别人对你授权的语
句中包含WITH GRANT OPTION选项,你可以把得到的该权限授予别人。
一旦你创建了一个表,你自动拥有查询该表和在表上授权的能力。
*只有拥有DBA权限或ALTER UAER权限的用户才能替普通用户修改密码。
*一旦用户被授权允许连接数据库,他们就能够修改自己的密码,而无需拥有 ALTER USER
权限。
REVOKE references ON inventory FROM joe CASCADE CONSTRAINTS;
这命令实现了两个作用:1 所有由joe创建的FOREIGN KEY 约束被删除
2 他创建 FOREIGN KEY约束的能力被取消了。
GRANT ALL ON inventory TO joe;
这命令使用了关键字ALL,向joe授予了在inventory表上ALTER, INDEX, INSERT, REFERENC
ES, SELECT, UPDATE, 和DELETE的权限。
要是你想通过命令REVOKE来回收用户A的某一权限,那你必须是当初的授权人。
要能创建用户,你必须拥有CREATE USER权限。要想有权访问数据库,你需拥有CREATE SE
SSION权限。要想在任何方案(schema)中创建和删除次表,你必须拥有CREATE ANY TABL
E 和DROP ANY TABLE权限,要想在自己的方案(schema)中创建和删除次表,你必须拥有
CREATE TABLE 和DROP TABLE权限。
对象权限REFERENCE只能授予用户,不能授予角色(role)。
ORACLE数据字典
DICTIONARY数据字典提供用户可以访问的数据字典表和视图的描述。
USER_OBJECTS显示用户拥有的对象。 USER_VIEWS显示用户拥有的视图。
USER_TABLES显示用户可以访问的表。ALL_TABLES显示用户可以访问的表。
ALL_VIEWS显示用户可以访问的视图。
USER_CATALOG显示用户拥有的所有表,视图,同义词和序列。
COMMENT ON TABLE命令用于在数据字典里添加关于表,视图或快照的注释。
USER_CONS_COLUMNS显示带约束的列。
DBA_CONS_COLUMNS显示数据库里的所有表,视图和同义词。
ALL_COL_PRIVS_RECD显示当前用户的权限情况,而该用户是通过角色,公众或直接授权的
被授权者(grantee)。例:你被授予在CUSTOMER表的LAST_NAME 列和FIRST_NAME列的SEL
ECT权限,而你想显示拥有该表的方案(schema),应查询该数据字典。
ALL_COL_PRIVS_MADE显示用户拥有的列上的授权描述,和用户授出权限的描述。例:
要显示所有被你授予在EMP_ID列上拥有SELECT权限的用户,应查询该表。
USER_TAB_PRIVS_MADE显示在表上拥有权限的用户。例:要想显示被你在INVENTORY
表上拥有UPDATE权限的用户,应查询该表。
ALL_前缀的数据字典显示用户可以访问的对象名。
USER_前缀的数据字典显示用户拥有的所有对象。
DBA_前缀的数据字典显示数据库的所有对象。
V$ 前缀的数据字典数据库服务器性能信息。通常是DBA用于显示系统的统计表和动态性能
表。
声明变量
一个新的量可在执行部分(executable section)被赋予初始值。
变量在声明部分(declaration section)被声明和初始化。
PL/SQL 变量可用于操纵数据(如计算),而无需访问数据库。PL/SQL 变量可在其他涉及
变量的应用环境里再使用。PL/SQL 变量可用于暂时存储数据。
一个PL/SQL块由三部分组成:声明部分(Declarative),执行部分(Executable),异常
处理部分(Exception Handling)。
BOOLEAN是个逻辑变量,它的值只能是TRUE, FALSE 和NULL。
在声明一个PL/SQL参数时,可以使用赋值运算符 := 为该参数赋初值。如果没有为参数赋
初值,参数会被设置为null。如果参数被定义NOT NULL约束,那么就必须赋初值。
一个语句里只能声明一个变量。声明变量的语法:
identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr]
编写可执行语句
一旦一个变量被声明,它可以在所有的子嵌套块中引用,但不能在任何外部块中引用。一
个变量不能在嵌套块的执行部分被声明。
在一个PL/SQL块里的三个部分,声明部分包含变量,常数,游标和用户定义可在其他部分
引用的的异常,执行部分包含以BEGIN开始的主程序,如用于操纵数据的SQL语句等,异常
处理部分用于指定执行部分出现异常情况时所执行的动作。
在内部块(inner block)中声明的变量不能在外部块(outer block)引用,也可以说,
在嵌套块(nested block)里声明的变量不能在封闭块(enclosing block)引用,而在封
闭块定义的变量可以在嵌套块中以引用。例:
1. BEGIN
2. DECLARE
3. v_new_tech_id NUMBER := 879563;
4. v_old_tech_id NUMBER := 874512;
5. v_rows_updated NUMBER := 1;
6. BEGIN
7. UPDATE service
8. SET technician_id = v_new_tech_id
9. WHERE technician_id = v_old_tech_id;
10. v_rows_updated := SQL%ROWCOUNT;
11. END;
12. TEXT_IO.PUT_LINE (TO_CHAR(v_rows_updated));
13. END;
第12行出错,在外部块中引用了内部块中声明的变量v_rows_updated。
要执行一个已存的block.sql文件,使用以下语法:
START block.sql
一个嵌套块成为封闭块里的一个可执行语句,一个块可嵌套在任何允许放置可执行语句的
地方,包括执行部分和异常处理部分。
PL/SQL表达式不能包含组函数,但一个PL/SQL块里的SQL语句可以。
当一个语句中有混合的数据类型时,PL/SQL可以动态转变。如:想把一个NUMBER值存进一
个VARCHAR2的变量里,PL/SQL会动态地把NUMBER值转变为VARCHAR2类型的字符值。
PL/SQL表达式可以包含SQL函数。
嵌套块里的语句不能包含一个异常段。
单行注释应以双下划线( -- )为前缀,多行注释应在 /* */ 之中。
PL/SQL中的SELECT语句必须使用INTO子句。
为避免PL/SQL编码的含糊,ORACLE推荐以下PL/SQL标识符的命名协定:
1. SQL*Plus substitution variable (SQL*Plus替代变量)p_name
2. Variable (变量)v_name
3. Constant (常量)c_name
4. SQL*Plus global variable(SQL*Plus共用变量) g_name
5. Exception(异常) e_name
与ORACLE服务器交互
外显游标属性用于检验DML语句的结果,在PL/SQL中可以给游标应用四种属性:
SQL%ROWCOUNT 受最近执行的SQL语句影响的行的数目。(一个整数值)
SQL%FOUND Boolean属性,如果最近的SQL语句影响了一行或多行,其值为TRUE。
SQL%NOTFOUND Boolean属性,如果最近的SQL语句没有影响任何行,其值为TRUE。
SQL%ISOPEN 总是为FALSE,原因是PL/SQL总是它们结束执行后立即关闭内隐游标。
PL/SQL不支持DDL 和DCL 命令。
在PL/SQL块中,使用SELECT语句从数据库检索数据,必须使用INTO子句,而该SELECT语句
必须只返回一行,否则会产生错误。
PL/SQL的DML语句里不能使用IF THEN语句。
如果PL/SQL块中的SELECT语句返回超过一行数据,会产生TOO_MANY_ROWS异常,如果没有返
回数据,会产生NO_DATA_FOUND 异常,这些异常可以在块的异常处理部分俘获。
编写控件结构
条件控制结构(IF语句)
语法: IF condition THEN
statements ;
[ELSIF condition THEN
statements ;]
[ELSE
statements ;]
END IF ;
可允许无限量个 ELSIF子句,但最多只能有一个ELSE 子句。
如果控制性BOOLEAN条件(condition)为TRUE,相关的语句序列将被执行,如果为FALSE或
NULL,相关语句序列将被忽略。
优先级按语句执行顺序排列,IF子句为最高优先级,如果该语句的condition为TRUE,以下
的ELSIF和ELSE语句将被忽略,直接跳到END IF,如此类推。
循环语句:
1 基本循环,语法:
LOOP
statements1;
……
EXIT [WHEN condition];
END LOOP;
当EXIT WHEN子句的condition为TRUE时,循环结束。
2 FOR 循环,语法:
FOR index in [REVERSE]
Lower_bound…upper_bound LOOP
statements1;
statements2;
……
END LOOP;
当index到达上限时,循环结束。
3 WHILE 循环,语法:
WHILE condition LOOP
statements1;
statements2;
……
END LOOP;
当condition的BOOLEAN值为FALSE时,循环结束。
嵌套循环的标签放置在《 》中,然后放置在LOOP前。
BOOLEAN逻辑关系:
FALSE AND TRUE = FALSE FALSE AND NULL=FALSE TRUE AND NULL=NULL
FALSE OR TRUE = TRUE FALSE OR NULL=NULL TRUE OR NULL=TRUE
NULL AND(OR) NULL=NULL NULL NOT NULL =NULL
使用符合数据类型
一个PL/SQL表按两个步骤声明(declare),首先声明表的类型,然后一个PL/SQL表声明为
这种类型。例:
DECLARE
TYPE customer_table_type IS TABLE OF customer%ROWTYPE
INDEX BY BINARY_INTEGER;
customer_table customer_table_type;
声明部分必须先基于CUSTOMER表创建CUSTOMER_TABLE_TYPE 的表的数据类型,然后,把CU
STOMER_TABLE 声明成CUSTOMER_TABLE_TYPE类型。
一个记录(record)至少要有一个域,必要时可有多个域。你可以声明和引用嵌套的记录
。
记录可以定义为NOT NULL。记录中的数据可以是不同的数据类型。
DECLARE
TYPE product_table_type IS TABLE OF product%ROWTYPE
INDEX BY BINARY_INTEGER;
product_table product_table_type;
执行以下语句:
product_table(10).manufacturer_id := 5;
PL/SQL表PRODUCT_TABLE 的记录10中的MANUFACTURER_ID域被设置为5。
如果不知道数据库字段的数据类型和数目,或者运行时,数据库字段的数据类型和数目可
能会改变,可使用%ROWTYPE属性来声明一个PL/SQL域。%ROWTYPE属性可根据数据库表格或
视图的字段集合,声明一个PL/SQL记录。
BINARY_INTEGER 是主关键字(primary key)的数据类型,用作PL/SQL的索引。
编写显式游标
游标FOR循环立时不需要FETCH语句的。游标打开,在循环中每次重复提取一行,所有的行
都处理后,游标会自动关闭。
控制显式游标的四个命令里,CURSOR语句用于声明一个显式游标,定义参数。OPEN语句用
于执行查询和为引用的变量赋值,如果查询没有返回行,PL/SQL不会产生异常。FETCH语句
和INTO子句用于把当前行的值提取到变量中。在完成行的处理后,CLOSE语句会关闭游标,
释放行的活动集合,游标关闭后可以重新打开并建立新的活动集合。
显式游标用于返回多于一行的查询,隐式游标会被隐式声明,用于所有的DML语句和SELEC
T语句,每一次只处理一行。隐式游标不能通过使用OPEN, FETCH, 和CLOSE语句控制。显式
游标用于个别地处理查询返回的多行数据。
在PL/SQL的执行部分为一个记录赋值的语法:
record_name.field_name := expression;
高级显式游标概念
伴随FOR UPDATE子句一起使用的UPDATE 和 DELETE 语句中可以使用WHERE CURRENT OF 子
句。WHERE CURRENT OF字句用于更新或删除当前行。FOR UPDATE OF子句会锁定被SELECT语
句影响的行。
DECLARE
CURSOR inv_cursor (p_man_id NUMBER, p_name VARCHAR2)
IS SELECT id, name FROM inventory
WHERE manufacturer_id = p_man_id AND name = p_name;
如果你创建了一个带参数的游标,你可以在打开游标时传递值。要把值传递到游标INV_CU
RSOR,执行以下句子:OPEN inv_cursor (45094, 'Cable');
游标打开时,45094和‘Cable’会传递到参数P_MAN_ID和 P_NAME。
你可以在FROM子句中使用子查询来为查询创建一个数据源,这样的查询可以用作游标的数
据源。
如果你声明游标时定义了一个带参数的游标,你必须指定指定参数的数据类型,但不用指
定大小。
处理例外
声明部分用于声明ORACLE服务器的非预定义异常和用户定义异常,俘获非预定义异常先要
在声明部分声明异常的名称。语法:exception EXEPTION;
然后把声明的异常和标准的ORACLE服务器错误编号相关联,使用EXCEPTION_INIT语句,语
法:PRAGMA EXCEPTION_INIT (exception,error_number);
俘获用户自定义异常,先要在声明部分声明用户自定义异常的名称,语法:
exception EXEPTION;
然后在执行部分,使用RAISE语句显式引发异常,语法:RAISE exception;
当一个子块处理异常后,它会正常结束,并且控制在封闭块(enclosing block)的子块E
ND语句后恢复。如果PL/SQL引发了异常,而当前块没有该异常的处理程序,异常会在封闭
块中传播,直到它找到一个处理程序。如果上述块均未处理该异常,这将会在主机环境中
引起一个未处理异常。当异常传播到封闭块时,块的其余部分将被绕过。
一些预定义的异常:
NO_DATA_FOUND 单行SELECT查询没有返回数据。
TOO_MANY_ROWS 单行SELECT查询返回多行数据。
INCALID_CURSOR 发生非法游标操作。
ZERO_DIVIDE 试图被0除。
DUP_VAL_ON_INDEX 试图在具有唯一索引的字段中插入重复值。
WHEN OTHERS子句放置在所有其他异常处理自居的后面,用于所有未显示列出的异常。
所有包含空值或与空值比较的表达式,结果为空值。
在各种数据类型中,只有NUMBER数据类型的默认显示是靠右对齐的,而CHAR, DATE和VARC
HAR2是靠左对齐的
DISTINCT关键字的位置紧跟在SELECT后,一旦使用,查询返回的数据不含冗余行。
当查询中包含带Primary Key 主键约束的列时,返回的数据不带冗余行,因为PK约束保证
了该列数据是不重复的。跟使用了DINSTICT关键字的作用是一样的。
SQL*PLUS 命令在SQL*PLUS环境中控制查询结果的格式,和操纵文件。
START 命令用以执行一个已储存的文件
SAVE命令用以创建一个文件
EDIT命令用以调用编辑器编辑已存文件的内容
CHANGE 是SQL*Plus的编辑命令,用于在当前一行把旧文段转换为新文段
DEL 命令用以删除文本中一行或多行文字
SPOOL命令用以把查询结果储存在一个已有文件中,注意与SAVE区别
GET命令用以一个文件的内容写进一个SQL块中
SPOOL OUT命令用以把文件的结果发送到系统打印机。
DML命令: UPDATE, INSERT, DELETE
DDL命令: ALTER, CREATE, DROP,TRUNCATE, RENAME,
DCL 命令: GRANT, REVOKE
当在限制语句NULL或NOT NULL 关键字时,不能写成 = NULL 或 <> NULL , 要写成 IS NU
LL。 因为NULL不是一个值。
Selection允许你选择表里的行(横向),Projection(投影)允许你选择表中的列(竖向)
ORDER BY 指令用于排序,如果指令中出现多列,先按第一列排序,然后第二列……
DESCRIBE 命令用于显示表和视图中的定义,包括列名,列的数据类型和长度,还有被赋以
NOT NULL约束的列。
NVL(expression1, expression2)
NVL 函数用以把一个空值转换为一个实值,如:
NVL(100/quantity, 0) ,要是quantity为空值,该函数返回一个0。
表达式中出现空值,或任何与空值比较结果都为空值
对数据进行限制和排序
当一个表被赋予表别名(不时列别名)时,应在所有能应用表别名的地方使用,包括SELE
CT,WHERE 和GROUP BY 子句。
列别名不能用于WHERE子句
运算符的计算次序:1 所有的比较运算符, 2 AND , 3 OR
NULL值不能跟任何值比较,所以不能使用=NULL,>NULL, !=NULL, 只能用IS NULL .
当ORDER BY 子句中对多列排序,会按先按紧跟其后的第一列升序排,再按第二列…….
在升序排列中,NULL值排在最后。
单行函数
常用的单行函数有:
LOWER(column/expression) ,UPPER(column/expression) ,INITCAP(column/expression)
,
CONCAT (column1/expression1,column2/expression2) ,SUBSTR (column/expression, m
[,n])
LENGTH(column/expression),NVL(column1/expression1, column2/expression2)
数字函数:ROUND(column/expression, n),TRUNC(column/expression,n), MOD(m,n)
日期函数:MONTHS_BETWEEN(date1, date2) , ADD_MONTHS(date, n) , NEXT_DAY(date,’
char’) , LAST_DAY(date) , ROUND , TRUNC
重点:
SUBSTR (column/expression, m[,n]) 用于对字符串进行截取操作,从第m个位置开始,把
其后的连续n个字符的部分截取下来,如果m位负值,则从末尾开始计算。
LENGTH(column/expression) 用于返回表达式中的字符数,注意返回的是NUMBER。
NVL(column1/expression1, column2/expression2)用于把列中的空值转化为另一个值,但
该值数据类型必须与列中数据类型一样,否则必须使用转换函数。如:NVL ( id,“no n
umber”)是错的, 正确:NVL (TO_CHAR( id),“no number”)
ROUND和TRUNC函数能用于NUMBER和DATE类型数据,不能用于字符型数据,
ROUND(order_date, 'YEAR')把 '23-MAY-00' 舍入为 '01-JAN-00'
ROUND(order_date, 'MONTH')把 '23-MAY-00' 舍入为 '01-MAY-00'
两个日期相减结果为天数,日期减天数结果为日期,天数减日期…….什么也不是,返回错
误,
日期中RR与YY的区别,RR格式对日期作类似于舍入的操作,YY格式对日期作类似于截取的
操作
Current year specified date RR format YY format
1995 27-oct-95 1995 1995
1995 27-oct-17 2017 1917
2001 27-oct-17 2017 2017
2001 27-oct-95 1995 2095
显示多个表中的数据
不等值连接的(+)加在不含对应值的一边,但返回的将是等号另一边列的不符合连接条
件的数据。
不等值连接的典型例子:与A表中的a列对应的B表中的b列包含有空值的行,而且这些行需
要显示。
要在SELECT语句中使用等值连接来连接n个表,最少的连接条件是n-1。
在外部连接中,关键字 =和and可以使用,in 和or 不可使用
使用组函数集合数据
常用组函数:AVG(DISTINCT| ALL | n) , COUNT (DISTINCT| ALL | expr) ,
MAX(DISTINCT| ALL | expr) , MIN(DISTINCT| ALL | expr) ,
STDDEV(DISTINCT| ALL | n) , SUM(DISTINCT| ALL | n) ,
VARIANCE(DISTINCT| ALL | n) ,
GROUP BY 子句中不能使用列别名
SELECT 子句中出现多个列和组函数时,组函数外的所有列必须出现在GROUP BY 子句中。
限制组函数不能用WHERE子句,只能用HAVING子句
WHERE子句对整个查询限制,HAVING只对组函数限制,
当MIN函数用于字符类型的列时,列中数据第一位字母最前的会显示。
查询语句的顺序
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
COUNT 函数所用的列包含空值时,空值行被忽略。
编写子查询
子查询中不能使用GROUP BY 子句
如果子查询返回的数据超过一行,则必须使用多行比较运算符(IN, NOT IN)
子查询不能用与INSERT语句的VALUES子句中,能用于WHERE, HAVING, FROM,
CREATE VIEW , CREATE TABLE 语法, INSERT 语句的INTO子句中 和UPDATE语句的SET子句
中
多列子查询
如果子查询返回数据包括空值,整个查询将不返回数据,为避免这种情况,可在子查询中
使用NVL函数。
!=ALL作用跟NOT IN 一样
在FROM子句里使用子查询等于定义了数据源,免除使用视图的必要。
使用SQL*PLUS产生可读输出
SQL*PLUS 命令中的START命令用于运行一个已存文件,用符号@可实现同样的功能。
SQL命令ACCEPT的典型用法
ACCEPT id PROMPT 'Please enter the student id:
注意不要漏了PRMOPT。
SET LINESIZE 50
这个语句的作用是把每行显示的字符值设置为50。
要指定每页显示的行的数值,用关键字PAGESIZE;要设置LONG类型数据显示的最大宽度,
用关键字LONG ;要设置查询返回记录的最大值,用关键字FEEDBACK。
&的用法
COLUMN product_name HEADING 'Product Name' FORMAT A20
这是编辑格式命令语句,实现了两项功能:1 把 PRODUCT_NAME 列设置为以 'Product Na
me'开头;2 把该列的显示宽度设置为20。
操纵数据
DCL 和DDL命令的执行会导致一次隐式提交,之前未提交的操作(包括DML 命令)都会提交
写入数据文件。
UPDATE table SET column 语句中使用子查询的典型用法:
UPDATE inventory SET price =
(SELECT price * 1.10 FROM inventory WHERE description = 'Cable')
WHERE description IN('Copper Wire', 'Cable');
注意由于使用了单行运算符“=”,这时子查询返回的数据必须为一行,否则会返回错误。
INSERT INTO table(column1,column2.......) VALUES value
该语句执行后,只会在表中插入一行数据。
在表中插入数据时要注意几项:1 表中带 NOT NULL约束的列,这些列必须在目标列中。
2 插入数据的数据类型必须跟表中的对应列相同。
3 数据长度不能超过对应列限定的最大值。
QUIT 是SQL*PLUS命令,用以结束一个SQL*PLUS的对话。
EXIT 是PL/SQL命令,用以结束一个循环。
DELETE命令会删除表中的行,是DML语句,提交后会永久删除,但表的结构会保留。
但你对一表执行了DML语句的INSERT操作时,但没有提交,别人可以同时访问该表,但看不
到你所作的修改,由于对象被加锁,所以别人不能作同样的修改。
数据库崩溃会导致一次自动回滚。
如果A表中的a列在B表中拥有一个外键约束,在你删除B表记录之前,你必须先删除A表中的
所有子记录。如果你尝试在A表中插入一个记录,而B表中不存在它的副记录的会得到一个
违反约束的错误。
创建和管理表
数据库会分配一定的空间从而定义表的大小,所以表的大小不用指定。表可容纳最多1000
列。表可在用户使用数据库的同时创建,而且表的结构可在表联机时修改。
如没有指定,数据类型为CHAR的列默认长度为1。这个长度的范围是1到2000。
当一个列中数据的精度未知(如可能是4,4.35或4.3567),定义这列的数据类型应使用N
UMBER数据类型,而不是NUMBER(p,s) 数据类型,NUMBER(p,s)用于定点数。LONG数据类型
用于长度不定,最大值为2G的字符型数据。
RENAME语句的语法 : RENAME old name TO new name; 注意要是表名中包含空格,符号或
数字,必须使用双引号。
TRUNCATE TABLE table 命令把表中的所有行删除,并存储容量参数重置为定义值,该命令
是DDL命令,不能回滚, DROP TABLE命令把表的行,相关的索引和表结构一并删除,但不能
释放存储空间。要成功执行TRUNCATE TABLE 命令,你必须拥有该表或拥有DELETE TABLE的
系统权限。
在CREATE TABLE子句中使用子查询,新表中的列数必须与子查询返回的列数相等,列位置
对应。另外,除NOT NULL约束外,新列不会继承源列的所有约束。
你不能对一列重命名。在表中添加一列时,你不能指定该列的位置,它会被默认放置在最
后。你可以为一列增加长度。 通常当一列包含数据时,你不能修改该列的数据类型,不能
减少一列的长度,但当列中包含空值或你不改变列的大小时,你可以把CHAR 转换为VARCH
AR2数据类型。
在DROP TABLE table命令后加上CASCADE CONSTRAINTS回把表中的相关约束一并删除。如命
令:"DROP TABLE employee CASCADE CONSTRAINTS;"会把employee表中的数据,结构,和
相关约束一并删除。
ORACLE的表名必须以字母开头,表名中可包含数字0-9,符号:“$”,“_”,“#”。表
名不是大小写敏感的,如没指定,在创建表时默认为大写。
同一个用户不能拥有两个同名的对象,即表的命名不能重复。
如在创建新表时通过子查询引用另一表的列,无需为新列定义数据类型,因为数据类型在
这里是可继承的,除非你在新表中把这些列改了名。
当你创建一个数据类型为VARCHAR2的列时,必须指定长度。
其他数据库对象
在创建同义词时,语句中出现PRIVATE 和OR REPLACE 是无效的。在你自己的方案(schem
a)中创建同义词时,方案名不是必须的。如果方案的主人希望所有用户能访问自己方案重
的表,应使用PUBILIC关键字。语法:
CREATE [PUBILIC] SYNONYM synonym
FOR object ;
CURRVAL伪列用于在当前序列中检索连续序列号,它能用在UPDATE语句的SET子句中和INSE
RT语句的VALUES子句中,还可以用在INSERT语句的子查询的SELECT列表中。但不能用于视
图的SELECT语句和带HAVING子句的SELECT语句中。
要删除一个自己的序列,你必须拥有DROP SEQUENCE权限,要删除别人的序列,你必须拥有
DROP ANY SEQUENCE权限。
如果创建序列时没有指定参数值,ORACLE服务器预分配的默认值20会使用。
定义序列的语法:
CREATE SEQUENCE name
[INCREMENT BY n] ;指定序列以n递增,如果没指定,默认值1会使用
[START WITH n] ;由n开始计数
[(MAXVALUE n | NOMAXVALUE)] ;设置最大值n或不设置最大值
[(MINVALUE n | NOMINVALUE)] ;设置最小值n或不设置最小值
[(CYCLE | NOCYCLE)] ;当达到最大值时循环或不循环
[(CACHE n | NOCACHE)] ;预分配缓存大小,默认为20
不是任何情况创建索引都能提高效率,要是在不适合创建索引的情况下创建了索引,反而
会降低效率。
应当创建索引的情况:
1 列中包含的值范围很大. 2 列中包含大量空值
3 在WHERE子句或连接条件中经常使用多个列 4 表很大,但经常查看的行不足2-4%。
不应当使用索引的情况:
1 表很小 2 某列在查询的条件中不常使用
3 经常查看的行大于2-4% 4 表经常更新。
由于序列号时独立于表存储的,所以一个序列可用于多个表中。
要显示一序列值的下一值,查询伪表SYS.DUAL,如:
SELECT parts_id.NEXTVAL FROM SYS.DUAL;
这里的parts_id是序列名。
创建索引语法:
CREATE INDEX index_name ON table_name (column[, column] . . .);
创建视图
修改一个视图最简单的方法是使用带OR REPLACE的 CREATE VIEW语句,这允许视图的旧版
本被代替,避免了删除视图和重建视图的必要,要是删除了视图,你必须在新视图上重新
给对象授权。
视图其实是提供一个窗口,让用户对视图所在的基表进行查询和数据操作,所以用户在视
图上的修改会影响基表,要避免这种情况,应在CREATE VIEW语句中使用WITH READ ONLY
选项,即把视图设置为只读。例如:
CREATE VIEW parts_456874_vu AS SELECT id_number, description, quantity
FROM inventory WHERE manufacturer_id = 456874 WITH READ ONLY;
要是WITH READ ONLY换成WITH CHECK OPTION,则指明只有允许被视图访问的行才能被插入
或更新。
当视图定义包含了GROUP BY子句,关键字DISTINCT,或视图中没有包括基表中所有带NOT
NULL 约束的列时,不能在视图上进行DML操作(包括删除,修改,插入数据)。
USER_VIEWS数据字典显示用户所拥有的视图的描述,ALL_VIEWS数据字典显示用户有权访问
的视图的描述,ALL_OBJECTS数据字典显示用户有权访问的对象(包括视图)的信息,USE
R_OBJECTS数据字典显示用户所拥有的对象的描述。
在视图中进行插入操作,必须注意基表中带NOT NULL 约束的列不被忽略。
DESCRIBE 是SQL*PLUS命令,用于显示表和视图的结构,同义词,或指定函数和过程的详述
。
视图实际上是一个逻辑表,可基于多个表或视图
定义视图时不能包括ORDER BY子句。
包含约束
只有NOT NULL约束只能在列级定义,PRIMARY KEY , FOREIGN KEY , UNIQUE和CHECK既能在
列级又能在表级定义。
ALTER TABLE inventory
DISABLE CONSTRAINT inventory_id_number_pk CASCADE;
在这里,DISABLE语法的作用是禁用inventory表中的 PRIMARY KEY约束,而添加CASCADE则
表示相关的完整性约束也一并禁用。
AKTER TABLE 命令可为一个现有的表添加一个约束,为一个列添加NOT NULL 约束,只能使
用MODIFY子句,但需注意的是,添加NOT NULL约束时,必须符合以下两个条件中的一个:
1.表中没有数据 2.添加约束的目标行没有空值。
PRIMARY KEY 约束所在列必须不包含空值和重复值,要是你试图在该列插入数据,系统会
返回一个错误。
控制用户访问
INDEX对象权限可被授予一个用户,但不能授予一个角色(role)。它允许用户使用CREAT
E INDEX
命令在一个表上创建索引。对象权限用于在表,视图,序列和过程上执行特殊操作。
CREATE SESSION, DROP USER, 和 BACKUP ANY TABLE,这些是系统权限,系统权限用于执行
数据定义和数据控制命令,和其他数据导向性行为。
要是你想通过是用PUBILIC关键字使所有用户能对表A进行SELECT查询,你必须拥有该表,
或被授予带WITH GRANT OPTION,对该表进行的SELECT查询的权限。要是别人对你授权的语
句中包含WITH GRANT OPTION选项,你可以把得到的该权限授予别人。
一旦你创建了一个表,你自动拥有查询该表和在表上授权的能力。
*只有拥有DBA权限或ALTER UAER权限的用户才能替普通用户修改密码。
*一旦用户被授权允许连接数据库,他们就能够修改自己的密码,而无需拥有 ALTER USER
权限。
REVOKE references ON inventory FROM joe CASCADE CONSTRAINTS;
这命令实现了两个作用:1 所有由joe创建的FOREIGN KEY 约束被删除
2 他创建 FOREIGN KEY约束的能力被取消了。
GRANT ALL ON inventory TO joe;
这命令使用了关键字ALL,向joe授予了在inventory表上ALTER, INDEX, INSERT, REFERENC
ES, SELECT, UPDATE, 和DELETE的权限。
要是你想通过命令REVOKE来回收用户A的某一权限,那你必须是当初的授权人。
要能创建用户,你必须拥有CREATE USER权限。要想有权访问数据库,你需拥有CREATE SE
SSION权限。要想在任何方案(schema)中创建和删除次表,你必须拥有CREATE ANY TABL
E 和DROP ANY TABLE权限,要想在自己的方案(schema)中创建和删除次表,你必须拥有
CREATE TABLE 和DROP TABLE权限。
对象权限REFERENCE只能授予用户,不能授予角色(role)。
ORACLE数据字典
DICTIONARY数据字典提供用户可以访问的数据字典表和视图的描述。
USER_OBJECTS显示用户拥有的对象。 USER_VIEWS显示用户拥有的视图。
USER_TABLES显示用户可以访问的表。ALL_TABLES显示用户可以访问的表。
ALL_VIEWS显示用户可以访问的视图。
USER_CATALOG显示用户拥有的所有表,视图,同义词和序列。
COMMENT ON TABLE命令用于在数据字典里添加关于表,视图或快照的注释。
USER_CONS_COLUMNS显示带约束的列。
DBA_CONS_COLUMNS显示数据库里的所有表,视图和同义词。
ALL_COL_PRIVS_RECD显示当前用户的权限情况,而该用户是通过角色,公众或直接授权的
被授权者(grantee)。例:你被授予在CUSTOMER表的LAST_NAME 列和FIRST_NAME列的SEL
ECT权限,而你想显示拥有该表的方案(schema),应查询该数据字典。
ALL_COL_PRIVS_MADE显示用户拥有的列上的授权描述,和用户授出权限的描述。例:
要显示所有被你授予在EMP_ID列上拥有SELECT权限的用户,应查询该表。
USER_TAB_PRIVS_MADE显示在表上拥有权限的用户。例:要想显示被你在INVENTORY
表上拥有UPDATE权限的用户,应查询该表。
ALL_前缀的数据字典显示用户可以访问的对象名。
USER_前缀的数据字典显示用户拥有的所有对象。
DBA_前缀的数据字典显示数据库的所有对象。
V$ 前缀的数据字典数据库服务器性能信息。通常是DBA用于显示系统的统计表和动态性能
表。
声明变量
一个新的量可在执行部分(executable section)被赋予初始值。
变量在声明部分(declaration section)被声明和初始化。
PL/SQL 变量可用于操纵数据(如计算),而无需访问数据库。PL/SQL 变量可在其他涉及
变量的应用环境里再使用。PL/SQL 变量可用于暂时存储数据。
一个PL/SQL块由三部分组成:声明部分(Declarative),执行部分(Executable),异常
处理部分(Exception Handling)。
BOOLEAN是个逻辑变量,它的值只能是TRUE, FALSE 和NULL。
在声明一个PL/SQL参数时,可以使用赋值运算符 := 为该参数赋初值。如果没有为参数赋
初值,参数会被设置为null。如果参数被定义NOT NULL约束,那么就必须赋初值。
一个语句里只能声明一个变量。声明变量的语法:
identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr]
编写可执行语句
一旦一个变量被声明,它可以在所有的子嵌套块中引用,但不能在任何外部块中引用。一
个变量不能在嵌套块的执行部分被声明。
在一个PL/SQL块里的三个部分,声明部分包含变量,常数,游标和用户定义可在其他部分
引用的的异常,执行部分包含以BEGIN开始的主程序,如用于操纵数据的SQL语句等,异常
处理部分用于指定执行部分出现异常情况时所执行的动作。
在内部块(inner block)中声明的变量不能在外部块(outer block)引用,也可以说,
在嵌套块(nested block)里声明的变量不能在封闭块(enclosing block)引用,而在封
闭块定义的变量可以在嵌套块中以引用。例:
1. BEGIN
2. DECLARE
3. v_new_tech_id NUMBER := 879563;
4. v_old_tech_id NUMBER := 874512;
5. v_rows_updated NUMBER := 1;
6. BEGIN
7. UPDATE service
8. SET technician_id = v_new_tech_id
9. WHERE technician_id = v_old_tech_id;
10. v_rows_updated := SQL%ROWCOUNT;
11. END;
12. TEXT_IO.PUT_LINE (TO_CHAR(v_rows_updated));
13. END;
第12行出错,在外部块中引用了内部块中声明的变量v_rows_updated。
要执行一个已存的block.sql文件,使用以下语法:
START block.sql
一个嵌套块成为封闭块里的一个可执行语句,一个块可嵌套在任何允许放置可执行语句的
地方,包括执行部分和异常处理部分。
PL/SQL表达式不能包含组函数,但一个PL/SQL块里的SQL语句可以。
当一个语句中有混合的数据类型时,PL/SQL可以动态转变。如:想把一个NUMBER值存进一
个VARCHAR2的变量里,PL/SQL会动态地把NUMBER值转变为VARCHAR2类型的字符值。
PL/SQL表达式可以包含SQL函数。
嵌套块里的语句不能包含一个异常段。
单行注释应以双下划线( -- )为前缀,多行注释应在 /* */ 之中。
PL/SQL中的SELECT语句必须使用INTO子句。
为避免PL/SQL编码的含糊,ORACLE推荐以下PL/SQL标识符的命名协定:
1. SQL*Plus substitution variable (SQL*Plus替代变量)p_name
2. Variable (变量)v_name
3. Constant (常量)c_name
4. SQL*Plus global variable(SQL*Plus共用变量) g_name
5. Exception(异常) e_name
与ORACLE服务器交互
外显游标属性用于检验DML语句的结果,在PL/SQL中可以给游标应用四种属性:
SQL%ROWCOUNT 受最近执行的SQL语句影响的行的数目。(一个整数值)
SQL%FOUND Boolean属性,如果最近的SQL语句影响了一行或多行,其值为TRUE。
SQL%NOTFOUND Boolean属性,如果最近的SQL语句没有影响任何行,其值为TRUE。
SQL%ISOPEN 总是为FALSE,原因是PL/SQL总是它们结束执行后立即关闭内隐游标。
PL/SQL不支持DDL 和DCL 命令。
在PL/SQL块中,使用SELECT语句从数据库检索数据,必须使用INTO子句,而该SELECT语句
必须只返回一行,否则会产生错误。
PL/SQL的DML语句里不能使用IF THEN语句。
如果PL/SQL块中的SELECT语句返回超过一行数据,会产生TOO_MANY_ROWS异常,如果没有返
回数据,会产生NO_DATA_FOUND 异常,这些异常可以在块的异常处理部分俘获。
编写控件结构
条件控制结构(IF语句)
语法: IF condition THEN
statements ;
[ELSIF condition THEN
statements ;]
[ELSE
statements ;]
END IF ;
可允许无限量个 ELSIF子句,但最多只能有一个ELSE 子句。
如果控制性BOOLEAN条件(condition)为TRUE,相关的语句序列将被执行,如果为FALSE或
NULL,相关语句序列将被忽略。
优先级按语句执行顺序排列,IF子句为最高优先级,如果该语句的condition为TRUE,以下
的ELSIF和ELSE语句将被忽略,直接跳到END IF,如此类推。
循环语句:
1 基本循环,语法:
LOOP
statements1;
……
EXIT [WHEN condition];
END LOOP;
当EXIT WHEN子句的condition为TRUE时,循环结束。
2 FOR 循环,语法:
FOR index in [REVERSE]
Lower_bound…upper_bound LOOP
statements1;
statements2;
……
END LOOP;
当index到达上限时,循环结束。
3 WHILE 循环,语法:
WHILE condition LOOP
statements1;
statements2;
……
END LOOP;
当condition的BOOLEAN值为FALSE时,循环结束。
嵌套循环的标签放置在《 》中,然后放置在LOOP前。
BOOLEAN逻辑关系:
FALSE AND TRUE = FALSE FALSE AND NULL=FALSE TRUE AND NULL=NULL
FALSE OR TRUE = TRUE FALSE OR NULL=NULL TRUE OR NULL=TRUE
NULL AND(OR) NULL=NULL NULL NOT NULL =NULL
使用符合数据类型
一个PL/SQL表按两个步骤声明(declare),首先声明表的类型,然后一个PL/SQL表声明为
这种类型。例:
DECLARE
TYPE customer_table_type IS TABLE OF customer%ROWTYPE
INDEX BY BINARY_INTEGER;
customer_table customer_table_type;
声明部分必须先基于CUSTOMER表创建CUSTOMER_TABLE_TYPE 的表的数据类型,然后,把CU
STOMER_TABLE 声明成CUSTOMER_TABLE_TYPE类型。
一个记录(record)至少要有一个域,必要时可有多个域。你可以声明和引用嵌套的记录
。
记录可以定义为NOT NULL。记录中的数据可以是不同的数据类型。
DECLARE
TYPE product_table_type IS TABLE OF product%ROWTYPE
INDEX BY BINARY_INTEGER;
product_table product_table_type;
执行以下语句:
product_table(10).manufacturer_id := 5;
PL/SQL表PRODUCT_TABLE 的记录10中的MANUFACTURER_ID域被设置为5。
如果不知道数据库字段的数据类型和数目,或者运行时,数据库字段的数据类型和数目可
能会改变,可使用%ROWTYPE属性来声明一个PL/SQL域。%ROWTYPE属性可根据数据库表格或
视图的字段集合,声明一个PL/SQL记录。
BINARY_INTEGER 是主关键字(primary key)的数据类型,用作PL/SQL的索引。
编写显式游标
游标FOR循环立时不需要FETCH语句的。游标打开,在循环中每次重复提取一行,所有的行
都处理后,游标会自动关闭。
控制显式游标的四个命令里,CURSOR语句用于声明一个显式游标,定义参数。OPEN语句用
于执行查询和为引用的变量赋值,如果查询没有返回行,PL/SQL不会产生异常。FETCH语句
和INTO子句用于把当前行的值提取到变量中。在完成行的处理后,CLOSE语句会关闭游标,
释放行的活动集合,游标关闭后可以重新打开并建立新的活动集合。
显式游标用于返回多于一行的查询,隐式游标会被隐式声明,用于所有的DML语句和SELEC
T语句,每一次只处理一行。隐式游标不能通过使用OPEN, FETCH, 和CLOSE语句控制。显式
游标用于个别地处理查询返回的多行数据。
在PL/SQL的执行部分为一个记录赋值的语法:
record_name.field_name := expression;
高级显式游标概念
伴随FOR UPDATE子句一起使用的UPDATE 和 DELETE 语句中可以使用WHERE CURRENT OF 子
句。WHERE CURRENT OF字句用于更新或删除当前行。FOR UPDATE OF子句会锁定被SELECT语
句影响的行。
DECLARE
CURSOR inv_cursor (p_man_id NUMBER, p_name VARCHAR2)
IS SELECT id, name FROM inventory
WHERE manufacturer_id = p_man_id AND name = p_name;
如果你创建了一个带参数的游标,你可以在打开游标时传递值。要把值传递到游标INV_CU
RSOR,执行以下句子:OPEN inv_cursor (45094, 'Cable');
游标打开时,45094和‘Cable’会传递到参数P_MAN_ID和 P_NAME。
你可以在FROM子句中使用子查询来为查询创建一个数据源,这样的查询可以用作游标的数
据源。
如果你声明游标时定义了一个带参数的游标,你必须指定指定参数的数据类型,但不用指
定大小。
处理例外
声明部分用于声明ORACLE服务器的非预定义异常和用户定义异常,俘获非预定义异常先要
在声明部分声明异常的名称。语法:exception EXEPTION;
然后把声明的异常和标准的ORACLE服务器错误编号相关联,使用EXCEPTION_INIT语句,语
法:PRAGMA EXCEPTION_INIT (exception,error_number);
俘获用户自定义异常,先要在声明部分声明用户自定义异常的名称,语法:
exception EXEPTION;
然后在执行部分,使用RAISE语句显式引发异常,语法:RAISE exception;
当一个子块处理异常后,它会正常结束,并且控制在封闭块(enclosing block)的子块E
ND语句后恢复。如果PL/SQL引发了异常,而当前块没有该异常的处理程序,异常会在封闭
块中传播,直到它找到一个处理程序。如果上述块均未处理该异常,这将会在主机环境中
引起一个未处理异常。当异常传播到封闭块时,块的其余部分将被绕过。
一些预定义的异常:
NO_DATA_FOUND 单行SELECT查询没有返回数据。
TOO_MANY_ROWS 单行SELECT查询返回多行数据。
INCALID_CURSOR 发生非法游标操作。
ZERO_DIVIDE 试图被0除。
DUP_VAL_ON_INDEX 试图在具有唯一索引的字段中插入重复值。
WHEN OTHERS子句放置在所有其他异常处理自居的后面,用于所有未显示列出的异常。