ocp11g培训内部教材051课堂笔记(047)SQLcphmvp

第四章、WHERE子句中数据的比较和运算...15

4.1隐式比较与显式比较:...15

4.2运算符优先级:...15

4.3用BETWEENAND操作符来查询出在某一范围内的行.15

4.4模糊查询及其通配符:...16

4.5用IN操作符来检验一个值是否在一个列表中...16

4.6交互输入变量符&和&&的用途:...17

4.7使用逻辑操作符:AND;OR;NOT.18

第五章分组函数...19

5.1五个分组函数...19

5.2在组函数中使用NVL函数...19

5.3GROUPBY创建数据组...20

5.4分组函数的嵌套...20

第六章、数据限定与排序...21

6.1简单查询语句执行顺序...21

6.2排序(orderby)21

6.3空值(null)22

第七章、复杂查询之一:多表连接技术...26

7.1简单查询的解析方法:...26

7.2多表连接...26

7.3集合运算...32

7.4集合运算中只要类型能匹配上就可以连接...34

7.5关于orderby使用别名排序的问题:...35

第八章、复杂查询(下):子查询与多列子查询...37

8.1单行子查询采用单行比较运算符(>,<,=,<>)37

8.2在多行子查询中使用all38

8.3在多行子查询中使用any.39

8.4在多行子查询中使用in.39

8.5多列子查询多行多列...40

8.6非成对比较多列子查询...43

8.7notin在子查询中的空值问题:...43

8.8from子句中使用子查询(这个也叫内联视图)...44

8.9关联子查询与非关联子查询...45

8.10简单查询与复杂查询练习题:...47

第九章用户访问控制...50

9.1创建和管理数据库用户账户...50

9.2管理概要文件...51

9.3系统权限,对象权限,角色...53

第十章Oracle的事务和锁...61

10.1什么是事务...61

10.2事务的开始和结束...61

10.3Oracle的事务保存点功能...62

10.4读一致性与锁定...62

10.5加锁模式...62

10.6五种表锁的含义:...63

10.7死锁和解锁...64

第十一章,索引...66

11.1索引结构及特点...66

11.2索引适用那些情况...66

11.3索引的类型与选项:...67

11.4索引扫描方式...67

11.5索引的碎片问题...71

11.6索引不可见(invisible),11g新特性...72

第十二章约束...73

12.1什么是约束...73

12.2约束的语法:...73

12.3五种约束的写法...73

第十三章视图...84

13.1为什么使用视图...84

13.2语法...84

13.3复杂视图的更新,键保留表概念。(不考)...86

第十四章同义词...87

14.1私有同义词;87

14.2公有同义词;大家都可使用,87

14.3关于同义词的几个要点:...87

第十五章序列...88

15.1序列是生成唯一整数值的结构,它的典型用途是用于主键值。...88

15.2几点说明:...88

第十六章外部表...89

第十七章insert语句总结...90

17.1单行insert90

17.2多行insert92

17.3Multitableinsert93

第十八章DML语句-MERGE.98

第十九章几个语句的用法...102

19.1with语句...102

19.2DDL操作及模式对象...103

19.3groupbyrollup,groupbycube,以及grouping的用法...104

第二十章ORACLE分层查询startwith&connectby.109

20.1树结构查询...109

20.2树结构的描述...110

20.3关于PRIOR.111

20.4定义查找起始节点...112

20.5使用LEVEL.114

20.6节点和分支的裁剪...115

20.7排序显示...117

21.1Timezone引入的背景...118

21.2模拟北京、东京、伦敦三地的时区,进一步理解Timezone。...119

21.4关于numtoyminterval函数和numtodsinterval函数...122

第二十二章正则表达式...123

22.1ORACLE中的支持正则表达式的函数主要有下面四个:...123

22.2POSIX正则表达式由标准的元字符(metacharacters)所构成:...123

22.3字符簇:...124

22.4OracleREGEXP_LIKE介绍和例子...124

数据操纵语言:DML:select;insert;delete;update.对表、试图操作查询、插入、删除、更新。

数据定义语言:DDL:create;alter;drop;truncate,rename.对数据库操作创建表、修改表、删除表、删除表内容保留表结构。

Delete与truncate的区别。

事务控制语言:TCL:commit;savepoint;rollback.保存断点

数据控制语言:DCL:grant;revoke.赋予权限、删除权限。

是指函数一次能处理表行的行数,函数总是接受零个或多个输入参数,但总是返回一个预定数据类型的结果。

单行函数:查询对每一行数据都返回一个结果。

SQL>selectempno,lower(ename)fromemp;

多行函数:对多数据行的群组进行操作,并且每组返回一个结果。(典型的是聚合函数)

SQL>selectsum(sal)fromemp;

lower('SQLCourse')----->sqlcourse返回小写

upper('sqlcourse')----->SQLCOURSE返回大写

initcap('SQLCourse')----->SqlCourse返回首字母大写

concat('good','string')---->goodstring拼接//只能拼接2个字符串多个字符嵌套有没有限制?

substr('String',1,3)---->str从第1位开始截取3位数

SQL>selectsubstr('qsedr456',3,5)fromdual;

SUBST

-----

edr45

instr('t#i#m#r#a#n#','#',3)--->从第3位起始找第一次出现#字符在那个绝对位置

SQL>selectinstr('123#45#2222','#',1)fromdual;

INSTR('123#45#2222','#',1)

--------------------------

4

length('String')---->6长度

lpad('first',10,'$')左填充——>$$$$$first

rpad(676768,10,'*')右填充——>676768****

round对指定的值做四舍五入,round(p,s)s为正数时,表示小数点后要保留的位数,s也可以为负数,意义不大。不写位数默认为1

round:按指定精度对十进制数四舍五入,如:round(45.923,1),结果,45.9

round(45.923,0),结果,46

round(45.923,-1),结果,50保留小数点左边的一位。

SQL>selectround(45.96,1)fromdual;

ROUND(45.96,1)

--------------

46

trunc对指定的值取整trunc(p,s)

trunc:按指定精度截断十进制数,如:trunc(45.923,1),结果,45.9

trunc(45.923),结果,45不写位数默认为0

trunc(45.923,-1),结果,40

mod返回除法后的余数

SQL>selectmod(100,12)fromdual;

MOD(100,12)

-----------

因为日期在oracle里是以数字形式存储的,所以可对它进行加减运算,计算是以天为单位。

缺省格式:DD-MON-YY.

可以表示(公元前)4712至(公元)9999

还有一种表示日期的格式DD-MON-RR02-03-13即191303.02。02-03-51即205103.02

SQL>selectto_date('2003-11-0400:00:00','YYYY-MM-DDHH24:Mi:ss')FROMdual;

MONTHS_BETWEEN//计算两个日期之间的月数

SQL>selectmonths_between('1994-04-01','1992-04-01')mmfromdual;

考点:很容易认为单行函数返回的数据类型与函数类型一致,那是对于数字函数类型而言是这样,但字符和日期函数可以返回任何数据类型的值。比如

instr是函数是字符型的,months_between函数是日期型的,但它们返回的都是数值,是一个数,不是字符或日期。

ADD_MONTHS//给日期增加月份

SQL>selectadd_months('1992-03-01',4)amfromdual;

LAST_DAY//日期当前月份的最后一天

SQL>selectlast_day('1989-03-28')l_dfromdual;

ROUND(p,s),TRUNC(p,s)在日期中的应用,如何舍入要看具体情况,s是MONTH按30天计,应该是14舍15入,s是YEAR则按6舍7入计算。S是year时候,如果月份是7月,则四舍五入比如,日期是1981-07-02round之后结果是1982-01-01

SQL>selectemployee_id,hire_date,round(hire_date,'year')asroundfromemployeeswhereemployee_id=194;

EMPLOYEE_IDHIRE_DATEROUND

-------------------------------------------------

1941998-07-0100:00:001999-01-0100:00:00

SQL>

SELECTempno,hiredate,

round(hiredate,'MONTH')ASround,

trunc(hiredate,'MONTH')AStrunc

FROMemp

WHEREempno=7788;

round(hiredate,'YEAR')ASround,

trunc(hiredate,'YEAR')AStrunc

WHEREempno=7839;

1)case函数与decode函数:

实现sql语句中的条件判断语句,具有类似高级语言中的if语句的功能。

case函数源自sql标准,decode函数源自oracle,实现功能类似,decode语法更简单些。

case函数第一种用法:

selectjob,sal,casejob

when'ANALYST'thenSAL*1.1

when'CLERK'thenSAL*1.15

when'MANAGER'thenSAL*1.20

elsesalend

REVISED_SALARY

fromemp

/

case函数第二种用法:

selectjob,sal,

casewhenjob='ANALYST'thenSAL*1.1

whenjob='CLERK'thenSAL*1.15

whenjob='MANAGER'thenSAL*1.20

2)decode函数用法:

SELECTjob,sal,

DECODE(job,'ANALYST',SAL*1.1,

'CLERK',SAL*1.15,

'MANAGER',SAL*1.20,

SAL)

以上三种写法结果都是一样的:

JOBSALREVISED_SALARY

---------------------------------

CLERK800920

SALESMAN16001600

SALESMAN12501250

MANAGER29753570

MANAGER28503420

MANAGER24502940

ANALYST30003300

PRESIDENT50005000

SALESMAN15001500

CLERK11001265

CLERK9501092.5

CLERK13001495

已选择14行。

3)DISTINCT(去重)的用法:

SQL>selectdistinctjobfromemp;//消除表行重复值。

JOB

---------

CLERK

SALESMAN

PRESIDENT

MANAGER

ANALYST

SQL>selectdistinctjob,deptnofromemp;//重复值是后面的字段组合起来考虑的

JOBDEPTNO

-------------------

MANAGER20

PRESIDENT10

CLERK10

SALESMAN30

ANALYST20

MANAGER30

MANAGER10

CLERK30

CLERK20

4)CHR()函数和ASCII()函数

chr()函数将ASCII码转换为字符:ASCII码–》字符

ascii()函数将字符转换为ASCII码:字符–》ASCII码

在oracle中chr()函数和ascii()是一对反函数。

求字符对应的ASCII值

SQL>selectASCII('A')FROMdual;

ASCII('A')

----------

65

SQL>selectchr(65)fromdual;

C

-

A

5)处理空值的几种函数(见第六章)

1、字符型,2、数值型,3、日期型,4、大对象型

char固定字符,最长2000个空间上固定长度不管字符多少。查询快。长度可扩展不可以缩短。

varchar2可变长字符,最长4000个,最小值是1

nchar/nvarchar2NCHAR/NVARCHAR2类型的列使用国家字符集

raw和longraw固定/可变长度的二进制数据长度最2G,可存放多媒体图象声音等。(老类型,逐步淘汰)

LONG可变长的字符串数据,最长2G,LONG具有VARCHAR2列的特性,一个表中最多一个LONG列。(老类型,逐步淘汰)。

SQL>createtableb(xchar(10),yvarchar2(10));

表已创建。

SQL>altertablebmodifyxvarchar2(8);

表已更改。

SQL>insertintobvalues('a','abc');

已创建1行。

SQL>altertablebmodifyxvarchar2(2);

SQL>altertablebmodifyxchar(8);

SQL>insertintobvalues('ab','abcde');

SQL>altertablebmodifyxchar(6);

altertablebmodifyxchar(6)

*

第1行出现错误:

ORA-01441:无法减小列长度,因为一些值过大

SQL>altertablebmodifyyvarchars(2);

altertablebmodifyyvarchars(2)

ORA-01735:无效的ALTERTABLE选项

SQL>altertablebmodifyyvarchar2(2);

altertablebmodifyyvarchar2(2)

number(p,s)实数类型,以可变长度的内部格式来存储数字。这个内部格式精度可以高达38位。最大可支持到38个9。

int整数型,number的子类型,范围同上最大可支持到38个9。

扩展知识:

双精度、浮点数值类型。

date日期的普通形式,表示精度只能到秒级。

timestamp日期的扩展形式,表示精度可达秒后小数点9位(10亿分之1秒)。

timestampwithtimezone带时区

timestampwithlocaltimezone时区转换后的本地日期

大对象是10g引入的,在11g中又重新定义,在一个表的字段里存储大容量数据,最长可能达到4G

CLOB:用来存储单字节的字符数据,包含在数据库内。

NCLOB:用来存储多字节的字符数据国家字符集

BLOB:用于存储二进制数据,包含在数据库内。涵盖了CLOB,反之不一定成立。

BFILE:存储在数据库之外的二进制文件中,这个文件中的数据只能被只读访问。但该文件不被修改。

不能用insert语句插入大对象数据。

CLOB,NCLOB,BLOB都是内部的LOB类型,没有LONG只能有一列的限制

如要保存图片、文本文件、Word文件各自最好用哪种数据类型的呢?

BLOB最好,LONGRAW也不错,但LONG是oracle将要废弃的类型,因此建议用LOB。

当然说将要废弃,但还没有完全废弃,比如oracle11g里的重要视图dba_views,对于text(视图定义)仍然沿用了LONG类型。

隐性类型转换和显性类型转换。

是oracle自动完成类型转换,即在一些明显意图的表达式上oracle可以自主完成数据类型的转换。如:

SQL>SELECT'12.5'+11FROMdual;

'12.5'+11

23.5

SQL>SELECT10+('12.5'||11)FROMdual;

10+('12.5'||11)

---------------

22.511

SQL>SELECT10+('12.5'||'11')FROMdual;

10+('12.5'||'11')

-----------------

是强制完成类型转换(推荐),转换函数形式有三种:

TO_CHAR

TO_DATE

TO_NUMBER

1)日期-->字符

SQL>selectename,hiredate,to_char(hiredate,'DD-MON-YY')month_hiredfromempwhereename='SCOTT';

ENAMEHIREDATEMONTH_HIRED

-------------------------------------------

SCOTT1987-04-1900:00:0019-4月-87

fm压缩空格或左边的'0'

SQL>selectename,hiredate,to_char(hiredate,'fmyyyy-mm-dd')month_hiredfromempwhereename='SCOTT';

ENAMEHIREDATEMONTH_HIRE

---------------------------------------

SCOTT1987-04-1900:00:001987-4-19

2)字符-->日期

SQL>selectto_date('1983-11-12','YYYY-MM-DD')tmp_DATEfromdual;

TMP_DATE

1983-11-1200:00:00

3)数字-->字符:9表示数字,$本地化货币字符

SQL>selectename,to_char(sal,'$99,999.99')Salaryfromempwhereename='SCOTT';

ENAMESALARY

---------------------

SCOTT$3,000.00

4)字符-->数字:

SQL>SELECTto_number('$123.45','$999.99')resultFROMdual;

RESULT

123.45

考点:使用to_number时如果使用较短的格式掩码转换数字,就会返回错误。不要混淆to_number和to_char转换。

例如:

SQL>selectto_number(123.56,'999.9')fromdual;

selectto_number(123.56,'999.9')fromdual

ORA-01722:无效数字

SQL>selectto_char(123.56,'999.9')fromdual;

TO_CHA

------

123.6

SQL>selectto_number('$123.45','$999.99')resultfromdual;

SQL>selectto_number('$123.45','$99.99')resultfromdual;

selectto_number('$123.45','$99.99')resultfromdual

SQL>selectename,hiredatefromempwherehiredate>'1982-01-01';//oracle隐式转换了

SQL>selectename,hiredatefromempwherehiredate>to_date('1982-01-01','YYYY-MM-DD');//显式

SQL>selectename,job,sal,commfromempwherejob='SALESMAN'ORjob='PRESIDENT'ANDsal>1500;

考点:条件子句使用比较运算符比较两个选项,重要的是要理解这两个选项的数据类型,如有必要可以将它们包含在单引号内。

优先级NOT>AND>OR打破优先级用括号。

SQL>SELECTename,salFROMempWHEREsalBETWEEN1000AND1500;

//between低值and高值,含低值和高值。

在where字句中使用like谓词,常使用特殊符号"%"或"_"匹配查找内容,也可使用escape可以取消特殊符号的作用。

‘%’多个,‘-’一个。

createtabletest1(namechar(10));

insertintotest1values('sFdL');

insertintotest1values('AEdLHH');

insertintotest1values('A%dMH');

commit;

SQL>select*fromtest1;

NAME

sFdL

AEdLHH

A%dMH

SQL>select*fromtest1wherenamelike'A\%%'escape'\';

SQL>SELECTempno,ename,sal,mgrFROMempWHEREmgrIN(7902,7566,7788);

SQL>select*fromemployeeswhereEMPLOYEE_IDin(100,101,102,1000000000000000);

EMPLOYEE_IDFIRST_NAMELAST_NAMEEMAILPHONE_NUMBER

-----------------------------------------------------------------------------------------------------

HIRE_DATEJOB_IDSALARYCOMMISSION_PCTMANAGER_IDDEPARTMENT_ID

----------------------------------------------------------------------------

100StevenKingSKING515.123.4567

1987-06-1700:00:00AD_PRES2400090

101NeenaKochharNKOCHHAR515.123.4568

1989-09-2100:00:00AD_VP1700010090

102LexDeHaanLDEHAAN515.123.4569

1993-01-1300:00:00AD_VP1700010090

()中的数值可以不存在在表中。

&后的变量名可以随意起名。

Sql>Setverifyoff可以关闭验证。

SQL>selectempno,enamefromempwhereempno=&empnumber;

输入empnumber的值:7788

原值1:selectempno,enamefromempwhereempno=&empnumber

新值1:selectempno,enamefromempwhereempno=7788

EMPNOENAME

--------------------

7788SCOTT

&后面是字符型的,注意单引号问题,可以有两种写法:

SQL>selectempno,enamefromempwhereename='&emp_name';

输入emp_name的值:SCOTT

原值1:selectempno,enamefromempwhereename='&emp_name'

新值1:selectempno,enamefromempwhereename='SCOTT'

SQL>selectempno,enamefromempwhereename=&emp_name;

输入emp_name的值:'SCOTT'

原值1:selectempno,enamefromempwhereename=&emp_name

&&存储了第一次输入值,使后面的相同的&不在提问,自动取代。

SQL>selectempno,ename,&&salaryfromempwheredeptno=10orderby&salary;

输入salary的值:sal

原值1:selectempno,ename,&&salaryfromempwheredeptno=10orderby&salary

新值1:selectempno,ename,salfromempwheredeptno=10orderbysal

EMPNOENAMESAL

------------------------------

7934MILLER1300

7782CLARK2450

7839KING5000

还可以使用define命令常用于批处理。

AND两个条件都为TRUE,则返回TRUE

SQL>SELECTempno,ename,job,salFROMempWHEREsal>=1100ANDjob='CLERK';

EMPNOENAMEJOBSAL

7876ADAMSCLERK1100

7934MILLERCLERK1300

OR两个条件中任何一个为TRUE,则返回TRUE

SQL>SELECTempno,ename,job,salFROMempWHEREsal>=1100ORjob='CLERK';

7369SMITHCLERK800

7499ALLENSALESMAN1600

7521WARDSALESMAN1250

7566JONESMANAGER2975

7654MARTINSALESMAN1250

......

NOT如果条件为FALSE,返回TRUE

SQL>SELECTename,jobFROMempWHEREjobNOTIN('CLERK','MANAGER','ANALYST');

ENAMEJOB

ALLENSALESMAN

WARDSALESMAN

MARTINSALESMAN

KINGPRESIDENT

TURNERSALESMAN

sum();avg();count();max();min().

数值类型可以使用所有组函数

SQL>selectsum(sal)sum,avg(sal)avg,max(sal)max,min(sal)min,count(*)countfromemp;

分组:groupby

对日期类型可以使用MIN,MAX

SQL>selectmin(hiredate),max(hiredate)fromemp;

COUNT(*)函数返回表中行的总数,包括重复行与数据列中含有空值的行,而其他分组函数的统计都不包括空值的行。(考点)

COUNT(EXPR)返回expr标识的列所含非空行的数量。

SQL>selectdeptno,avg(nvl(comm,0))fromempgroupbydeptno;在统计过程中,遇到空值,自动取值为数值0

DEPTNOAVG(NVL(COMM,0))

30366.666667-----------基数6

200

100

SQL>selectdeptno,avg(comm)fromempgroupbydeptno;

DEPTNOAVG(COMM)

30550-------------基数4

20

10

想一想上面两个例子结果为何不一样?

SQL>selectdeptno,avg(nvl(sal,0))fromempgroupbydeptno;

对分组结果进行过滤

SQL>selectdeptno,avg(sal)avgcommfromempgroupbydeptnohavingavg(sal)>2000;

SQL>selectdeptno,avg(sal)avgcommfromempwhereavg(sal)>2000groupbydeptno;//错误的,应该使用HAVING子句

HAVING必须在GROUPBY中使用,不能单独使用,且后面不能直接跟列(select中出现列)

Where后不能直接跟聚合函数。

对分组结果排序

SQL>selectdeptno,avg(nvl(sal,0))avgcommfromempgroupbydeptnoorderbyavg(nvl(sal,0));

确保SELECT列表中除了组函数的项,所有列都包含在GROUPBY子句中(考点)。

例如,错误的写法:selectempno,sum(sal)fromemp;

单行函数可以嵌套任意层,但分组函数最多可以嵌套两层。(考点)

比如:count(sum(avg)))会返回错误“ORA-00935:groupfunctionisnestedtoodeeply”.

在分组函数内可以嵌套单行函数,如:要计算各个部门ename值的平均长度之和

SQL>selectsum(avg(length(ename)))fromempgroupbydeptno;

SUM(AVG(LENGTH(ENAME)))

-----------------------

14.9666667

from,where,groupby,having,orderby,select

where限定from后面的表或视图,限定的选项只能是表的列或列函数或列表达式,where后不可以直接使用分组函数即sum();avg();count();max();min().

SQL>selectempno,jobfromempwheresal>2000;实列

SQL>selectempno,jobfromempwherelength(job)>5;列的单行函数

SQL>selectempno,jobfromempwheresal+comm>2000;列的表达式

having限定groupby的结果,限定的选项必须是groupby后的聚合函数或分组列,不可以直接使用where后的限定选项。

SQL>selectsum(sal)fromempgroupbydeptnohavingdeptno=10;

SQL>selectdeptno,sum(sal)fromempgroupbydeptnohavingsum(sal)>9000;

如果要使用分组函数及having,有条件的话先使用where删选。

1)位置:orderby语句总是在一个select语句的最后面。

2)排序可以使用列名,表达式(虚列),列别名,列的位置等都没有限制,select选项也可以没有排序列。

Orderby2(select后面的第二列)。

3)升序和降序,升序ASC(默认),DESC降序。

SQL>selectename,job,sal+commfromemporderby3descnullslast;(或first。默认为first)

4)混合排序,使用多个列进行排序,多列使用逗号隔开,可以分别在各列后面加升降序。

SQL>selectename,deptno,jobfromemporderbydeptnoasc,jobdesc;

ENAMEDEPTNOJOB

-----------------------------

KING10PRESIDENT

CLARK10MANAGER

MILLER10CLERK

JONES20MANAGER

ADAMS20CLERK

SMITH20CLERK

SCOTT20ANALYST

FORD20ANALYST

MARTIN30SALESMAN

TURNER30SALESMAN

WARD30SALESMAN

ALLEN30SALESMAN

BLAKE30MANAGER

JAMES30CLERK

空值既不是数值0,也不是字符"",

1)空值(null)的数据行将对算数表达式返回空值

SQL>selectename,sal,comm,sal+commfromemp;

ENAMESALCOMMSAL+COMM

----------------------------------------

SMITH800

ALLEN16003001900

WARD12505001750

JONES2975

MARTIN125014002650

BLAKE2850

CLARK2450

SCOTT3000

KING5000

TURNER150001500

ADAMS1100

JAMES950

FORD3000

MILLER1300

2)空值(null)的数据行将比较表达式返回空值

SQL>selectename,sal,commfromempwheresal>=comm;

ENAMESALCOMM

ALLEN1600300

WARD1250500

TURNER15000

3)非空字段与空值字段做"||"时,返回非空字段内容。连字符

SQL>selectename,sal||commfromemp;

ENAMESAL||COMM

------------------------------------------------------------------------------------------

MARTIN12501400

4)notin在子查询中的空值问题(见第八章)

5)外键值可以为null

6)空值在where子句里使用“isnull”或“isnotnull”

SQL>selectempno,mgrfromempwheremgrisnull;

SQL>selectempno,mgrfromempwheremgrisnotnull;

7)空值在update语句和insert语句可以直接使用“=null”赋值

SQL>updateempsetcomm=nullwhereempno=7788;

1)nvl(expr1,expr2)

当第一个参数不为空时取第一个值,当第一个值为NULL时,取第二个参数的值。

SQL>selectnvl(1,2)fromdual;

NVL(1,2)

1

SQL>selectnvl(null,2)fromdual;

NVL(NULL,2)

2

2)nvl2(expr1,expr2,expr3)

当第一个参数不为NULL,取第二个参数的值,当第一个参数为NULL,取第三个数的值。

SQL>selectnvl2(1,2,3)fromdual;

NVL2(1,2,3)

SQL>selectnvl2(null,2,3)fromdual;

NVL2(NULL,2,3)

3

//注意:nvl和nvl2中的第二个参数不是一回事(考点)

3)NULLIF(expr1,expr2)/*比对两个值是否一样,一样就返回为空,否则不会为空*/

当第一个参数和第二个参数相同时,返回为空,当第一个参数和第二个数不同时,返回第一个参数值,第一个参数值不允许为null。第二个可以是NULL

SQL>selectnullif(2,2)fromdual;

NULLIF(2,2)

SQL>selectnullif(1,2)fromdual;

NULLIF(1,2)

4)coalesce(expr1,expr2........)返回第一个不为空的值,如果所有参数都为空,那么返回空值。

SQL>selectcoalesce(1,2,3,4)fromdual;

COALESCE(1,2,3,4)

SQL>selectcoalesce(null,2,null,4)fromdual;

COALESCE(NULL,2,3,4)

SQL>selectcoalesce(null,null,null)fromdual;

全表扫描:指针从第一条记录开始,依次逐行处理,直到最后一条记录结束;

横向过滤+纵向筛选=结果集

两大类:等值连接和非等值连接。

等值连接:例如joinon。等值连接使用‘=’。例如e.abc=b.abce表和b表的公共列abc

交叉连接(笛卡尔积)

典型代表:内连接

外连接(左外,右外,全连接)

自连接

自然连接(隐含连接条件,自动匹配连接字段)

集合运算

范例:

createtablea(idint,namechar(10));

createtableb(idint,locchar(10));

insertintoavalues(1,'a');

insertintoavalues(2,'b');

insertintoavalues(4,'d');

insertintobvalues(1,'A');

insertintobvalues(2,'B');

insertintobvalues(3,'C');

SQL>select*froma;

IDNAME

1a

2b

4d

SQL>select*fromb;

IDLOC

1A

2B

3C

当连接条件无效或被省略时,两个表的所有行都发生连接,所有行的组合都会返回(n*m)

SQL>select*froma,b;

IDNAMEIDLOC

1a1A

1a2B

1a3C

2b1A

2b2B

2b3C

4d1A

4d2B

4d3C

已选择9行。

内联运算效率高

SQL99写法:

SQL>select*fromainnerjoinbona.id=b.id;

oracle写法:

SQL>select*froma,bwherea.id=b.id;

1)左外连接

SQL99语法:

SQL>select*fromaleftjoinbona.id=b.id;

oracle语法:

SQL>select*froma,bwherea.id=b.id(+);左联右补全。

结果:

匹配不上则补全空值。

2)右外连接

SQL>select*fromarightjoinbona.id=b.id;

SQL>select*froma,bwherea.id(+)=b.id;右联左补全。

结果

3)全外连接

SQL>select*fromafulljoinbona.id=b.id;

SQL>select*froma,bwherea.id=b.id(+)

union

select*froma,bwherea.id(+)=b.id;

必须使用别名

SQL>select*fromaa1,aa2;

IDNAMEIDNAME

1a1a

1a2b

1a4d

2b1a

2b2b

2b4d

4d1a

4d2b

4d4d

在oralce中使用naturaljoin,也就是自然连接。在Oracle中的join连接中使用using关键字,

是相对于naturaljoin的。如果是使用natrauljoin,并且两张表中如果有多个字段是具有相同的名称和数据类型的,那么这些字段都将被oracle自作主张的将他们连接起来。但实际上我们有时候是不需要这样来连接的。我们只需要将他们的多个具有相同的名称和数据类型的字段中挑选一两个。这时候我们就需要用到using关键字了。当多列匹配时,用using指定匹配的列

先看自然连接:

SQL>select*fromanaturaljoinb;

IDNAMELOC

1aA

2bB

-----两个表分别再加一个列ABC后,则有两个公共列做连接条件。

IDNAMEABC

1as

2bt

4du

IDLOCABC

1Aw

2Bt

3Cr

IDABCNAMELOC

2tbB

在oracle连接(join)中使用using关键字

SQL>selectid,a.abc,name,locfromajoinbusing(id);可以显示两个表的abc

1saA

SQL>selectid,abc,name,locfromajoinbusing(id,abc);

注意:

1、如果在使用using关键字时,而且select的结果列表项中包含了using关键字所指明的那个关键字,那么,不要在select的结果列表项中对该关键字指明它属于哪个表。

2、using中可以指定多个列名。

3、natural关键字和using关键字是互斥的,也就是说不能同时出现。

SQL>selectx,a.abc,b.abcfromajoinbusing(x);

XABCABC

----------------------------

a123123

Union,对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;包含相交的集合部分,计算一次。

UnionAll,对两个结果集进行并集操作,包括重复行,不进行排序;包含相交的集合部分,计算两次。

Intersect,对两个结果集进行交集操作,不包括重复行,同时进行默认规则的排序;

Minus,对两个结果集进行差操作,不包括重复行,同时进行默认规则的排序。

集合操作有并,交,差3种运算。

举例:

SQL>createtabledept1asselect*fromdeptwhererownum<2;从dept表中取第一行的值创建表dept1;

SQL>insertintodept1values(80,'MARKTING','BEIJING');

SQL>select*fromdept;

DEPTNODNAMELOC

-------------------------------------

10ACCOUNTINGNEWYORK

20RESEARCHDALLAS

30SALESCHICAGO

40OPERATIONSBOSTON

SQL>select*fromdept1;

80MARKTINGBEIJING

SQL>select*fromdept

2union

3select*fromdept1;

2unionall

2intersect

2minus

SQL>select*fromdept1

3select*fromdept;

如果是char类型,长度也必须一样才可以集合运算。列名可以不一样。Verchar2可以不需要长度一样。

可以将CHAR长度扩展。

SQL>createtablea(id_aint,name_achar(10));

SQL>createtableb(id_bint,name_bchar(10),salnumber(10,2));

insertintoavalues(1,'sohu');

insertintoavalues(2,'sina’);

insertintobvalues(1,'sohu',1000);

insertintobvalues(2,'yahoo',2000);

ID_ANAME_A

1sohu

2sina

ID_BNAME_BSAL

1sohu1000

2yahoo2000

SQL>selectid_a,name_afroma

3selectid_b,name_bfromb;

2yahoo

1),缺省情况下,集合运算后的结果集是按第一列隐式排序的(除unionall外)

如果不希望缺省的排序,也可以使用orderby显示排序。对整个结果集排序。

selectid_a,name_anamefroma

selectid_b,name_bnamefromb

orderbyname;

ID_ANAME

selectid_a,name_afroma

selectid_b,name_bfromb

orderby2;

2),显式orderby是参照第一个表的列元素,如果是补全的null值需要orderby,则需要使用别名。

SQL>selectid_a,name_aname,to_number(null)froma

3selectid_b,name_bname,salfromb

4orderbysal

5/

orderbysal

第4行出现错误:

ORA-00904:"SAL":标识符无效

4orderby3(第三列)

ID_ANAMETO_NUMBER(NULL)

-----------------------------------

SQL>selectid_b,name_bname,salfromb

3selectid_a,name_aname,to_number(null)froma

ID_BNAMESAL

SQL>selectid_a,name_aname,to_number(null)aafroma

3selectid_b,name_bname,salaafromb

4orderbyaa

ID_ANAMEAA

3),排序是对结果集的排序,不能分别在两表中排序,orderby只能出现一次且在最后一行;

SQL>selectid_a,name_afromaorderbyid_a

3selectid_b,name_bfromborderbyid_b;

第2行出现错误:

ORA-00933:SQL命令未正确结束

升序排列时候,NULL默认排在最后。

子查询返回的值可以被外部查询使用,这样的复合查询等于执行两个连续的查询。

内部SELECT子句只返回一行结果(单列)

SQL>selectename,sal

wheresal>(

selectsalfromemp

whereename='JONES')

和员工7369从事相同工作并且工资大于员工7876的员工的姓名和工作

SQL>selectename,job

wherejob=(

selectjob

whereempno=7369

)

and

sal>(

selectsal

whereempno=7876

(>大于最大的,<小于最小的)

SQL>selectename,salfromempwheresal>all(2000,3000,4000);

ENAMESAL

查找高于所有部门的平均工资的员工(>比子查询中返回的列表中最大的大才行)

SQL>SQL>selectename,job,sal

2fromemp

3wheresal>all(

4selectavg(sal)

5fromemp

6groupbydeptno)

7/

ENAMEJOBSAL

JONESMANAGER2975

SCOTTANALYST3000

KINGPRESIDENT5000

FORDANALYST3000

SQL>selectavg(sal)fromempgroupbydeptno;//子查询结果

AVG(SAL)

1566.66667

2175

2916.66667

(>大于最小的,<小于最大的)

>any的意思是:比子查询中返回的列表中最小的大就行,注意和all的区别,all的条件苛刻,any的条件松阔,

any强调的是只要有任意一个符合就行了,所以>any只要比最小的那个大就行了,没必要比最大的还大。

selectename,salfromempwheresal>any(2000,3000,4000);

(逐个比较是否有匹配值)

SQL>selectename,salfromempwheresalin(800,3000,4000);

NOT运算操作符可以使用在IN操作上,但不能使用在ANY,ALL操作。

SQL>selectename,salfromempwheresalnotin(800,3000,4000);

ALLEN1600

WARD1250

MARTIN1250

TURNER1500

已选择11行。

多列子查询是返回多列结果的内部SELECT语句

将WHERE子句中多个条件合并成一个

列比较有成对比较与不成对比较两种

实验准备

SQL>createtableemp1asselect*fromemp;

SQL>updateemp1setsal=1600,comm=300whereename='SMITH';//SMITH是20部门的员工

SQL>updateemp1setsal=1500,comm=300whereename='CLARK';//CLARK是10部门的员工

SQL>select*fromemp1;

EMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO

----------------------------------------------------------------------------------------

7369SMITHCLERK79021980-12-1700:00:00160030020

7499ALLENSALESMAN76981981-02-2000:00:00160030030

7521WARDSALESMAN76981981-02-2200:00:00125050030

7566JONESMANAGER78391981-04-0200:00:00297520

7654MARTINSALESMAN76981981-09-2800:00:001250140030

7698BLAKEMANAGER78391981-05-0100:00:00285030

7782CLARKMANAGER78391981-06-0900:00:00150030010

7788SCOTTANALYST75661987-04-1900:00:00300020

7839KINGPRESIDENT1981-11-1700:00:00500010

7844TURNERSALESMAN76981981-09-0800:00:001500030

7876ADAMSCLERK77881987-05-2300:00:00110020

7900JAMESCLERK76981981-12-0300:00:0095030

7902FORDANALYST75661981-12-0300:00:00300020

7934MILLERCLERK77821982-01-2300:00:00130010

查询条件:查找emp1表中是否有与30部门的员工工资和奖金相同的其他部门的员工。

(注意看一下:现在20部门的SIMTH符合这个条件,它与30部门的ALLEN有相同的工资和奖金)

成对比较多列子查询

主查询每一行中的列都要与子查询返回列表中的相应列进行比较

只有各列完全匹配时才显示主查询中的该数据行

分解一下:

第一步,我们可以先找出emp1表中30号部门的工资和奖金的结果集,(此例没有对comm的空值进行处理)

SQL>SQL>selectsal,commfromemp1wheredeptno=30;

SALCOMM

1600300

1250500

12501400

2850

15000

950

已选择6行。

第二步,列出emp1表中属于这个结果集的所有员工。

可以这样想:相当于谓词in(...)中有上面这6行内容

SQL>select*fromemp1where(sal,comm)in(selectsal,commfromemp1wheredeptno=30);必须一一对应。

上面句子相当于:

select*fromemp1where(sal,comm)in(

(1600,300),(1250,500),(1250,1400),(2850,null),(1500,0),(950,null)

);

第三步,再去掉30号部门后,就显示出了在emp1表中与30部门中任意一个员工的工资和奖金完全相同的,

但该员工不是来自30部门的员工信息。

selectename,deptno,sal,commfromemp1

where(sal,comm)in(selectsal,commfromemp1wheredeptno=30)

anddeptno<>30

ENAMEDEPTNOSALCOMM

SMITH201600300

SQL>selectename,deptno,sal,comm

fromemp1

wheresalin(

wheredeptno=30)

nvl(comm,0)in(

selectnvl(comm,0)

CLARK101500300

两个子查询返回的值分别与主查询中的sal和comm列比较

员工的工资与30部门任意一个员工相同,同时,奖金也与30部门的任意一个员工相同,则输出该员工信息。

in与notin遇到空值时情况不同,对于notin如果子查询的结果集中有空值,那么最终主查询的结果集是空。考点

查找出没有下属的员工,即普通员工,(该员工号不在mgr之列的)

SQL>selectename

whereempnonotin

(selectmgr

fromemp)

norowsselected

上面的结果不出所料,主查询没有返回记录。这个原因是在子查询中有一个空值,而对于notin这种形式,一旦子查询出现了空值,则主查询记录结果

也就返回空了。

例:排除空值的影响使用去空函数nvl

(selectnvl(mgr,0)

8rowsselected.

例:员工的工资大于他所在的部门的平均工资的话,显示其信息。

分两步来考虑:

第一步,先看看每个部门的平均工资,把这个结果集作为一个内联视图

SQL>selectdeptno,avg(sal)salavgfromempgroupbydeptno;

DEPTNOSALAVG

301566.66667

202175

102916.66667

第二步,把这个内联视图起一个别名b,然后和emp别名e做连接,满足条件即可。

selecte.ename,e.sal,e.deptno,b.salavg

fromempe,(selectdeptno,avg(sal)salavgfromempgroupbydeptno)b

wheree.deptno=b.deptnoande.sal>b.salavg

知识点:内联试图使用在from中,多表连接使用别名。

ENAMESALDEPTNOSALAVG

ALLEN1600301566.66667

JONES2975202175

BLAKE2850301566.66667

SCOTT3000202175

KING5000102916.66667

FORD3000202175

从主查询(外部)调用子查询(内部)来看,可以有分关联与非关联子查询之分

子查询部分可以独立执行,Oracle的in子查询一般用于非关联子查询,执行过程是这样的,首先执行子查询,并将获得的结果列表存放在一个加了索引

的临时表中。也就是说在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。

例:查找名称为ACCOUNTING的部门里所有员工的信息

selectename,deptnofromemp

wheredeptnoin(

selectdeptnofromdeptwheredname='ACCOUNTING')

ENAMEDEPTNO

CLARK10

KING10

MILLER10

其子查询(内部,inner)会引用主查询(外部,outer)查询中的一列或多列。在执行时,外部查询的每一行都被一次一行地传递给子查询.子查询依次读取

外部查询传递来的每一值,并将其用到子查询上,直到外部查询所有的行都处理完为止.然后返回查询结果.

同例:

selectename,deptnofromempe

selectd.deptnofromdeptdwheree.deptno=d.deptnoandd.dname='ACCOUNTING')

注意1)以上两例都是用了in查询,结果一样,但是Oracle的查询过程却截然不同。

2)in用于关联子查询效率不高,Oracle推荐使用exists()代替

SQL>selectename,deptnofromempe

whereexists(

可以是select*

其中“e.deptno=d.deptno”相当于一个关联表查询,如果你只执行括号里的语句,是会报语法错误的,这也是使用关联子查询的特点。

“exists(xxx)”就表示括号里的语句能不能查出记录,它要查的记录是否存在。因此,子查询中的“selectd.deptno”这里的“d.deptno”其实是无关紧要的,换成“*”也没问题,它只在乎括号里的数据能不能查找出来,是否存在这样的记录,如果存在,外部语句的where条件成立。

对于关联子查询,使用exists操作符可能比in更快。比较两种查询的执行有以下特点:

第一,差异在于两类查询的工作方式不同,in操作是在括号里的内容必须经过整个子表扫描之后,符合条件的内容(结果集)全部确定下来后才会进行

in的选取,而exist是逻辑判断,如果在子表逐行过滤中碰到一行符合条件,即逻辑比较为‘真’了,则立刻返回,该次子表查询也立刻结束。这就意味着它可能没有全表遍历,省去了子表后面扫描操作。

第二,dept表只有4行记录,如果是4万行,效果就出来了,比如,极端情况下,主查询第m次调用,子查询在第一条就满足了,则马上返回EXISTS='真'.那么第m次调用就结束了,也就是说子查询省去了39999行的后续扫描。所以子表越大,主表越小exists的效率越高。

第三,exists的效率是和表的数据有关的、也和表的数据的排列有关,子表遇到“真”时要看是靠前匹配,还是到靠后匹配,效果是大不一样的,当然如果不能匹配上,则EXISTS=“假”,这样的结果也是做了子表的全表扫描,同in相比的话,也并没有提高效率。

第四,in可以用于各种子查询,而exists只用于关联子查询,exists用于非关联查询是没有意义的(主查询要么返回所有结果,要么无结果。)

第五,exists是Oracle特有的,推荐使用。另外还有notin与notexists的比较,机制类似。

a)列出emp表工资最高的前三名员工信息

rownum,rowedrownum不能用大于号连接,只能用小于号或者等于号。

select*from(select*fromemporderbysaldesc)whererownum<4;

select*from(selectrownumasrn,employee_idasid,first_name||''||last_nameasname,salaryfromemployeesorderbysalarydesc);

b)列出emp表第5-第10名员工的信息(结果集的分页查询技术)

select*from(selectt1.*,rownumrnfromempt1)wherernbetween5and10;

c)从列出emp表中显示员工和经理对应关系表。(emp自连,利用笛卡尔积)

selecta.empno,a.ename,a.mgr,b.empno,b.ename,b.mgr

fromempa,empb

wherea.mgr=b.empno;

d)要求列出emp表中最高工资的员工所在工作地点,(emp+dept左外)

selecta.ename,d.locfrom

(select*fromempwheresal=

(selectmax(sal)fromemp))aleftjoindeptdona.deptno=d.deptno;

e)根据emp表和dept表组织一张新表emp1,要求新表能看到所有员工的员工号,姓名与工作地点,部门编号的对应信息。

createtableemp1as(selecte.empno,e.ename,d.loc,d.deptnofromempe,deptdwheree.deptno=d.deptno(+));

f)在e)的基础上将所有loc字段的记录修改为空值,再利用dept表更新(深入理解update语句执行过程、顺序,及关联子查询概念)

SQL>updateemp1setloc=null;

SQL>updateemp1esetloc=(selectd.locfromdeptdwheree.deptno=d.deptno);

g)三表联查,假设有三个表(显示如下),分别是emp1,title,detp要求列出各部门经理的信息,信息里包括员工编号、员工姓名、薪水、头衔、部门编号、工作地点。

表A----------表B----------------表C

表A与表B之间有公共列,表B与表C之间有公共列,即可将三个表连接。

7369SMITH800

7499ALLEN1600

7521WARD1250

7566JONES2975

7654MARTIN1250

7698BLAKE2850

7788SCOTT3000

7844TURNER1500

7876ADAMS1100

7900JAMES950

7902FORD3000

SQL>select*fromtitle;

EMPNOJOBDEPTNO

7369CLERK20

7499SALESMAN30

7521SALESMAN30

7566MANAGER20

7654SALESMAN30

7698MANAGER30

7782MANAGER10

7788ANALYST20

7839PRESIDENT10

7844SALESMAN30

7876CLERK20

7900CLERK30

7902ANALYST20

7934CLERK10

SQL>selecte.empno,e.ename,e.sal,t.job,t.deptno,d.loc

fromemp1e,titlet,deptd

wheret.deptno=d.deptno

ande.empno=t.empno

andt.job=UPPER('manager')

EMPNOENAMESALJOBDEPTNOLOC

--------------------------------------------------------------

7566JONES2975MANAGER20DALLAS

7698BLAKE2850MANAGER30CHICAGO

7782CLARK2450MANAGER10NEWYORK

Selecte.empno,e.ename,e.sal,t.job,t.deptno,d.locfromempeinnerjointitletone.empno=t.empnoinnerjoindeptdont.deptno=d.deptnowheret.job=UPPER(‘manager’)

创建一个用户,可以三种缺省:缺省表空间,缺省临时文件,缺省profile

每个用户账户都有默然的表空间,用户创建的任何对象(如表或索引)将保存在此表空间中,如果创建用户是没有指定默认表空间,那么属于数据库级的默认表空间(缺省安装时是users表空间)将应用于所有账户。Users表空间是所有用户的公共的默认表空间。

SQL>Select*fromv$tablespace;

TS#NAMEINCBIGFLAENC

----------------------------------------------------

0SYSTEMYESNOYES

1SYSAUXYESNOYES

4USERSYESNOYES

6EXAMPLEYESNOYES

8TESTYESNOYES

2UNDOTBS1YESNOYES

3TEMPNONOYES

数据库级的默认表空间可以更改

alterdatabasedefaulttablespacetablespace_name;

配额(quota)是表空间中为用户的对象使用的空间量,dba建立用户时就应该考虑限制用户的磁盘配额,否则用户可以将对他无限制配额的表空间撑爆。

--设置限额=10m

ALTERusertimquota10montest_tbs;

--限额无限=不受限

ALTERUSERtimQUOTAUNLIMITEDONtest_tbs;

--收回限额

ALTERUSERtimQUOTA0ONtest_tbs;

考点:

1)要创建表,用户必须具有执行createtable的权限,而且拥有在其中创建表的表空间上的配额。要创建表必须满足这两个条件:权限和配额。

2)用户不需要临时表空间上的配额。临时表空间是公共空间。

作用是对用户访问数据库做一些限制。有几个要点:

1)概要文件(profile)具有两个功能,一个是实施口令限制,另一个是限制会话可以占用的资源。

2)始终要实施口令控制,而对于资源限制,则只有实例参数RESOURE_LIMIT为TRUE时(默认是FALSE)才会实施(考点)。

3)系统自动使用概要文件,默认的概要文件限制很松,作用较小。

4)可以使用createprofile为用户创建它自己的概要文件,没有说明的参数就从defauleprofile的当前版本中提取。

Password_parameter部分:

Failed_login_attempts:指定在帐户被锁定之前所允许尝试登陆的的最大次数。

Password_lock_time:在到达Failed_login_attempts后锁定账户的天数。

Password_life_time:口令过期前的天数,口令在过期后仍可以使用,具体取决于Password_grace_time

Password_reuse_time:可以重新使用口令前的天数

password_reuse_max:可以重新使用口令的次数

Password_verify_function:更改口令时运行的函数名,此函数一般用于检查新口令所需的复杂程度。

Resource_parameter部分

Logical_reads_per_session:在强制终止会话前,会话可读取的块数(无论块在数据缓冲区还是磁盘)。

Logical_read_per_call:在强制终止单个语句前,此语句可读取的块数(无论块在数据缓冲区还是磁盘)。

Private_sga:对于通过共享服务器体系结构连接的会话,允许会话的会话数据在SGA中占用的字节数(KB)。

Composite_limit:前面几个参数的加权和。这是一个高级功能,其需要的配置不在OCP考试范围。

例:

1)创建一个概要文件,如果出现两次口令失误,那么将账户锁定。

SQL>createprofiletwo_errorlimitfailed_login_attempts2;

2)将概要文件分配给tim用户

SQL>alterusertimprofiletwo_error;

SQL>conntim/fdfd

ERROR:

ORA-28000:帐户已被锁定

Alterusertimaccountunlock解锁。

4)sys为tim解锁

SQL>conn/assysdba

SQL>alterusertimaccountunlock;

5)sys删掉了two_error概要文件

SQL>dropprofiletwo_error;

//profile这部分操作参数较多,使用命令有些啰嗦,可以使用EM方式来管理,比较方便。

删除profile不会删除用户。

数据库安全分为系统安全和数据安全

系统安全:用户名和口令,分配给用户的磁盘空间及用户的系统操作

数据库安全:对数据库对象的访问及操作

用户具备系统权限才能够访问数据库

具备对象权限才能访问数据库中的对象

简而言之:权限(privilege):systemprivilegeandobjectprivilege

系统权限通常由DBA授予(11g有200多种,selectdistinctprivilegefromdba_sys_privs;也可被其他用户或角色授予)

典型DBA权限

CREATEUSER

DROPUSER

BACKUPANYTABLE

SELECTANYTABLE

CREATEANYTABLE

典型用户需要的系统权限

CREATESESSION

CREATETABLE

CREATESEQUENCE

CREATEVIEW

CREATEPROCEDURE

2)objectprivilege:针对于schema(用户)的object

对象权限有8种:ALTERDELETEEXECUTEINDEXINSERTREFERENCESSELECTUPDATE

主要的常用的对象

试图

序列

过程

alter

delete

Execute

index

insert

refrerences

select

update

授予系统权限语法:

GRANTsys_privs,[role]TOuser|role|PUBLIC[WITHADMINOPTION]

//授予角色与系统权限的语法格式是一样的,所以可以并列在一个句子里赋权考点。

授予对象权限语法

GRANTobject_privsONobjectTOuser|role|PUBLIC[WITHGRANTOPTION]

创建和删除角色

CREATErolemyrole;

DROProlemyrole;

角色相当于是N多权限的集合。可以包含系统角色,权限,对象权限等。

sys:

SQL>createusertimidentifiedbytim;//建一个tim用户

SQL>conntim/tim

警告:您不再连接到ORACLE。

已连接。

SQL>grantcreatesessiontotim;//授予tim系统权限createsession

SQL>select*fromtab;

未选定行

SQL>createtablea(idint);

createtablea(idint)

ORA-01031:权限不足

SQL>grantcreatetabletotim;//授予tim系统权限createtable

tim:

ORA-01950:对表空间'USERS'无权限

SQL>grantunlimitedtablespacetotim;//授予tim系统权限unlimitedtablespace,可以无限制的使用任何表空间

SQL>alterusertimquota5monusers;//仅对于使用users表空间加上了磁盘限额。

SQL>select*fromsession_privs;

PRIVILEGE

UNLIMITEDTABLESPACE

列出oracle所有系统权限;

SQL>selectdistinctprivilegefromdba_sys_privs;

可以看出由于系统权限太过繁杂,oracle引入角色(role),通过角色得授予是的用户访问管理得以大大简化。

SQL>dropusertimcascade;

SQL>createusertimidentifiedbytim;

SQL>grantconnect,resourcetotim;两个角色赋予TIM

CREATECLUSTER

CREATETRIGGER

CREATETYPE

CREATEOPERATOR

CREATEINDEXTYPE

已选择10行。

需要注意一点:在resource角色里包含了unlimitedtablesapce权限,对于所有的表空间不限制配额,此权限太大,它包括可以访问system表空间,在实际应用中一般要将此权限收回,然后再对用户限制配额。权限不能限制配额。

SQL>createtablespacetest_tbsdatafile'/u01/oradata/timran11g/test01.dbf'size10m;

SQL>createusertimidentifiedbytimdefaulttablespacetest_tbs;

SQL>grantconnect,resourcetotim;

SQL>revokeunlimitedtablespacefromtim;

SQL>alterusertimquota10montest_tbs;

回收配额之后,不可以新建表,但是可以修改插入原来已经创建的表。

SQL>selecttablespace_name,username,max_bytesfromDBA_TS_QUOTASwhereusername='TIM';

2)系统权限里的any含义:

SQL>grantcreateanytabletotim;tim可以给任何人(usera)建表。所创建的表不在tim下,在usera下可以查询到。

SQL>createtablescott.t100(idint);

3)可以使update对象权限精确到列:赋予update某一列的权限时候,确保之前没有给过update全表的权限,如果有,先收回,在赋予。

scott:

SQL>grantselect,update(sal)onemptotim;

SQL>revokeupdate(sal)onempfromtim;

revokeupdate(sal)onempfromtim

ORA-01750:UPDATE/REFERENCES只能从整个表而不能按列REVOKE

SQL>revokeupdateonempfromtim;

撤销成功。

4)对象权限的传递与回收:WITHGRANTOPTION选项

先建立两个测试用户tim和ran(sys)

CREATEUSERtimIDENTIFIEDBYtim;GRANTCREATESESSIONTOtim;

CREATEUSERranIDENTIFIEDBYran;GRANTCREATESESSIONTOran;

GRANTSELECTONempTOtimWITHGRANTOPTION;

检查tim用户能否访问scott.emp....

tim用户把该权限分给ran用户(tim)

GRANTSELECTONscott.empTOran;

检查ran用户能否访问scott.emp....

回收对象权限将会级联

REVOKESELECTONempFROMtim;(scott)

回收了tim的对象权限后,tim二次分配给ran的对象权限也隐式的收回了。

5)系统权限的传递与回收:WITHADMINOPTION选项

为tim用户授予系统权限

GRANTCREATETABLETOtimWITHADMINOPTION;(sys)

查看tim用户拥有的系统权限

SELECT*FROMUSER_SYS_PRIVS;(tim)

USERNAMEPRIVILEGEADMIN_OPT

--------------------------------------------

timCREATETABLEYES

timCREATESESSIONNO

二次分配给ran用户

GRANTCREATETABLETOran;(tim)

查看ran用户系统权限

SELECT*FROMUSER_SYS_PRIVS;(ran)

ranCREATETABLENO

ranCREATESESSIONNO

收回系统权限不会级联

REVOKECREATETABLEFROMtim;(sys)

回收了tim的系统权限后,tim二次分配给ran的系统权限并不会自动收回。

对象权限如果将tim用户删除,ran用户的对象权限也没有了。

6)对象权限不能和系统权限一起给,因为语法不一样。

7)对象权限可以由owner给也可以由sysdba给。

SESSION_PRIVS//用户当前会话拥有的系统权限

USER_ROLE_PRIVS//用户被授予的角色

ROLE_SYS_PRIVS//用户当前拥有的角色的系统权限

USER_SYS_PRIVS//直接授予用户的系统权限

USER_TAB_PRIVS//授予用户的对象权限

ROLE_TAB_PRIVS//授予角色的表的权限

练习:要掌握权限与角色的关系,以及如何查看信息,

数据字典

dba_xxx_privs

all_xxx_privs

user_xxx_privs

其中xxx:role表示角色,sys表示系统权限,tab表示对象权限。

从哪个角度看,非常重要!

我们举个例子:三个用户,分别是sys,scott,和tim,

1)建立myrole角色,把connect角色和createtable系统权限以及updateonscott.emp对象权限放进myrole。

2)把myrole角色授给tim。

3)把createtable系统权限授给tim。

把selectonemp表的对象权限授给tim

如此tim用户有了如下角色和权限:

myrole(connect,createtable,updateonscott.emp)

createtable

selectonemp

我们从三个角度分析一下,如何里数据字典里查看tim拥有的角色和权限信息。

从dba角度想看:

数据库里有多少用户?

selectusernamefromdba_users;

看用户tim所拥有的系统权限

select*fromdba_sys_privswheregrantee='TIM';

看用户tim所拥有的对象权限

select*fromdba_tab_privswheregrantee='TIM';

看用户tim所拥有的角色(不包含角色里的角色)

select*fromdba_role_privswheregrantee='TIM';

查看这个角色里包含的角色

select*fromdba_role_privswheregrantee='MYROLE';

查看这个角色里包含的系统权限

select*fromdba_sys_privswheregrantee='MYROLE';

查看这个角色里包含的对象权限

select*fromdba_tab_privswheregrantee='MYROLE';

从当前用户角度看:和自己有关的角色都有什么内容?

角色里包含的角色

select*fromrole_role_privs;

角色里包括的系统权限

select*fromrole_sys_privs;

角色里包括的对象权限

select*fromrole_tab_privs;

查看和自己有关的角色(不含角色中含有的角色)

select*fromuser_role_privs;

查看和自己有关的系统权限(不含角色中的系统权限)

select*fromuser_sys_privs;

查看和自己有关的对象权限(不含角色中的对象权限)

select*fromuser_tab_privs;

查看和自己有关的系统权限(包括角色里的权限)

select*fromsession_privs;

从scott用户看是个什么情况

select*fromall_tab_privswheregrantee='TIM';

select*fromall_tab_privswheretable_name='EMP';

必须具备以下四个属性,简称ACID属性:

原子性(Atimicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行。

一致性(Consistency):一个查询的结果必须与数据库在查询开始的状态一致。

隔离性(Isolation):对于其他部分来说,未完成的(也就是未提交的)事务必须不可见。

持久性(Durability):事务完成后,它对数据库就不可以丢失这个事务,数据库通过日志能够保持事务的持久性

1)COMMIT(提交)或ROLLBACK(回滚)

2)DDL语句被执行(提交)数据定义语言包括createaltertruncaterenamedrop

3)DCL语句被执行(提交)数据控制语言包括grantrevoked

4)用户退出SQL*PLUS(正常退出是提交,非正常退出是回滚)还没提及就重启电脑

5)机器故障或系统崩溃(回滚)

6)shutdowmimmediate(回滚)

考点:在一个事务里如果某个语句失败,则此语句回滚,其他任何DML语句将保持完好,而且不会提交!

用sys查看事务。Select*fromv$transaction.

保存点就是允许在事务中设置一个标记,这个标记可以控制rollback的效果,即在一个事务中回滚掉最近的部分dml语句,保留下保存点之前的的dml语句,并使事务本身继续执行。也就是说回滚到保存点这个动作并不使事务结束。

SAVEPOINT实验

savepointsp1;

deletefromemp1whereempno=7900;

savepointsp2;

updateemp1setename='XIAOMAO'whereempno=9000;

select*fromemp1;

rollbacktosp2;

rollbacktosp1;

如果先回滚到sp1则无法再回滚到sp2.

行锁(TX)只有一个

表锁(TM)共有五个,分别是RS,RX,S,SRX,X。lmode从2开始算,rs:2,rx:3,s:4,srx:5,x:6

比如一个update语句,有行锁(即TX锁),和表级锁(RX),在功能上对应,只是表级锁还有一层意思是规定了不许别人加的锁,特别防止DDL语句操作这个表。不允许其他DDL操作。

Oracle是先申请表级锁RX,获得后,系统再自动申请行锁(TX),并将实际锁定的数据行的锁标志置位(即指向该TX锁)

第一种方式:自动加锁

做DML操作时,如insert,update,delete,以及select....forupdate由oracle自动完成加锁

scott://用forupdate加锁

SQL>select*fromdeptwheredeptno>20forupdate;当其他用户在对结果中的记录操作时,会被挂起。

system://试探,以防被锁住以防被挂起。

SQL>select*fromscott.deptforupdatenowait;如果目标资源被锁住,则提示用户,不要把事物挂起。

SQL>select*fromscott.deptforupdatewait5;如果目标资源被加了锁,则等待五秒钟,如果未解锁,则结束防止session被挂起。

1)对整个表forupdate是不锁插入语句的。

2)参数wait5等5秒自动退出,防止被锁住。参数nowait,不等待。

select*fromemp1wheredeptno=10forupdate;

select*fromemp1forupdateskiplocked.跳过已经上锁的记录,锁住余下的所有记录。

第二种方式:人工方式加锁,显示的用lock命令加锁。

locktable表名inexclusivemode.(一般限于后三种表锁)

ROWSHARE行共享(RS),允许其他用户同时更新其他行,允许其他用户同时加共享锁,不允许有独占(排他性质)的锁

ROWEXCLUSIVE行排他(RX),允许其他用户同时更新其他行,只允许其他用户同时加行共享锁或者行排他锁

SHARE共享(S),不允许其他用户同时更新任何行,只允许其他用户同时加共享锁或者行共享锁

SHAREROWEXCLUSIVE(SRX)共享行排他,不允许其他用户同时更新其他行,只允许其他用户同时加行共享锁

EXCLUSIVE(X)排他,其他用户禁止更新任何行,禁止其他用户同时加任何。

sql语句加锁模式许可其他用户的加锁模式

-----------------------------------------------------------------------------------------------

select*fromtable_name无RS,RX,S,SRX,X

insert,update,delete(DML操作)RXRS,RX

select*fromtable_nameforupdateRXRS,RX

locktabletable_nameinrowsharemodeRSRS,RX,S,SRX

locktabletable_nameinrowexclusivemodeRXRS,RX

locktabletable_nameinsharemodeSRS,S

locktabletable_nameinsharerowexclusivemodeSRXRS

locktabletable_nameinexclusivemodeX无

观察锁的动态视图v$locksid:session号。Lmode:锁级别。Block:阻塞了其他用户的DML操作,0表示没有阻塞Request:请求上锁,0表示没有请求。

观察锁的动态视图dba_locks

TM锁分为两类:排他,共享

select*fromv$lock;

select*fromdba_lockswheresession_id=149;

制作死锁案例:

ID_A

brain::

ID_B

Oracle的机制,当两个进程产生相互block的死锁时候,最早的进程会释放锁。

ORA-00060:deadlockdetectedwhilewaitingforresource等待资源时检测到死锁

scott://改自己,不提交

updatetableasetid=11whereid=1;

brain://改自己,不提交

updatetablebsetid=1100whereid=100;

scott://改对方,被锁住

updatetablebrain.bid=1000whereid=100;

brain://改对方,造成死锁

先看事务的锁,sid是session号

ADDRKADDRSIDTYPEID1ID2LMODEREQUESTCTIMEBLOCK

0036ABAC0036ABDC128TM7578803021850

37901E0437901E44128TX52431314876021850

再看看sid=128这个session的的事务里最后一条sql语句是:

selecta.sid,a.serial#,b.sql_textfromv$sessiona,v$sqlbwherea.prev_sql_id=b.sql_idanda.sid=128;

SIDSERIAL#SQL_TEXT

----------------------------------------------------------------------------------------------------

12820updateasetid=3whereid=1

确定无误后

杀掉这个session

SQL>ALTERSYSTEMKILLSESSION'128,20';

加入一个B树和位图的图示。

以B树索引为例分析它的结构(图)balancetree平衡树

当对表进行DML操作比如删除和插入等,系统也会自动的维护索引,当索引同步维护后才会打印执行完毕的信息。所以建立过多不必要的索引,对表经常操作,会使DML执行效率降低。Update表,相对而言,对索引的维护工作量会小很多。

如果SQL语句仅访问被索引的列,那么数据库只需从索引中读取数据,而不用读取表,如果该语句同时还要访问除索引列之外的列,那么,数据库会使用rowid来查找表中的行,通常,为检索表数据,数据库以交替方式先读取索引块,然后读取相应的表块。

如果SQL语句没有用到被索引的列,那么数据库会遍历表,不会使用索引,所以要优化我们的查询语句,使之尽可能的使用索引,提高搜索速度。

B树中的叶子节点:存放了键值和rowid。

叶子节点是经过排序的。

适合情况不适合情况

--------------------------------------------------------------------------------------------

经常用于WHERE子句或作为连接条件的列表很小

所含数据值范围比较的列列很少在查询中作为条件

含有大量空值的列多数情况下查询出大于总记录的5%的表

总是使用两个或多个组合列查询频繁更新的表

多数情况下只查询总记录小于5%的表

考点:索引里不存空值。

1)B树索引,

2)位图索引

建立B树索引选项包括:

唯一或非唯一索引(Uniqueornon_unique):唯一索引指键值不重复。

组合索引(Composite):绑定了两个或更多列的索引。(job,deptno)组合索引,当使用组合和job(即第一个字段)时,使用索引。当使用后一个字段查询时候,不使用索引,全表扫描。考点。

反向键索引(Reverse):将字节倒置后组织键值。

函数索引(Functionbase):以索引列值的函数值为键值去组织索引

压缩(Compressed):重复键值只存储一次,就是说如果重复的键值在叶块中就存一次,后跟所有与之匹配的rowid字符串。

升序或降序(Ascendingordescending):叶节点中的键值排列默认是升序的。

USER_INDEXES//索引主要信息

USER_IND_CULUMNS//索引列的信息

Oracle的执行计划常见的四种索引扫描方式:

1)索引唯一扫描(indexuniquescan)

通过唯一索引查找一个数值经常返回单个ROWID。如果该唯一索引有多个列组成(即组合索引),则至少要有组合索引的引导列参与到该查询中。

2)索引范围扫描(indexrangescan)

在非唯一索引上,可能返回多行数据,所以在非唯一索引上都使用索引范围扫描。

使用indexrangscan的3种情况:

(a)在唯一索引列上使用了range操作符(><<>>=<=between)

(b)在组合索引上,只使用部分列进行查询,导致查询出多行

(c)对非唯一索引列上进行的任何查询。

3)索引全扫描(indexfullscan)

对整个index进行扫描,并且顺序的读取其中数据。

全Oracle索引扫描只在CBO(COSTBASED基于成本的优化器,I/O读写,cpu,内存成本

)模式下才有效。CBO根据统计数值得知进行全Oracle索引扫描比进行全表扫描更有效时,才进行全Oracle索引扫描,而且此时查询出的数据都必须从索引中可以直接得到。

并行顺序读。聚合函数常用到。

4)索引快速扫描(indexfastfullscan)

扫描索引中的所有的数据块,与indexfullscan很类似,但是一个显著的区别是fullscan是根据叶子块的双向列表顺序读取,读取的块是有顺序的,也是经过排序的,所以返回的列表也是排序的。而fastfullscan在读取叶子块时的顺序完全由物理存储位置决定,并采取多块读,每次读取DB_FILE_MULTIBLOCK_READ_COUNT个块。并行读。聚合函数常用到。

//分析器是根据要访问的数据量和索引的填充因子等属性判断使用RANGSCAN或FULLINDEXSCA

举例这四种索引扫描方式:

sys

SQL>setautotracetraceonlyexplain执行计划,不显示查询结果;setautotraceoff关闭计划。只能dba使用。

SQL>selectempnofromscott.emp1;

执行计划

----------------------------------------------------------

Planhashvalue:2226897347

--------------------------------------------------------------------------

|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Time|

|0|SELECTSTATEMENT||14|182|3(0)|00:00:01|

|1|TABLEACCESSFULL|EMP1|14|182|3(0)|00:00:01|

SQL>createuniqueindexemp1_idxonemp1(empno);

索引已创建。

SQL>selectempnofromscott.emp1whereempno=7788;

Planhashvalue:1995401140

------------------------------------------------------------------------------

|0|SELECTSTATEMENT||1|13|0(0)|00:00:01|

|*1|INDEXUNIQUESCAN|EMP1_IDX|1|13|0(0)|00:00:01|

SQL>dropindexemp1_idx;

SQL>createindexemp1_idxonemp1(empno);

SQL>analyzeindex索引名validatestructure;先分析,实行一条dml语句

SQL>select*fromindex_stats;查看索引的分支节点,blocks等信息。

Hight层高,不要大于3

Planhashvalue:253836959

-----------------------------------------------------------------------------

|0|SELECTSTATEMENT||1|13|1(0)|00:00:01|

|*1|INDEXRANGESCAN|EMP1_IDX|1|13|1(0)|00:00:01|

SQL>selectcount(empno)fromscott.emp1;

Planhashvalue:1026340756

|1|SORTAGGREGATE||1|13|||

|2|INDEXFULLSCAN|EMP1_IDX|14|182|1(0)|00:00:01|

scott:

SQL>insertintoemp1select*fromemp1;

已创建14行。

SQL>/

.....

已创建14336行。

SQL>altertablescott.emp1modify(empnonotnull);--因索引的叶子块不存空值,使empno字段非空。

SQL>selectempnofromscott.emp1;--数据库仅访问索引本身的数据。而无需访问表。

Planhashvalue:1892048637

---------------------------------------------------------------------------------

|0|SELECTSTATEMENT||28033|355K|29(0)|00:00:01|

|1|INDEXFASTFULLSCAN|EMP1_IDX|28033|355K|29(0)|00:00:01|

Note

-dynamicsamplingusedforthisstatement

可以看出:oracle在满足一定条件时会先选fastfullscan,而不是fullscan,因为前者的cost是29,比后者低许多。

可以加一行说明,强制使用fullscan的执行计划,cost是100.

SQL>select/*+index(emp1emp1_idx)*/empnofromscott.emp1;

Planhashvalue:4252953140

|0|SELECTSTATEMENT||28033|355K|100(0)|00:00:02|

|1|INDEXFULLSCAN|EMP1_IDX|28033|355K|100(0)|00:00:02|

查询索引的两个动态视图:

select*fromuser_indexes;

select*fromuser_ind_columnsuwhereu.index_name='IND1';

select*fromdba_indexes;

select*fromuser_ind_columnsuwhereu.index_name=’IND1’;

Oracle没有量化碎片,当执行了大量的DML语句,感觉索引比较慢了,然后当以下三种情况发生时,就说明积累的碎片改整理了。

1、hight>=4

2、pct_used<50%(排除,插入大量数据后,才创建的索引的情况。因为那时候创建的索引,pct_used值就有可能<50%)

3、del_lf_rows/lf_rows>0.2lf_row叶子行lf_blk叶子块

createindexind_tont(t1)

selectname,pct_usedfromindex_statswherename='IND_T';(运行此句之前,先分析analyzeindexind_1validatestructure。Analyze是基于session的分析。)

createtablet(idint);

createindexind_1ont(id);

begin

foriin1..1000000loop

insertintotvalues(i);

ifmod(i,100)=0then

endif;

endloop;

end;

analyzeindexind_1validatestructure;

selectname,pct_usedfromindex_stats;

deletetwhererownum<700000;

alterindexind_1rebuild[online];重建索引

alterindexind_1coalesce;

在Oracle11g中有了改进,实现了最终意义上的联机索引重建(rebuildindexonline)的特性,它重新设计了锁的模式,因此容许DML操作不受干扰。

在11g里,Oracle提供了一个新特性来降低直接删除索引或禁用索引的风险,那就是索引不可见(IndexInvisible)。我们可以在创建索引时指定

unusable索引不更新

考点:invisible和unusable的区别。

invisible属性或者用alter语句来修改索引为invisible(visible)

SQL>createtabletest(idint,namechar(10));

SQL>createindextest_idxontest(id)invisible;

SQL>alterindextest_idxvisible;

SQL>alterindextest_idxinvisible;

当索引被设为不可见后,实际上就是指该索引对于优化器不可见,而索引的正常更新仍然会由有Oracle自动完成的。对比11g前的unusable,(保存索引定义,不删除索引,也不更新索引)。

SQL>alterindextest_idxunusable;

约束是数据库能够实施业务规则以及保证数据遵循实体-关系模型的一种手段。

考点:如果违反约束,将自动回滚出现问题的整个语句,而不是语句中的单个操作,也不是整个事务。

列级定义:只能引用一个列,表中可以有多个列级约束。

表级定义:引用一个或多个列,通常用来定义主键。

追加定义:建表后,再通过altertable命令追加的约束。

查看约束的两个数据字典视图

select*fromuser_constraints;

selectconstraint_name,column_name,table_namefromuser_cons_columns;

列级定义:

createtablestud(idnumber(2)notnull,namevarchar(4))

追加非空约束:

notnull约束比较特殊,一般只是列级定义和表外定义,当使用表外(追加)时,要使用modify关键字,

如:altertableemp1modifyenamenotnull;

或altertableemp1modifyenameconstraintxyznotnull;

查看非空约束

selectconstraint_name,constraint_type,table_name

fromuser_constraints

whereowner='SCOTT'

andtable_name=UPPER('stud')

删除非空约束

altertablestuddropconstraintSYS_C005454//SYS_C005454是系统生成的约束名

列级定义

SQL>createtablea1(idnumber(2)unique,namevarchar2(4));

表级定义

createtablea2(idnumber(2),namevarchar2(4),constraintid_ukunique(id));

追加定义

altertablea2addCONSTRAINTid_ukUNIQUE(id);

删除唯一约束

altertablestuddropunique(id);

主键约束的六种写法

1)createtableu1(idchar(10)primarykey,namechar(20));--主键名字,Oracle起的

2)createtableu2(idchar(10)constraintpk_u2primarykey,namechar(20));--主键名字,自己指定

3)createtableu3(idchar(10),namechar(20),primarykey(id));--主键名字,Oracle起的

4)createtableu4(idchar(10),namechar(20),CONSTRAINTSpk_u4primarykey(id));--主键名字,自己指定

createtableu5(idchar(10),namechar(20));

5)altertableu5addprimarykey(id);

6)altertableu5addCONSTRAINTpk_u5primarykey(id);--表外,后来加上主键。

删除主键约束

altertabledept1dropconstraintd_pk;

建立主键约束和唯一约束时,如果该列没有索引,oracle会自动在该列上创建一个唯一性索引。为什么?主键是非空且唯一。

关于主键和索引关联的问题:(这个地方考点较多)

SQL>createtablet(idint,namechar(10));

SQL>insertintotvalues(1,'sohu');

SQL>insertintotvalues(2,'sina')

SQL>commit;

SQL>createindext_idxont(id);

下面这两句话是一样的效果,因为缺省情况下id列已经有索引t_id了,建主键时就会自动用这个索引(考点)。不能删除主键(或unique)创建的索引。删除约束之后索引还在。

SQL>altertabletaddconstraintpk_idprimarykey(id);

SQL>altertabletaddconstraintpk_idprimarykey(id)usingindext_idx;

SQL>selectCONSTRAINT_NAME,TABLE_NAME,INDEX_NAMEfromuser_constraints;

CONSTRAINT_NAMETABLE_NAMEINDEX_NAME

FK_DEPTNOEMP

PK_DEPTDEPTPK_DEPT

PK_EMPEMPPK_EMP

PK_IDTT_IDX

SQL>altertabletdropconstraintpk_id;//删除了约束,索引还在,本来就是借用的索引。

SQL>selectindex_namefromuser_indexes;

INDEX_NAME

PK_EMP

PK_DEPT

T_IDX

SQL>droptabletpurge;//t_idx是和t表关联的,关键字purge使表和索引一并永久删除了。

也可以使用using字句在建表建约束建约束一条龙下来,当然primarykey也会自动使用这个索引(考点)。

SQL>createtablet(idint,namechar(10),constraintpk_idprimarykey(id)usingindex

(createindext_idxont(id)));

作用:是为了和同一个表或其他表的主关键字或唯一关键字建立连接关系,外键值必须和父表中的值匹配或者为空值。

考点:外键约束和unique约束都可以有空值。

SQL>createtabledept1asselect*fromdept;

SQL>altertabledept1addprimarykey(deptno);

SQL>createtableemp100(empnoint,deptnointreferencesdept1(deptno),deptno2int);

//外键的列级定义不写foreignkey关键字,有点不习惯。

SQL>createtableemp200(empnoint,deptnoint,salint,foreignkey(deptno)referencesdept1(deptno));

ALTERTABLEemp100ADDCONSTRAINTe_fkFOREIGNKEY(deptno2)REFERENCESdept1(deptno);

关于ONDELETECASCADE关键字

SQL>droptableemp100purge;

SQL>droptableemp200purge;

SQL>ALTERTABLEemp1ADDCONSTRAINTe_fkFOREIGNKEY(deptno)REFERENCESdept1(deptno);

测试:

deletefromdept1wheredeptno=30

ERRORatline1:

ORA-02292:integrityconstraint(SCOTT.E_FK)violated-childrecordfound

删除外键约束

altertableemp1

dropconstrainte_fk

使用ONDELETECASCADE关键字重建外键(级联删除)不能用alter修改,只能建表的约束的时候用。

ALTERTABLEemp1

ADDCONSTRAINTe_fkFOREIGNKEY(deptno)

REFERENCESdept1(deptno)ONDELETECASCADE

1rowdeleted.

再查看emp1表的deptno

select*fromemp1;

ONDELETECASCADE要慎用,主表中删除一行数据就可能引发从表中大量数据丢失。

SQL>createtableemp100(empnoint,salintcheck(sal>0),commint);

SQL>createtableemp200(empnoint,salint,commint,check(sal>1000));

SQL>altertableemp200addconstrainte_no_ckcheck(empnoisnotnull);

验证

SQL>insertintoemp200values(null,1,1);

insertintoemp200values(null,1,1)

ORA-02290:违反检查约束条件(SCOTT.E_NO_CK)

测试表

CREATETABLEtest2(

pkNUMBERPRIMARYKEY,

fkNUMBER,

col1NUMBER,

col2NUMBER,

CONSTRAINTfk_constraintFOREIGNKEY(fk)REFERENCEStest2,一个表的时候可以省略主键pk

CONSTRAINTck1CHECK(pk>0andcol1>0),

CONSTRAINTck2CHECK(col2>0)

当删除列时,看看会发生什么

ALTERTABLEtest2DROP(col2);//这句可以执行

ALTERTABLEtest2DROP(pk);//这句不能执行,在constraintck1中使用了该列,约束级联问题)

ALTERTABLEtest2DROP(fk);//这句可以执行

ALTERTABLEtest2DROP(col1);//这句不能执行,在constraintck1中使用了该列,约束级联问题)要带上cascadeconstraints才行

ALTERTABLEtest2DROP(pk)cascadeconstraint;//所有与pk列有关的约束统统随该列被删掉。

ALTERTABLEtest1DROP(col1)cascadeconstraints;

CASCADECONSTRAINTS将丢弃在删除列上的唯一键或主键约束。

启用约束:

enablevalidate:启用约束,创建索引,对已有及新加入的数据执行约束.默认的。

enablenovalidate:启用约束,创建索引,仅对新加入的数据强制执行约束,而不管表中的现有数据.约束只对新数据生效。

禁用约束:

disablenovalidate:关闭约束,删除索引,可以对约束列的数据进行修改等操作.约束不生效。

disablevalidate:关闭约束,删除索引,不能对表进行插入/更新/删除等操作,注意是相当于对整个表的readonly设定,不管列上有没有约束.不常用。

更改约束状态是一个数据字典更新,将对所有session有效。

举例:

以scottuser中的emp﹑dept两个表分别复制emp1,dpet1来进行例证.

SQLcreatetableemp1asselect*fromemp;

建立约束

SQL>altertableemp1addconstraintpk_emp1primarykey(empno)

;

SQL>altertabledept1addconstraintpk_dept1primarykey(deptno);

SQL>altertableemp1addconstraintfk_deptno1foreignkey(deptno)referencesdept1(deptno);

SQL>selectconstraint_name,constraint_type,status,validatedfromuser_constraints;

CONSTRAINT_NAMECSTATUSVALIDATED

FK_DEPTNO1RENABLEDVALIDATED

FK_DEPTNORENABLEDVALIDATED

PK_DEPTPENABLEDVALIDATED

PK_EMPPENABLEDVALIDATED

PK_EMP1PENABLEDVALIDATED

PK_DEPT1PENABLEDVALIDATED

6rowsselected.

一般来讲﹐默认的情况下enable时就会validate;disable时就会novalidate;

而这两个不同的动作分开来讲就是:

enable/disable是指是否现在要启动/失效这个约束.

validate/novalidate是指是否对现在的数据进行合法性的檢查.

现实操作中因为有一些违规的操作需要我们处理﹐如改变主细中有外FK关联的表结构﹐truncate表...

所以我们要打断数据库的约束关联后再进行操作。

SQL>altertableemp1disableconstraintFK_DEPTNO1;

Tablealtered

这样我们就可以操作emp1表中的deptno字段而不受外键的限制[无须在dept1表中存在或值为NULL了].

而当我们没有打断这种关联时﹐像下面这些操作都会出错:

SQL>deletefromdept1wheredeptno=10;

deletefromdept1wheredeptno=10

ORA-02292:integrityconstraint(SCOTT.FK_DEPTNO1)violated-childrecordfound

SQL>updateemp1setdeptno=50whereempno=7934;

updateemp1setdeptno=50whereempno=7934

ORA-02291:integrityconstraint(SCOTT.FK_DEPTNO1)violated-parentkeynotfound

此外如果没有disable关联时即使子表中没有资料﹐父表也不能truncate。

因为truncate是一条DDL指令﹐当进行truncate时,它并不会去一条条的记录去检查父中的这条记录在

子表是否已有引用﹐而是去检查这类的constraint_name的status是否为disable﹐否则不能truncate.

SQL>truncatetabledept1;

truncatetabledept1

ORA-02266:unique/primarykeysintablereferencedbyenabledforeignkeys

SQL>altertableemp1enablenovalidateconstraintFK_EMP_DEPT;

SQL>truncatetabledept;

Tabletruncated

前面讲到disable/enable与[novalidate|validate]两种操作就有四种组态.

而因为enablevalidate与disablenovalidate是默认的所以就不以讨论了。

============================================================

以下来说明enablenovalidate这种组态的实用用法

我们常用于当我们在表中输入了一些测试数据﹐而上线时我们并不想去清除这些

违规数据﹐只想从以后开始才执行这些约束时可以用到。

假设已经建立了一个emp1表,也插入了数据,如果有一天想在empno上加入primarykey但是之前有不符合(notnull+unique)约束的,怎样才能既往不咎呢?

createtableemp1asselect*fromemp;(约束并没有考过来)

updateemp1setempno=7788whereempno=7369;(设置一个重号)

altertableemp1addconstraintpk_emp1primarykey(empno);因要检查主键唯一索引,拒绝建立此约束。

任何违反(notnull+unique)的update或insert操作将被拒绝。

altertableemp1addconstraintpk_emp1primarykey(empno)enablenovalidate;(这句话也不行,为什么?原因是唯一索引在捣乱)。

createindexempno_indexonemp1(empno);建一个索引,一定要一个普通索引,不能是唯一索引,普通索引不受unquie的限制)

altertableemp1addconstraintpk_emp1primarykey(empno)enablenovalidate;(这句话可以了)。

从此之后,这个列的DML操作还是要符合(notnull+unique)。

----------------------------------------------------------------------------------------------------------------------

可延迟(deferrable)的约束可以指定为:

1.initiallyimmediate(初始化立即执行)

2.initiallydeferred(初始化延迟执行)

其中InitiallyImmediate意思是每次向表中添加数据,修改数据或是从表中删除数据时.都要检查这个约束.(这与约束默认行为相同).

而InitiallyDeferred.意思是只有事务被提交时才检查这个约束.

1、deferrable必须在简历约束的时候指明否则不可再追加。

2、多个DML组成一个事务,COMMIT时候如果有一个不符合约束,则所有DML都被回退。

3、在定义的时候,initially状态将应用于所有SESSION有效。Immediate和deferred的切换对当前session有效。考点。

在你操作table时,例如insert数据。以主键约束为例

如果有违反主键唯一性的约束时,系统应该报错。

现在你要决定系统什么时候报错。

1,initiallyimmediate在执行sql的时候报错。

2,initiallydeferred在commit的时候报错。

比方说,2个人先后在执行insert同一笔资料。

如果第一种方案,则后面的那个人无法执行sql。

如果第二种方案,则2个人都可以执行sql,但是先commit的人会成功。后commit的人会被提示报错。

可以通过查询User_Constraints表获得当前所有关于约束的系统信息.下面关于约束User_Constraints表常用信息字段说明:

Owner//约束所有者

Constraint_name//约束名称

Constraint_Type//约束类型:

[C:代表Check或NotNull约束.P:主键约束.R:外键约束.U:唯一约束.V:Checkoption束.O:Readonly只读约束]

Table//name——约束定义针对表名

Status_//约束的状态Enable或Disable可用或不可用

Deferrable//是否为延迟约束值为:Deferrable或NotDeferred.

Deferred://是否采用延迟值为:IMMEDIate或Deferred.

SQL>altertableemp1addconstraintfk_emp1foreignkey(deptno)referencesdept1(deptno)deferrable;

SQL>updateemp1setdeptno=50whereempno=7900;(因为不检查约束,可以暂时违反完整性约束)

SQL>insertintoemp1empno=7788whereename='SMITH';(暂时通过,插入记录也只在提交(commit)时检查)

SQL>commit;(这时候检查了,报错!)

考点:一旦有一条DML语句违反了约束,整个提交都将失败,全军覆没。

关于deferrable可延迟,提醒以下几点:

1)约束的默认方式下是:enable/validate和notdefferable。

2)如果创建约束时没有指定deferrable那么无法在后来使约束成为延迟约束的(只有再重建约束时指定它是延迟约束)

3)一个constraint如果被定义成deferrable,那么这个constraints可以在deferred和imediate两种状态间相互转换

4)因为是deferrable,可以使用setconstraint字句了。

SQL>setconstraintfk_emp1deferred;--约束fk_emp1已经进入了临时延迟状态

以上3)和4)合起来就相当于:

SQL>altertableemp1addconstraintfk_emp1foreignkey(deptno)referencesdept1(deptno)deferrableinitiallydeferred

限制数据的存取:用户只能看到基表的部分信息。

使得复杂的查询变得容易:视图中的数据可能来自多个表。

使得数据相对比较独立:从项目开发的角度,模块对应视图,模块包含多个表,模块发生变化后只需修改相应的视图,对应的表的结构无需修改。

代表对同一数据的不同视角:不同部门的员工只能看到本部门的信息。

CREATE[ORREPLACE][FORCE|NOFORCE]VIEWview

[(alias[,alias]...)]

ASsubquery

[WITHCHECKOPTION[CONSTRAINTconstraint]]

[WITHREADONLY];

Selecttextfromuser_views;视图的数据字典。

考点:如果select字句中有表达式(sal+1000),需要给表达式加别名。

Create(orreplace)forceviewview1asselect*fromtest1;

因为基表不存在,执行报错。但是试图已经建立。

对视图where子句进行约束。不允许对限定关键字修改。

SQL>createviewview2asselect*fromempwheredeptno=10withcheckoption;

无法对DEPTNO字段键值进行修改。

禁止对视图执行DML操作

SQL>createviewview3asselect*fromempwheredeptno=10withreadonly;

1)定义视图的查询中列中有函数或表达式要加别名考点

2)只要视图中的数据不是来自基表的原始数据,就尽量不要对该数据做DML操作。考点

比如:createviewV1asselectsal+1000abcfromemp1;则这样的试图不能修改,因为基表emp1中没有abc列。

3)视图的DML操作

含有如下情况,则无法删除视图中的数据:

含有聚组函数

含有GROUPBY子句

含有DISTINCT关键字

含有ROWNUM这个伪列

含有如下情况,不能修改该视图中的数据:

上面提到的任何一种情况。

列是由表达式来进行定义的

含有如下情况,不能增加该视图中的数据:

在基表中包含有NOTNULL约束的列,然而该列并没有在视图中出现

比如,试图只映射了部分字段,不包括NOTNULL字段,如果插入的话,将对基表中的NOTNULL字段补空值,违反约束。

select*fromuser_views

如果建立了视图想查看其中的定义,可以访问如下视图dba_views中的text字段(long型);

自建一pl/sql过程,参照一下。

declare

v_textdba_views.text%type;

v_namedba_views.view_name%type;

selecttext,view_nameintov_text,v_nameFROMdba_viewsWHEREview_name='V1';

dbms_output.put_line(v_name||'defineis:'||v_text);

sysdba下执行:

setserverouton;

aadba_views.text%type;

selecttextintoaaFROMdba_viewsWHEREOWNER='SCOTT';

dbms_output.put_line(aa);

sys用户看scott的emp:

select*fromscott.emp;

createsynonymsyn1forscott.emp;

select*fromsyn1;(私有同义词只能在当前用户下访问,scott使用不了)

但是创建同义词是要权限的(createsynonym,createpublicsynonym);

createpublicsynonymsyn2for...

(新用户要访问publicsynonym(代表emp表),需要有访问基表的权限。

select*fromtab;(tab是什么?);用下面的查看语句:

select*fromall_objectswhereobject_name='TAB';

select*fromall_synonymwheresynonym_name='TAB';

1)私有同义词是基于模式的对象,要么在自己的模式中,要么必须用模式名限定。

比如scott.syn1syn1是同义词,scott是模式名

2)公有同义词不是模式对象,不能用模式名做前缀。(考点)

3)私有和公有同义词同名但指向不同的别名时,私有同义词优先。

For后面的对象不一样的时候,私有优先。

4)同义词被引用的对象(表或视图)被删除,同义词仍然存在,这同视图类似,重新创建对象,下次访问同义词时自动编译。(考点)

结合真题演示

伪列nextval,currval用法下一个值,当前值

CREATESEQUENCEdept_deptno

INCREMENTBY10

STARTWITH50

MAXVALUE100

CYCLE转一圈回来之后,就不从50开始,而从1开始考点。

NOCACHE

第一次要引用一下nextval伪列

selectdept_deptno.nextvalfromdual;

以后就有currval伪列值了。

1)最简单的建立序列只需要createsequence序列名就可以,注意缺省值,起始是1,步长也是1。

2)如果启用cache,缺省只有20个号,经验表明这个数量会不够,可以设置多一些,根据需要10000个也可以。Cache10000

3)cycle其实没有什么意义,因为它使序列发出重复值,这对于基于序列是主键值的用法是个问题。

4)创建序列后可以使用alter命令再进行修改。alter命令和create命令基本相同,只有一点区别:alter命令不能设置起始值。如果要重启该序列,唯一的办法是删除并重新创建它。

5)循环后初始是从1开始的,不管原来的值是如何设的(考点)。

16.1读取外部表的方法

OS下建目录,

$mkdir-p/u01/oradata/timran11g/aaa_dir

chmod777/u01/oradata/timran11g/aaa_dir

建立txt外部表文件,并放到aaa_dir下

假如有如下的数据文件:

t1.txt文件内容:

7566,JONES,2975,20

7698,BLAKE,2850,30

7788,SCOTT,3000,20

7839,KING,9000,10

7902,FORD,3000,20

sql>createdirectorytest_diras'/u01/oradata/timran11g/aaa_dir';

sql>grantread,writeondirectorytest_dirtoscott;

createtabletest_table

(empnoint,

enamechar(20),

salint,

deptnoint)

ORGANIZATIONEXTERNAL

(

TYPEORACLE_LOADER

DEFAULTDIRECTORYtest_dir

ACCESSParameters

RECORDSDELIMITEDBYNEWLINE

badfile'bad_dev.txt'

LOGFILE'log_dev.txt'

FIELDSTERMINATEDBY','说明外部表里每个值之间的分隔符。

MISSINGFIELDVALUESARENULL

(empno,ename,sal,deptno)

LOCATION('t1.txt')

4),进行SELECT操作看是否正确;

SQL>select*fromtest_table

SQL>select*fromtest_tablewheredeptno=10;

查看外部表的两个字典视图

DBA_EXTERNAL_TABLES;

DBA_EXTERNAL_LOCATIONS;

SQL>SELECTOWNER,TABLE_NAME,DEFAULT_DIRECTORY_NAME,ACCESS_PARAMETERSFR

FROMDBA_EXTERNAL_TABLES;

第二册部分

第一类insert语句:一次插入一行

1)SQL>createtablea(idint,namechar(10)default'aaa');//name列指定了default值

2)SQL>insertintoavalues(1,'abc');//表a后没有所选列,values必须指定所有字段的值。

3)SQL>insertintoavalues(2,default);//同上,name字段用default占位。

4)SQL>insertintoavalues(3,null);//表a后没有所选列,name字段用null占位。

5)SQL>insertintoa(id)values(4);//表a后有选择字段,未选定的字段如果指定了default,则以default的值代替null

6)SQL>insertinto(selectidfroma)values(5);//这种形式本质同上,只不过表a的形式以结果集代之。

NOTE:insert命令会有约束的问题,不符合约束条件的insert不能成功。

1abc

2aaa

4aaa

5aaa

7)insertWITHCHECKOPTION的用法

SQL>insertinto(selectidfromawhereid<100WITHCHECKOPTION)values(20);

20aaa

SQL>rollback;

SQL>insertinto(selectidfromawhereid<100WITHCHECKOPTION)values(101);

insertinto(selectidfromawhereid<100WITHCHECKOPTION)values(101)

ORA-01402:viewWITHCHECKOPTIONwhere-clauseviolation

这样的语法看起来很特殊,其实就是insert进subquery里的这张表里,只不过如果不满足subquery里的where条件的话,就不允许插入。

看看这句话的另一种情况:

SQL>insertinto(selectnamefromawhereid<100WITHCHECKOPTION)values('NBA');

insertinto(selectnamefromawhereid<100WITHCHECKOPTION)values('NBA')

note:上例是想说明如果插入的列有不在subquery作为检查的where条件里,那么也会不允许插入(考点)。

SQL>insertinto(selectid,namefromawhereid<100WITHCHECKOPTION)values(10,'tim');

SQL>insertinto(selectnamefromawhereid<100)values('NBA');//不加WITHCHECKOPTION则在插入时不会检查。

SQL>insertinto(selectnamefromawhereid<100)values('NBA');

一次插入多行语法上去掉了values选项。

SQL>createtablebasselect*fromawhere1>2;//建立一个空表b。结构来自a表,where1>2使没有符合的记录被筛选出来.

SQL>insertintobselect*fromawherename='aaa';//插入的是结果集,注意没有values选项。

SQL>insertintob(id)selectidfromawhereidin(1,3);//使用子查询(结果集)插入,对位,注意b表没有default。复制表结构,除了非空约束、字段名、字段类型、字段长度之外,其他都复制不过来。

一条INSERT语句可以完成向多张表的插入任务。

insertall与insertfirst

1.创建表T并初始化测试数据,此表作为数据源。

createtablet(xnumber(10),yvarchar2(10));

insertintotvalues(1,'a');

insertintotvalues(2,'b');

insertintotvalues(3,'c');

insertintotvalues(4,'d');

insertintotvalues(5,'e');

insertintotvalues(6,'f');

2.查看表T的数据

SQL>select*fromt;

XY

3c

5e

6f

3.创建表T1和T2,作为我们要插入的目标表。

SQL>createtablet1asselect*fromtwhere0=1;

Tablecreated.

SQL>createtablet2asselect*fromtwhere0=1;

unconditionalinsertall(无条件insertall)

1)完成INSERTALL插入

SQL>insertallintot1intot2select*fromt;

12rowscreated.

这里之所以显示插入了12条数据,实际上表示在T1表中插入了6条,T2表插入了6条,一共是12条数据。

2)验证T1表中被插入的数据。

SQL>select*fromt1;

3)验证T2表中被插入的数据。

SQL>select*fromt2;

OK,完成INSERTALL命令的使命。

conditionalinsertfirst(有条件insertfirst)

1)清空表T1和T2

SQL>deletefromt1;truncatetablet1;

SQL>deletefromt2;truncatetablet2;

2)完成INSERTFIRST插入

SQL>insertfirstwhenx>=5thenintot1whenx>=2thenintot2select*fromt;

5rowscreated.

处理逻辑是这样的,首先检索T表查找X列值大于等于5的数据(这里是“5,e”和“6,f”)插入到T1表,然后将前一个查询中出现的数据排除后再查找T表,找到X列值大于等于2的数据再插入到T2表(这里是“2,b”、“3,c”和“4,d”)。注意INSERTFIRST的真正目的是将同样的数据只插入一次。

3)验证T1表中被插入的数据。

4)验证T2表中被插入的数据。

5)为真实的反映“数据只插入一次”的目的,我们把条件颠倒后再插入一次。

SQL>deletefromt1;

SQL>deletefromt2;

SQL>insertfirstwhenx>=2thenintot1whenx>=5thenintot2select*fromt;

OK,目的达到,可见满足第二个条件的数据已经包含在第一个条件里,所以不会有数据插入到第二张表。

同样的插入条件,我们把“INSERTFIRST”换成“INSERTALL”,对比一下结果。

5rowsdeleted.

0rowsdeleted.

SQL>insertallwhenx>=2thenintot1whenx>=5thenintot2select*fromt;//conditionalinsertall

7rowscreated.

createtablesales_source_data(

employee_idnumber(6),

week_idnumber(2),

sales_monnumber(8,2),

sales_tuenumber(8,2),

sales_wednumber(8,2),

sales_thurnumber(8,2),

sales_frinumber(8,2)

insertintosales_source_datavalues(176,6,2000,3000,4000,5000,6000);

createtablesales_info(

weeknumber(2),

salesnumber(8,2)

看上面的表结构,现在将要sales_source_data表中的数据转换到sales_info表中,这种情况就需要使用旋转Insert

示例如下:

insertall

intosales_infovalues(employee_id,week_id,sales_mon)

intosales_infovalues(employee_id,week_id,sales_tue)

intosales_infovalues(employee_id,week_id,sales_wed)

intosales_infovalues(employee_id,week_id,sales_thur)

intosales_infovalues(employee_id,week_id,sales_fri)

selectemployee_id,week_id,sales_mon,sales_tue,

sales_wed,sales_thur,sales_fri

fromsales_source_data;

从该例子可以看出,所谓旋转Insert是无条件insertall的一种特殊应用,但这种应用被oracle官方,赋予了一个pivotinginsert的名称,即旋转insert.

把数据从一个表复制到另一个表,插入新数据或替换掉老数据是每一个ORACLEDBA都会经常碰到的问题。

在ORACLE9i以前的年代,我们要先查找是否存在老数据,如果有用UPDATE替换,否则用INSERT语句插入,其间少不了还有一些标记变量等等,繁琐的很。

ORACLE9i后专为这种情况提供了MERGE语句,使这一工作变得异常轻松,MERGE命令能够在一个SQL语句中对一个表同时执行inserts和updates操作。

MERGE命令从一个或多个数据源中选择行来updating或inserting到一个或多个表.

Oracle10g中MERGE有如下一些改进:

1、UPDATE或INSERT子句是可选的

2、UPDATE和INSERT子句可以加WHERE子句

3、ON条件中使用常量过滤谓词来insert所有的行到目标表中,不需要连接源表和目标表

4、UPDATE子句后面可以跟DELETE子句来去除一些不需要的行

首先创建示例表:

createtablePRODUCTS

PRODUCT_IDINTEGER,

PRODUCT_NAMEVARCHAR2(30),

CATEGORYVARCHAR2(30)

insertintoPRODUCTSvalues(1501,'VIVITAR35MM','ELECTRNCS');

insertintoPRODUCTSvalues(1502,'OLYMPUSIS50','ELECTRNCS');

insertintoPRODUCTSvalues(1600,'PLAYGYM','TOYS');

insertintoPRODUCTSvalues(1601,'LAMAZE','TOYS');

insertintoPRODUCTSvalues(1666,'HARRYPOTTER','DVD');

createtableNEWPRODUCTS

insertintoNEWPRODUCTSvalues(1502,'OLYMPUSCAMERA','ELECTRNCS');

insertintoNEWPRODUCTSvalues(1601,'LAMAZE','TOYS');

insertintoNEWPRODUCTSvalues(1666,'HARRYPOTTER','TOYS');

insertintoNEWPRODUCTSvalues(1700,'WAITINTERFACE','BOOKS');

SQL>select*fromproducts;

PRODUCT_IDPRODUCT_NAMECATEGORY

----------------------------------------------------------------------

1501VIVITAR35MMELECTRNCS

1502OLYMPUSIS50ELECTRNCS

1600PLAYGYMTOYS

1601LAMAZETOYS

1666HARRYPOTTERDVD

SQL>select*fromnewproducts;

1502OLYMPUSCAMERAELECTRNCS

1666HARRYPOTTERTOYS

1700WAITINTERFACEBOOKS

1、可省略的UPDATE或INSERT子句

在Oracle9i,MERGE语句要求你必须同时指定INSERT和UPDATE子句.而在Oracle10g,你可以省略UPDATE或INSERT子句中的一个.下面的例子根据

表NEWPRODUCTS的PRODUCT_ID字段是否匹配来updates表PRODUCTS的信息:

SQL>MERGEINTOproductsp

USINGnewproductsnp

ON(p.product_id=np.product_id)

WHENMATCHEDTHEN

UPDATE

SETp.product_name=np.product_name,

p.category=np.category;

3rowsmerged.

在上面例子中,MERGE语句影响到是产品id为1502,1601和1666的行.它们的产品名字和种类被更新为表newproducts中的值.下面例子省略UPDATE

子句,把表NEWPRODUCTS中新的PRODUCT_ID插入到表PRODUCTS中,对于在两个表中能够匹配上PRODUCT_ID的数据不作任何处理.从这个例子你能看到

PRODUCT_ID=1700的行被插入到表PRODUCTS中.

WHENNOTMATCHEDTHEN

INSERT

VALUES(np.product_id,np.product_name,

np.category);

1rowmerged.

select*fromproducts;

2、新增加的DELETE子句

Oracle10g中的MERGE提供了在执行数据操作时清除行的选项.你能够在WHENMATCHEDTHENUPDATE子句中包含DELETE子句.DELETE子句必须有一个WHERE条件来删除匹配某些条件的行.匹配DELETEWHERE条件但不匹配ON条件的行不会被从表中删除.

下面例子验证DELETE子句.我们从表NEWPRODUCTS中合并行到表PRODUCTS中,但删除category为ELECTRNCS的行.

p.category=np.category

DELETEWHERE(p.category='ELECTRNCS')

VALUES(np.product_id,np.product_name,np.category);

4rowsmerged.

产品ID为1502的行从表PRODUCTS中被删除,因为它同时匹配ON条件和DELETEWHERE条件.产品ID为1501的行匹配DELETEWHERE条件但不匹配ON条件

,所以它没有被删除.产品ID为1700的行不匹配ON条件,所以被插入表PRODUCTS.产品ID为1601和1666的行匹配ON条件但不匹配DELETEWHERE条件,所

以被更新为表NEWPRODUCTS中的值.

好处:

1、使用with语句,可以避免在select语句中重复书写相同的语句块。

2、with语句将该子句中的语句块执行一次并存储到用户的临时表空间中。

3、使用with语句可以提高查询效率。

举例:一个with语句完成三个动作

建立一个dept_costs,保存每个部门的工资总和,

建立一个avg_cost,根据dept_costs求出所有部门总工资的平均值,

最后显示出部门总工资值小于部门总工资平均值的那些部门的信息(dname)。

WITH

dept_costsAS(

SELECTd.dname,SUM(e.sal)ASdept_total

FROMempe,deptd

WHEREe.deptno=d.deptno

GROUPBYd.dname),

avg_costAS(

SELECTSUM(dept_total)/COUNT(*)ASdept_avgFROMdept_costs)

SELECT*FROMdept_costs

WHEREdept_total<

(SELECTdept_avgFROMavg_cost)

ORDERBYdname

DNAMEDEPT_TOTAL

------------------------

ACCOUNTING8750

SALES9400

可以分三个部分来看:

第一AS建立一个dept_costs,保存每个部门的工资总和

第二个AS建立一个avg_cost,根据刚才的dept_costs求出所有部门总工资的平均值

最后,SELECT*FROM...显示部门总工资值小于部门总工资平均值的那些部门的信息

模式是一种逻辑结构,它对应于用户,每建一个用户就有一套模式与之对应。

我们通常说对象的唯一标识符是前缀为模式名的对象名称,那么对象的命名需要有名称空间的概念

名称空间定义了一组对象类型,在这个组中所有名称都必须由模式和名称唯一标识,不同的名称空间中的对象可以共享相同的名称。

1)同一模式下的相同对象类型是不可以重名的。

2)表,视图,序列,同义词是不同的对象,它们在一个名称空间里也是不可以重名的,比如scott下不可以使一个表名和一个视图名同名。

3)索引、约束有自己的名称空间,所以在scott模式下,可以有表A,索引A和约束A共存。

考点:在同一个模式中,表、视图和同义词不能同名。

语法:createtable[schema.]tableassubquery;

如:createtable表2asselect*from表1;是最简洁的复制表的命令,但是要注意,索引不会被复制到表2,约束只有notnull约束能够带到表2里来,如果有default也不会被复制表2。

原理:清除掉字典信息(撤消存储空间),不可恢复。

Oracle推荐:

可以使用SETUNUSED选项标记一列(或多列),使该列不可用。不可恢复

使用DROPUNUSEDcolumn选项删除被被标记为不可用的列。

语法:

ALTERTABLEtableSETUNUSED(COLlist多个)或者ALTERTABLEtableSETUNUSEDCOLUMNcol单个;

ALTERTABLEtableDROPUNUSEDCOLUMNS;

答:视图和同义词会失效,其中同义词再次引用即可重新编译,但是视图重新编译会报错,约束和索引会被自动删除。

SETUNUSED不会真地删除字段。

除了altertabledropfield外,也可以

altertablesetunusedfield;

altertabledropunusedcolumns;

setunused系统开销比较小,速度较快,所以可以先setunuased,然后在系统负载较小时,再drop。如系统负载不大,也可以直接drop。

不管用何种方法,都不会收回空间。

Oracle数据库中的rollup配合groupby命令使用,可以提供信息汇总功能(与"小计"相似)

CUBE,也是GROUPBY子句的一种扩展,可以返回每一个列组合的小计记录,同时在末尾加上总计记录。

示例如下:

SQL>selectjob,deptno,salfromemp;

JOBDEPTNOSAL

CLERK20800

SALESMAN301600

SALESMAN301250

MANAGER202975

MANAGER302850

MANAGER102450

ANALYST203000

PRESIDENT105000

SALESMAN301500

CLERK201100

CLERK30950

CLERK101300

14rowsselected.

SQL>selectjob,deptno,sum(sal)total_salfromempgroupbyrollup(job,deptno);

JOBDEPTNOTOTAL_SAL

CLERK201900

CLERK4150

ANALYST206000

ANALYST6000

MANAGER8275

SALESMAN305600

SALESMAN5600

PRESIDENT5000

29025

15rowsselected.

SQL>selectjob,deptno,sum(sal)total_salfromempgroupbycube(job,deptno);

108750

2010875

309400

18rowsselected.

可以看出,用了rollup的groupby子句所产生的所谓的超级聚合就是指在在产生聚合时会从右向左逐个对每一列进行小结,并在结果中生成独立的一行,

同时也会对聚合列生成一个合计列。

selectdeptno,job,sum(sal)fromempgroupbydeptno,job;

会对每一个不同的dept,job生成一行独立的结果。

而selectdeptno,job,sum(sal)fromempgroupbyrollup(deptno,job);

的结果中除了上述的结果结果之外,还会对每一个deptno进行一个小结,并单独生成一行,除此之外还会对所有的sal求和并生成一列。

这里的groupby后面我们仅仅接了2列,实际上我们可以使用更多列的,这样的话oracle就会以从右向左的方式来进行逐个小结。

这里需要注意的是使用了groupby和rollup后,其后面的列要用括号括起来,否则将会出现ORA-00933:SQL命令未正确结束的错误。

看看grouping、grouping_id函数是什么?

GROUPING函数可以接受一列,返回0或者1。如果列值为空,那么GROUPING()返回1;如果列值非空,那么返回0。GROUPING只能在使用ROLLUP或CUBE的查询中使用。当需要在返回空值的地方显示某个值时,GROUPING()就非常有用。

grouping_id函数

可以返回0,1,2,3...可以分别表示小计,合计等信息。

SQL>selectjob,deptno,sum(sal)total_sal,grouping(job)job_grp,grouping(deptno)deptno_grp,grouping_id(job,deptno)total_grpfrom

empgroupbycube(job,deptno);

JOBDEPTNOTOTAL_SALJOB_GRPDEPTNO_GRPTOTAL_GRP

-----------------------------------------------------------

29025113

108750102

2010875102

309400102

CLERK4150011

CLERK101300000

CLERK201900000

CLERK30950000

ANALYST6000011

ANALYST206000000

MANAGER8275011

MANAGER102450000

MANAGER202975000

MANAGER302850000

SALESMAN5600011

SALESMAN305600000

PRESIDENT5000011

PRESIDENT105000000

已选择18行。

但是我们大多数情况下需要在查询的结果集的汇总列加上“合计”,怎么办呢?用grouping和grouping_id函数,然后再用decode函数判断一下是否为空

就可以了

SQL>selectgrouping_id(job,deptno)asgroup_col,sum(sal)total_salfromempgroupbyrollup(job,deptno);

GROUP_COLTOTAL_SAL

01300

01900

0950

14150

06000

16000

02450

02975

02850

18275

05600

15600

05000

329025

已选择15行。

SQL>selectdecode(grouping_id(job,deptno),1,'合计',job||deptno)asgroup_col,sum(sal)total_salfromempgroupbyrollup(job,deptno);

合计4150

合计6000

合计8275

合计5600

合计5000

ORACLE是一个关系数据库管理系统,它用表的形式组织数据,在某些表中的数据还呈现出树型结构的联系。例如,我们现在讨论雇员信息表EMP,其中含

有雇员编号(EMPNO)和经理(MGR)两列,通过这两列反映出来的就是雇员之间领导和被领导的关系。他们之间的这种关系就是一种树结构。

图1.1EMP表树结构图

7839

|

------------------------------------------------------------------------------------------------

|||

756676987782

---------------------------------------------------------

||||||||

77887902749975217654784479007943--------

||

78767369

扫描树结构表时,需要依此访问树结构的每个节点,一个节点只能访问一次,其访问的步骤如下:

第一步:从根节点开始;

第二步:访问该节点;

第三步:判断该节点有无未被访问的子节点,若有,则转向它最左侧的未被访问的子节,并执行第二步,否则执行第四步;

第四步:若该节点为根节点,则访问完毕,否则执行第五步;

第五步:返回到该节点的父节点,并执行第三步骤。

总之:扫描整个树结构的过程也即是中序遍历树的过程。

树结构的数据存放在表中,数据之间的层次关系即父子关系,在表的每一行中都有一个表示父节点的MGR(除根节点外)。

在SELECT命令中使用CONNECTBY和STARTWITH子句可以查询表中的树型结构关系。其命令格式如下:

SELECT...

CONNECTBY{PRIOR列名1=列名2|列名1=PRIOR列名2}

[STARTWITH];

其中:CONNECTBY子句说明每行数据将是按层次顺序检索,并规定将表中的数据连入树型结构的关系中。PRIOR运算符必须放置在连接关系的两列中某一个的前面。PRIOR运算符在的一侧表示父节点,另一侧表示子节点,从而确定查找树结构时的顺序是自顶向下还是自底向上。在连接关系中,除了可以使用列名外,还允许使用列表达式。STARTWITH子句为可选项,用来标识哪个节点作为查找树型结构的根节点。若该子句被省略,则表示所有满足查询条件的行作为根节点。

例1以树结构方式显示EMP表的数据。

SQL>selectempno,ename,mgr

connectbypriorempno=mgr

startwithempno=7839

EMPNOENAMEMGR

7839KING

7566JONES7839

7788SCOTT7566

7876ADAMS7788

7902FORD7566

7369SMITH7902

7698BLAKE7839

7499ALLEN7698

7521WARD7698

7654MARTIN7698

7844TURNER7698

7900JAMES7698

7782CLARK7839

7934MILLER7782

仔细看empno这一列输出的顺序,就是上图树状结构每一条分支(从根节点开始)的结构。

运算符PRIOR被放置于等号前后的位置,决定着查询时的检索顺序。

PRIOR被置于CONNECTBY子句中等号的前面时,则强制从根节点到叶节点的顺序检索,即由父节点向子节点方向通过树结构,我们称之为自顶向下的方式

。如:

CONNECTBYPRIOREMPNO=MGR//父节点与子节点的关系,在表内存储的数据上体现

PIROR运算符被置于CONNECTBY子句中等号的后面时,则强制从叶节点到根节点的顺序检索,即由子节点向父节点方向通过树结构,我们称之为自底向

上的方式。例如:

CONNECTBYEMPNO=PRIORMGR

在这种方式中也应指定一个开始的节点。

例2从SMITH节点开始自底向上查找EMP的树结构。

connectbyempno=priormgr

startwithempno=7369

在这种自底向上的查找过程中,只有树中的一枝被显示,这是因为,在树结构中每一个节点只允许有一个父节点,其查找过程是从开始节点起,找到其

父节点,再由其父节点向上,找父节点的父节点。这样一直找到根节点为止,结果就是树中一枝的数据。

备注:例2的另外一种写法

SQL>SELECTEMPNO,ENAME,MGR

FROMEMP

CONNECTBYPRIORMGR=EMPNO

STARTWITHEMPNO=7369

在自顶向下查询树结构时,不但可以从根节点开始,还可以定义任何节点为起始节点,以此开始向下查找。这样查找的结果就是以该节点为开始的结构

树的一枝。

例3查找7566(JONES)直接或间接领导的所有雇员信息。

SQL>SELECTEMPNO,ENAME,MGR

CONNECTBYPRIOREMPNO=MGR

STARTWITHEMPNO=7566

STARTWITH不但可以指定一个根节点,还可以指定多个根节点。

例4查找由FORD和BLAKE领导的所有雇员的信息。

STARTWITHENAMEIN('FORD','BLAKE')

在自底向上查询树结构时,也要指定一个开始节点,以此开始向上查找其父节点,直至找到根节点,其结果将是结构树中的一枝数据。

在具有树结构的表中,每一行数据都是树结构中的一个节点,由于节点所处的层次位置不同,所以每行记录都可以有一个层号。

在查询中,可以使用伪列LEVEL显示每行数据的有关层次。LEVEL将返回树型结构中当前节点的层次。

伪列LEVEL为数值型,可以在SELECT命令中用于各种计算。

例5使用LEVEL改变查询结果的显示形式。

SQL>COLUMNLEVELFORMATA20

SQL>SELECTLPAD(LEVEL,LEVEL*3,'')

as"LEVEL",EMPNO,ENAME,MGR

STARTWITHENAME='KING'

LEVELEMPNOENAMEMGR

--------------------------------------------------

17839KING

27566JONES7839

37788SCOTT7566

47876ADAMS7788

37902FORD7566

47369SMITH7902

27698BLAKE7839

37499ALLEN7698

37521WARD7698

37654MARTIN7698

37844TURNER7698

37900JAMES7698

27782CLARK7839

37934MILLER7782

在SELECT使用了函数LPAD,该函数表示以LEVEL*3个空格进行填充,由于不同行处于不同的节点位置,具有不同的LEVEL值,因此填充的空格数将根据各

自的层号确定,空格再与层号拼接,结果显示出这种层次关系。

在对树结构进行查询时,可以去掉表中的某些行,也可以剪掉树中的一个分支,使用WHERE子句来限定树型结构中的单个节点,以去掉树中的单个节点,

但它却不影响其后代节点(自顶向下检索时)或前辈节点(自底向顶检索时)。

WHEREENAME!='SCOTT'

13rowsselected.

在这个查询中,仅剪去了树中单个节点SCOTT。若希望剪去树结构中的某个分支,则要用CONNECTBY子句。CONNECTBY子句是限定树型结构中的整个分

支,既要剪除分支上的单个节点,也要剪除其后代节点(自顶向下检索时)或前辈节点(自底向顶检索时)。

例8.显示KING领导下的全体雇员信息,除去SCOTT领导的一支。

ANDENAME!='SCOTT'

12rowsselected

这个查询结果就与例7不同,除了剪去单个节点SCOTT外,还将SCOTT的子节点ADAMS剪掉,即把SCOTT这个分支剪掉了。

当然WHERE子句可以和CONNECTBY子句联合使用,这样能够同时剪掉单个节点和树中的某个分支。

例9.显示KING领导全体雇员信息,除去雇员SCOTT,以及BLAKE领导的一支。

这个留给大家实践吧:)

像在其它查询中一样,在树结构查询中也可以使用ORDERBY子句,改变查询结果的显示顺序,而不必按照遍历树结构的顺序。

例10以EMPNO的顺序显示树结构EMP中的数据。

ORDERBYEMPNO

在使用SELECT语句来报告树结构报表时应当注意,CONNECTBY子句不能作用于出现在WHERE子句中的表连接。如果需要进行连接,可以先用树结构建立

一个视图,再将这个视图与其他表连接,以完成所需要的查询。

TIMESTAMPWITHTIMEZONE

TIMESTAMPWITHLOCALTIMEZONE

1)Database的timezone可以在创建数据库的时候指定,如:

CREATEDATABASEdb01

...

SETTIME_ZONE='+08:00';

或者在数据库创建之后通过alterdatabase语句修改,但是只有重启数据库后有效:

ALTERDATABASESETTIME_ZONE='+08:00';

查看数据库时区信息:

SQL>selectdbtimezonefromdual;

DBTIME

+08:00

2)session的timezone可以简单通过altersession语句修改:

ALTERSESSIONSETTIME_ZONE='+08:00';

查看session时区信息:

SQL>selectsessiontimezonefromdual;

SESSIONTIMEZONE

---------------------------------------------------------------------------

比如2005-4-614:00:00.000并不能说清楚到底这是日本的下午2点还是中国的下午两点。

假设有一个onlinemeetingsystem

DB服务器在英国dbtimezone(+0:00)[selectdbtimezonefromdual;]

一个客户端c-cn在中国sessiontimezone(+8:00)[selectsessiontimezonefromdual;]

一个客户端c-jp在日本sessiontimezone(+9:00)[selectsessiontimezonefromdual;]

管理客户端c-en在英国sessiontimezone(+0:00)[selectsessiontimezonefromdual;]

===================================================

Timestamp不能(没有)包含任何时区信息

DB有TABLE定义如下:

createtablemeeting_table1(idnumber(10)primarykey,ctimetimestamp);

中国用户插入了第一个会议,早上8点开会

insertintomeeting_table1values(1,to_timestamp('2005-06-298:00:00.0','yyyy-mm-ddhh24:mi:ss.ff'));

日本用户也插入了第二个会议,早上8点开会

(如果是中文字符集也可以使用下列格式转换一下:

insertintomeeting_table1values(2,to_timestamp('2005-06-298:00:00.0','yyyy-mm-ddhh24:mi:ss.ff'));

英国的管理员查询一下这张表,发现两个会议是同时的,

IDCTIME

12005-06-2908:00:00,000000

22005-06-2908:00:00,000000

而实际上应该日本的会议比中国的早一个小时。

英国的管理员如果想参加2号会议的话,他到底该几点去呢?

八点?0点?前一天的晚上11点?数据库完全不能给他一个明确的答复。

c-cn,c-jp来查询也都得到相同的模糊结果:

Timestampwithtimezone显式包含时区信息

createtablemeeting_table2(idnumber(10)primarykey,ctimetimestampwith

timezone);

中国、日本用户同样插入上例中的两个会议

英国的管理员查询表时,返回的结果就清晰多了:

select*frommeeting_table2;

12005-06-2908:00:00,000000+08:00

22005-06-2908:00:00,000000+09:00

他可以知道meeting2是在东九区的早上八点开始的,去参加的话,

前一天晚上11:00他就要接进webmeeting了。

c-cn,c-jp来查询也都与c-en结果相同

结果都包含时区信息,所以是精确的,不可能被混淆。

Timestampwithlocaltimezone隐式包含时区信息

客户session里面时区的不同自动转换:

*插入时,从客户端的时区转到数据库时区

*显示时,从数据库时区转到客户端的时区

createtablemeeting_table3(idnumber(10)primarykey,ctimetimestampwith

localtimezone);

c-cn,c-jp同样插入上例中的两个会议

c-en的查询结果:

12005-06-2900:00:00,000000

22005-06-2823:00:00,000000

c-cn的查询结果:

22005-06-2907:00:00,000000

c-jp的查询结果:

12005-06-2909:00:00,000000

INTERVAL"2-6"YEARTOMONTH

下面的例子表示3天12个小时30分钟6.7秒:

INTERVAL"312:30:06.7"DAYTOSECOND(1)

因为有精度问题,相对来讲,INTERVALDAYTOSECOND比INTERVALYEARTOMONTH要复杂一些

SQL>selectsysdate,sysdate+numtoyminterval(1,'month'),sysdate+numtoyminterval(1,'year')fromdual;

SYSDATESYSDATE+NUMTOYMINTESYSDATE+NUMTOYMINTE

2012-07-0908:18:592012-08-0908:18:592013-07-0908:18:59

SQL>selectsysdate,sysdate+numtodsinterval(1,'day'),sysdate+numtodsinterval(1,'second')fromdual;

SYSDATESYSDATE+NUMTODSINTESYSDATE+NUMTODSINTE

2012-07-0909:09:062012-07-1009:09:062012-07-0909:09:07

1,REGEXP_LIKE:与LIKE的功能相似

2,REGEXP_INSTR:与INSTR的功能相似

3,REGEXP_SUBSTR:与SUBSTR的功能相似

4,REGEXP_REPLACE:与REPLACE的功能相似

它们在用法上与OracleSQL函数LIKE、INSTR、SUBSTR和REPLACE用法相同,

但是它们使用POSIX正则表达式代替了老的百分号(%)和通配符(_)字符。

'^'匹配输入字符串的开始位置,在方括号表达式中使用,此时它表示不接受该字符集合。

'$'匹配输入字符串的结尾位置。如果设置了RegExp对象的Multiline属性,则$也匹配'\n'或'\r'。

'.'匹配除换行符之外的任何单字符。

''匹配前面的子表达式零次或一次。

'+'匹配前面的子表达式一次或多次。

'*'匹配前面的子表达式零次或多次。

'|'指明两项之间的一个选择。例子'^([a-z]+|[0-9]+)$'表示所有小写字母或数字组合成的字符串。

'()'标记一个子表达式的开始和结束位置。

'[]'标记一个中括号表达式。

'{m,n}'一个精确地出现次数范围,m=<出现次数<=n,'{m}'表示出现m次,'{m,}'表示至少出现m次。

\num匹配num,其中num是一个正整数。对所获取的匹配的引用。

[[:alpha:]]任何字母。

[[:digit:]]任何数字。

[[:alnum:]]任何字母和数字。

[[:space:]]任何白字符。

[[:upper:]]任何大写字母。

[[:lower:]]任何小写字母。

[[:punct:]]任何标点符号。

[[:xdigit:]]任何16进制的数字,相当于[0-9a-fA-F]。

各种操作符的运算优先级

\转义符

(),(:),(=),[]圆括号和方括号

*,+,,{n},{n,},{n,m}限定符

^,$,anymetacharacter位置和顺序

*/

--创建表

createtablefzq(idvarchar(4),valuevarchar(10));

--数据插入

insertintofzqvalues('1','1234560');

insertintofzqvalues('2','1234560');

insertintofzqvalues('3','1b3b560');

insertintofzqvalues('4','abc');

insertintofzqvalues('5','abcde');

insertintofzqvalues('6','ADREasx');

insertintofzqvalues('7','12345');

insertintofzqvalues('8','adcde');

insertintofzqvalues('9','adc,.de');

insertintofzqvalues('10','1B');

insertintofzqvalues('10','abcbvbnb');

insertintofzqvalues('11','11114560');

insertintofzqvalues('11','11124560');

--regexp_like

--查询value中以1开头60结束的记录并且长度是7位

select*fromfzqwherevaluelike'1____60';

select*fromfzqwhereregexp_like(value,'1....60');

--查询value中以1开头60结束的记录并且长度是7位并且全部是数字的记录。

--使用like就不是很好实现了。

select*fromfzqwhereregexp_like(value,'1[0-9]{4}60');

--也可以这样实现,使用字符集。

select*fromfzqwhereregexp_like(value,'1[[:digit:]]{4}60');

--查询value中不是纯数字的记录

select*fromfzqwherenotregexp_like(value,'^[[:digit:]]+$');

--查询value中不包含任何数字的记录。

select*fromfzqwhereregexp_like(value,'^[^[:digit:]]+$');

--查询以12或者1b开头的记录.不区分大小写。

select*fromfzqwhereregexp_like(value,'^1[2b]','i');

--查询以12或者1b开头的记录.区分大小写。

select*fromfzqwhereregexp_like(value,'^1[2B]');

--查询数据中包含空白的记录。

select*fromfzqwhereregexp_like(value,'[[:space:]]');

--查询所有包含小写字母或者数字的记录。

select*fromfzqwhereregexp_like(value,'^([a-z]+|[0-9]+)$');

--查询任何包含标点符号的记录。

select*fromfzqwhereregexp_like(value,'[[:punct:]]');

22.5REGEXP_REPLACE(字符串替换函数)

REPLACE函数是用另外一个值来替代串中的某个值。例如,可以用一个匹配数字来替代字母的每一次出现。REPLACE的格式如下所示:

原型:regexp_replace(x,pattern[,replace_string[,start[,occurence[match_option]]]])

每个参数的意思分别是:

x待匹配的函数

pattern正则表达式元字符构成的匹配模式

replace_string替换字符串

start开始位置

occurence匹配次数

举例来讲:

SQL>selectregexp_replace('helloeverybody,047courseswillbeoversoon,thanks.','b[[:alpha:]]{3}','one')fromdual;

THE END
1.在文化习俗中这个日期代表着什么含义或象征吗首先,4月20日通常与春季有关,因为这一时期许多地区正处于温暖而鲜花盛开之际。这种自然景观往往会被用作庆祝生机、希望和新开始的情绪表达。在一些宗教传统中,春季也被视为复活和更新的时候,因此这一天可能会有特别的仪式或仪式来纪念这些概念。 其次,有些人认为这个日期具有特殊意义,比如它距离冬至(12月21/22)后https://www.rrxveryc.cn/shi-shang-da-pei/289631.html
2.12月24日是什么日子,12月24日是什么节日当天是什么日子,是黄道吉日吗 周2024年12月24日是第52周,星期二 天2024年12月24日是2024年的第359天 节2024年12月24日是平安夜 吉2024年12月24日值神是天刑,黑道日 忌2024年12月24日是开日不适合做生意 今日黄历 公历:2024年12月24日 农历:二零二四年十一月二十四日 干支:甲辰年 丙子月 https://m.k366.com/hl/rizi_12-24.html
3.如何解释那些在这个时期举行传统习俗或仪式的人们对这一天的情感在探讨12月9日所代表的意义和价值观念之前,我们首先需要明确这天究竟是什么节日。对于不同文化背景下的人们而言,12.9可能意味着截然不同的东西,它可能是一个普通的工作日,也可能是某个重要节庆的开始。 然而,不论其具体含义如何,这一天对于许多人来说都是一个值得特别关注和纪念的时刻。它们不仅仅是日期上的标记,https://www.paimingb.com/wen-zi/622727.html
4.中国文化中的十二探秘这个数字背后的故事与象征首先,让我们来看看在中国传统历法中,一个月有多少天?是12个!古人将一年分为四季,每季又分为3个月,所以每一年的确切日期都是通过农历来计算出来的。在农历里,每年都有一些特殊的节气,比如立春、清明、小满、大暑等,这些节气通常与黄道上的某些星座相对应,而这些星座也是由12个组成。 https://www.lya72p0gb.cn/min-su-wen-hua/296411.html
5.12day有什么特殊含义12day是出自于朋友、恋人、家人的笔画,是指特殊的寓意难忘。12也用作网名,或者用作恋人、闺蜜之间的https://iask.sina.com.cn/jxwd/6dXHCuG9cpE.html
6.2016高考英语核心考点轻松阅读:词类高考复习指南高考英语有些物质名词的复数形式有特殊的含义。 rains大量的雨水、多场雨 snows大量的雪、雪堆、多场雪 winds多场风 waters大片水域 sands沙堆、沙丘 (4)专有名词 专有名词一般视为不可数名词,有时也可成为可数名词,可以由a/an修饰或用复数形式。 The Greens are expecting us this evening. https://yy.chazidian.com/show-221262-56/
7.初三英语知识点总结初三英语Unit12 1. be supposed to do . 应该 如:We are supposed to stop smoking. 我们应该停止吸烟。 知识拓展 表示应该的词有:should, ought to ,be supposed to 2. shake hands 握手shake 本意是“摇动、震动” 3. You should have asked what you were supposed to wear. http://m.hujiang.com/zx/p251900/
8.英语语法知识难点解读特殊疑问句:疑问词+be +主语+过去分词+(by~)? 被动语态的时态是由be的时态决定的,be是什么时态,全句就是什么时态,be动词后面的过去分词不变。 一、 被动语态的用法: 1. 一般现在时的被动语态构成:is / am / are + 及物动词的过去分词 Our classroom is cleaned everyday. I am asked to studhttp://www.360doc.com/content/14/0628/09/18357269_390429454.shtml
9.英语语言与西方文化12篇(全文)英语中有许多格言,和汉语类似,格言的含义往往与字面意思不同,是对字面意思的一种延伸,这些格言有很多和宗教文化有關。 基督教是西方最主要的宗教之一,其经典《圣经》则被教徒奉为圭臬,英语语言中很多格言与圣经有关。比如“atreeisknownbyit’sfruit”这句话在英语地区广为流传,其字面意思是“看果实就知道这是一https://www.99xueshu.com/w/ikeyt10chz0z.html
10.vfp命令给两表设置索引vfp建立索引SQL Sever索引类型有:唯一索引,主键索引,聚集索引,非聚集索引。 MySQL 索引类型有:唯一索引,主键(聚集)索引,非聚集索引,全文索引。 深入浅出引出含义 实际上,您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也https://blog.51cto.com/u_16099246/11435664
11.我还是喜欢你这张牌本身的含义是 值得信赖的、会得到援助、良好的建言者、有贡献的、心胸比较宽广、有宗教情绪的。 这是一张开启智慧,拥有精神上援助的一张牌 暗示你向某人或某个群体的人屈服了。也许你觉得这是为自己及心灵上的需求负起责任的时刻,你目前的行事作风并非应付事情的唯一方式,假设你愿意加以探索的话,或许你就会https://www.meipian.cn/1z5665fi
12.零基础说英语第六单元这句同样可以作为例句1的回答,由于上午和下午都有1-12点的时间,所以在时间后面加上am和pm作为区分,am即上午,pm即下午。 5.It’s ten to eleven. 还有10分钟到11点。/10点50分了。 如果还有不到30分钟到下一个整点,那么这种表达方式有时更方便些,这里使用了介词”to”, 表示“到”,”to”的前面是到下https://www.jianshu.com/p/e0f1ad2db34a