网络上有数不尽的关于Oracle的资料,但是大部分都是课本或者用户手册上的官方解释。在学习数据库时我也是遇到了同样的问题。所以为了使用方便在各种文本中总结出这些资料希望能够帮助大家,少走弯路尽快的学会和使用Oracle. 第1讲数据库基本概念,工作模式
1. 为什么要使用数据库
简单的来说,数据库是一种专门用于存储数据的软件。在数据存储方面具有很多有点。
在以前的程序中,数据的存储通常会选择文本文件,下面列举了一些数据库与文本文件之间的优劣对比,让我们对数据库软件有一个初步的认识: ? 文件系统不适合存储数据量比较大的信息 ? 文本文件中存储的数据都是字符串类型 ? 没有考虑并发访问问题
? 文件系统不会对数据的有效性和完整性作出检查 ? 没有任何安全保护
对于现代企业应用而言,数据本身具有非常重要的价值,甚至可以说数据比应用更加重要。应用瘫痪了可以恢复,甚至可以重新开发,而数据丢失了,就会对企业造成重要的损失。比如,一个金融如果应用丢失了客户信息,对企业来讲就无法确认哪些用户在企业中有存款,存款金额是多少,这对企业来将将会是致命的损失。
所以,为了保证数据的安全,几乎所有的企业应用都会选择数据库软件作为数据存储的方式,同时数据库还可以在数据处理,检索等方面为应用程序提供帮助。
目前市场上主流的数据软件有:
? Oracle(甲骨文)公司出品的 Oracle 数据库 ? IMB公司出品的DB2数据库
? 微软公司出品的MS SQLServer 数据库。
? 以及开源的MySQL数据库(mysql数据库被SUN公司收购,之后SUN公司又被
Oracle公司收购)
除此之外,还有许多其他厂商的产品,如sybase,postgreSQL等等。
2. 什么是关系型数据库
数据库(database)就是一个由一批数据构成的有序集合,这个集合通常被保存为一个或多个彼此相关的文件。这些数据被分门别类地存放在一些结构化的数据表(table)
里,而数据表之间又往往会形成种种内在的交叉引用关系。存在于数据表之间的这种关系(relation)使数据库又被称为关系数据库。
让我们来简单解释一下面关于关系型数据库的定义。首先数据库中得主要内容是数据,数据在数据库中是以表(table)的形式存在的,这很像我们平时熟知的execl文件的形式,一个表的结构由列(column)组成,表中的数据由行(row)组成,如下图所示:
在数据库中数据的逻辑存储格式就是上图的样子。那么,关系型数据库中的“关系“二字是如何而来的呢?它的意思是说在数据与数据之间是存在联系的。 我们假设上面的表格存储的是学生数据,现在我要记录每个学生每天的签到时间。这是我们就需要另外一张表来记录签到数据。如下图所示:
现在我们要查看每个学生的完整信息,以及他们每天的签到时间的话,就需要同时浏览两张表中的数据,而这两张表中的数据是通过学生表中得id列和签到表中得stu_id 列关联起来的。所谓关系型数据库,这的就是数据和数据之间并非孤立存在的,而是相互联系的。如下图所示:
3. 关系型数据库的工作模式
接下来我们简要介绍一下关系型数据库的工作模式:
1) 关系型数据是基于客户端服务器模式工作的
原因很简单,数据库中得数据是为多个用户共同服务的。所以任何一个用户也不应当独享数据库中的数据,只能通过数据库的客户端程序来对数据库进行访问。数据库服务器可以并发处理多个用户的请求。 A 客户端
TCP/IP Socket 数据库服务器 B 客户端 TCP/IP Socket Tables
TCP/IP Socket C
客户端 2)数据库通过SQL语言 (Structured Query Language)对数据进行管理 SQL 是一门 ANSI 的标准计算机语言,用来访问和操作数据库系统。SQL 语句用于取回和更新数据库中的数据。所有的数据库厂商都会遵从SQL规范来设计自己的产
品,这就是说,在不同的数据库之间标准SQL语句是可以通用的。当然,各个厂商也会结合自身的特点对标准SQL进行扩展。对于程序员而言,标准SQL的学习占到了学习总量的80%以上。
4. 安装Oralce xe :
Oracle xe 是oracle公司推出的一个简化版本。这个免费版本也被称为“Oracle
Database 10g Express Edition”(XE版)。这款产品主要面向新手、应用开发爱好者和其他想尝试数据库产品的人士。XE版仅有150M大小,不过和其他的“超大型”标准版产品完全兼容,带有所有重要的API(应用编程接口)。目前供下载的版本同时支持Windows和Linux操作系统。Mendelsohn表示,开发者可以用XE版来开发产品,然后无缝地升级到“Oracle标准版一”或更高的版本。下面想大家介绍oracle xe的安装过程 1) 从oralce官方网站下载oracle xe , 注意选择合适的操作系统版本。
http://www.oracle.com/technetwork/database/express-edition/downloads/index.html
2)运行安装文件,在安装程序做好安装准备后,出现如下界面,直接点击“下一步“即可
接下来选择接受用户协议,并点击下一步 :
选择数据库的安装目录:
点击下一步后,设置数据管理员的密码,改密码应当牢记,数据库管理员拥有管理数据库的最高权限。只有对数据库进行配置时才会使用该账号,平时基本都会使用普通账号对数据库进行操作.
点击下一步之后,进入安装环节,需要等待一段时间。安装环节结束之后,即可点击完成,安装程序会自动启动数据库管理页面,这是Oracle提供的一个网页形式的管理工具。用于对数据库进行各种管理工作。用户名输入System(即数据库管理员)密码就是在安装过程中指定的密码。
进入管理页面后,我们通过管理菜单创建一个普通用户,毕竟System(数据库管理员)是拥有极高权限的管理账户,在日常使用过程中不会直接使用。
在创建用户页面中输入新的用户名和密码后,点击创建按钮即可。同时要注意,用户状态设定为未锁定,用户角色选中 CONNECT和 RESOURCE 。
在Oracle 中,还有一个非常特殊的账号,叫hr账户,这个账户中预先创建好了一些表和数据,学习oracle的新人通常都是通过hr账户开始了解SQL语句和数据库的。这个账户默认情况下是出于锁定状态的,下面,我们通过oracle管理页面来解锁这个账户。以system账户登录数据库管理页面,并选择管理用户选项
进入管理用户页面后,我们会看见现有用户列表:
点击HR图标,输入新的密码,将用户状态设定为未锁定状态后,点击变更用户即可。
第2ud讲使用客户端工具链接oracle服务器
对于Oracle数据库来说,有两种常用的客户端,一种是基于c/s结构的 SQLPLUS,一种是基于B/S结构的管理页面。我们首先介绍SQLPLUS的使用方式。 1, SQLPLUS的使用方式:
如果你的数据库是安装在本地计算机上得话,可以在开始菜单中直接启动SQLPLUS程序。 在开始菜单中找到(oracle database 10g express edition),然后选择”运行SQL命令,弹出的Shell窗口极为SQLPLUS程序:
当SQLPLUS刚刚启动时,是没有与数据库建立链接的。要建立链接,我们需要使用connect命令,命令格式如下:
SQL>connect username/password
当但看到已连接字样时,说明数据库链接成功, 上图中显示的 “SQL>”为命令提示符,我们会在命令提示符下输入SQL命令。下面我们做个简单的实验,输入: “select table_name from user_tables ;” ,并输入回车键,我们会看到如下显示(不同账户下显示结果可能不同)
该命令的作用是查询所有表的名字,目前我们还不用对该命令的原理特别在意,我们会在后面的学习过程中详细讲解。
也许有同学发现,在输入SQL语句时,如果没有输入分号直接键入回车的话,SQL语句并没有被执行,而是出现一个”2”,如下图所示:
这是因为在SQLPLUS中查询语句要使用分号作为结束标记。图中的”2”表示行号,如果一条
查询语句太长,可以分多行输入,在最后一行输入分号。
建议使用文本编辑器书写SQL,写好后将SQL复制->粘贴到SQLPLUS窗口。好处:
? 写错了容易修改 ? 便于保存
当Oracle数据库没有安装在本地电脑中得时候,我们无法直接使用SQLPLUS命令。这时需要先使用telnet命令连接数据库服务器,然后在telnet环境下运行SQLPLUS : 比如 :
telnet 192.168.0.25 (数据库服务器的IP地址)
属于用户名和密码后再telnet的命令提示符下输入sqlplus即可进入SQLPLUS。
2) 数据库管理页面的使用方法:
数据库管理页面是Oracle提供的一种基于网页的交互模式,其特点是使用更见简单。进入管理页面的方法有两种:
A , 当数据库安装在本地时,通过开始菜单,找到oracle database 10g express edition , 然后选择“转到数据库主页”. B, 当数据库安装在其他电脑上时,需要打开浏览器,并在地址栏中输入 : http://127.0.0.1:8080/apex(127.0.0.1为数据库服务器的ip地址)。即可进入.如下图所示 :
输入用户名密码后,点击登录,即可进入管理页面。
进入管理页面后,点击SQL选项,即可进入SQL命令执行页面:如下所示:
我们输入与SQLPLUS相同的命令,来看一下运行效果 :
第3讲SELECT语句
select 语句用于查询数据库中的数据,在使用select 语句之前,我们首先要介绍一下如何查看一个表的结构,即一个表由那些列组成,只有了解了一个表的结构之后,我们才能通过select语句对该表进行查询。
在Oracle数据库中,使用desc命令查看一个表的结构,命令格式为: desc 表名字。比如我们想查看 employees表由那些列组成,就可以输入命令desc employees 我们会看到如下结果:
在返回结果中,我们可以清晰的看到employees 包含那些列,每一列都是什么数据类型,是否允许空值出现等信息。 1, select 语句的基本语法
在掌握了一个表的结构之后,我们就可以使用select语句查询一个表中得数据了,select 语句最简单的格式是:
Select列名1, ,列名2 , … , 列名n from表名字
其中select 关键字表示要对表中得数据进行查询操作, select之后为要查询的列的名字,一个表由多个列组成,我们把需要查询的列写在select 后面,列名之间使用”,”分割。from 关键字用于指明要查询的表名字。 比如:
select name , age from students 。从students表中查询 name 和 age 两个列的数据
select name , salary from employees 。从employees表中查询name 和salary 两个列的数据。
select first_name , last_name , hire_date , email from employees 。从employees表中查询first_name,last_name ,hire_date , email 四个列的数据。我们看看这条语句的实际运行结果:
如果在查询一个表的时候,忘记了该表有哪些列组成,或者忘记了某个列的准确名字时,大家可以回忆一下上一节中学习的 desc 命令,通过该命令可以查看一个表的具体结构。
在select 语句中使用*
前面我们学习了select 语句最基本的语法结构。如果我们需要把一个表中所有的列都查询出来,而这个表的列数有比较多得话。上述写法就会比较麻烦,因为我们必须在select之后把所有的列名字都写出来。这时我们可以用一种简单方法代替,即使用*号,代表要表中得所有列,比如: select * from employees , 这条查询语句是说,把employee表中所有的列全部查询出来,结果如下:
使用* 虽然是一种简洁的方式,但是我们在编写SQL语句时,尤其是将来在程序中编写SQL语句时还是要尽量避免使用。因为这样会降低程序的可读性,对于阅读SQL语句的人来将,很难通过该语句判断查询的列数和列名,另外从执行效率上来讲,*的执行效率也比写列名字的方式低一些。
2, 如何限制返回结果的行数
上一节中我们学习了如何使用select 语句查询一个表中的所有数据。在很多情况下,我们需要依据摸个条件查询部分数据,比如我们需要查询工资在10000以上的员工的信息,或者women要查询90号部门的所有员工。这个时候,我们就需要对表中的所有数据进行
过滤,从全部数据中找出符合我们要求的数据来,这时我们就需要在select 语句中使用where子句了。比如:
select * from employees where salary>10000
where 后面跟的是一个布尔表达式,也称作查询的条件,只有满足查询条件的数据才会被纳入到最终结果中。上述SQL的运行结果如下:
从结果中可以看出,只用salary 大于10000的员工信息被查询出来,不符合查询条件的数据被排除在查询结果之外了。
那么where子句是如何工作的呢。其实很简单,当整条sql被执行的时候,对于数据库会扫描表中得所有数据,并逐个判断当前数据是否符合查询条件,如果符合条件,则将该数据放入查询结果集,否则就将当前数据排除在查询结果之外。我们可以借助下图来分析where语句的执行过程
从上图的表现形式来看,表中得每一条数据都要进行一次where条件的判断,并且只有满足条件的语句才能被最终列入到查询结果中,也就是说,如果表中有10000条数据,那么where后面的条件就要被判断10000次,如果在这10000次判断中,只有20条符合查询条件,那么最终的查询结果就只有20行。
3,where子句中的布尔运算符
可以使用在where子句的布尔运算符非常简单,和我们在java程序中使用的基本一致: >大于预算
<小于运算
>= 大于等于运算 <= 运算
= 等于运算,这里要和java中的”==”运算区分开,在数据库中,使用”=”标示等值判断 != 不等于运算,同时也可以写成”<>” 当where子句后需要有多个查询条件的时候,我们可以通过“and” , “or” ,”not”来进行组织,比如我们要查询90号部门中工资大于10000的员工,就需要两个查询条件,一个是部门id等于90 ,另一个是工资大于10000 ,两个条件缺一不可。这是就需要”and”来进行与预算了,写法如下:
select * from employees where department_id = 90 and salary > 10000 查询结果如下:
在比如,我们要查询 90号部门的所有员工和60号部门的所有员工,这里也需要两个条件,即部门id等于90 或者部门id等于 60 ,这两个条件之间是或者的关系,也就是说满足其中一个即可。这是就可以使用”or”来进行或运算:
Select * from employees where department_id = 90 or department_id=60 查询结果如下:
通过and 和 or 可以灵活组织出多种多样的查询条件,如
Select * from employees where ( department_id = 60 or department_id=90 ) and salary > 10000 这条语句的意思是查询 60 号和90号部门中薪资大于10000的所有员工,跟多的组合方式
需要大家在动手练习过程中慢慢熟悉。
另外强调一点,个运算符之间有优先级的概念,所以在进行多个运算符组合是,最好通过括号来保证正确的运算顺序。
4, between…and 和 in 运算
前面我们提到的运算符大多可以在java语言中找到对应的运算符,在SQL语言中,也有一些Java语言中没有的运算符,比如between … and运算符合in运算符。我们来了解一下这两个预算符的使用方法。
有如下语句,用于查询工资大于等于1000 并且小于等于2000的所有员工. Select * from emp where salay >=1000 and salay <=2000 对于上述SQL 也可以使用between.. and 来表示: Select * from emp where sal between 1000 and 2000
需要注意的是,使用between.. and 进行预算时,查询条件是包含边界值的。另外较小的边界值必须写在前面,较大的边界值必须写在后面。如果顺序错误的话,将不会得到查询结果。大家可以通过练习自己验证一下。
接下来我们看in语句。如果我们想查询90,60 ,100 三个部门的员工的话,就需写3个查询条件,彼此之间使用or 连接:
Select * from employees where department_id = 90 or department_id=60 or department_id=100 三个条件看起来不够简洁,在这种情况之下,我们可以使用in运算简化该条件.
Select * from employees where department_id in( 90 , 60 , 100 ) 这种写法的运算逻辑和上面SQL完全一致。查询结果如下:
in 预算的意思是,只要和括号中任意一个值相同,即算满足条件,所以各个值在括号中出现的先后顺序对查询结果没有影响,即in( 10, 20 , 40 ) 和 in(40 , 20 , 10 )是完全一样的效果。
还要注意between…and必须小值在前
5,使用LIKE进行模糊查询
模糊查询是程序中经常用到的查询方式,首先我们来介绍一下什么是模糊查询,所谓模糊查询就是指无法为查询条件指定准确的取值,比如说我们要查询所有电话号码以011开头的员工,我们的查询条件只能精确到电话号的前三位,在这种情况下,是无法使用精确查询的。如果我们把查询条件写成:where phone_number = ‘011’的话是一定查不出任何结果的,因
为电话号码的长度超过3为,任何一个电话号码也不会只由“011”三个数字组成。在这种情况下我们就需要使用模糊查询了。
首先,我们需要先来学习两个特殊的符号,也叫做模糊查询中得占位符。用于和具体的字母和数字一起组成一个模糊查询的条件,这两个符号是:
“%”代表0到任意多个字符。 “_”代表一个任意字符。
通过两个占位符和普通字符的组合,就可以组成多种多样的模糊查询条件,比如:
‘%m’表示已m结尾的任意字符,’aaam’ , ‘bm’ , ‘m’ , ‘121m’,都符合这个条件.它所标示
的含义是前面有0到多个任意字符,最后一个字符是’m’。
‘m%’标示以m开头的任意字符,’maaa’ , ‘mbbb’ , ‘m’ , ‘m121’ ,都符合这个条件,但是 ‘1maaaa’不符合该条件,以为’m*’代表的含义是第一个字母是m , 后面可以有0 多个任意字符.
‘_m’ , 以m结尾的两位字符,前面的”_”标示一个任意字符,不管字符是什么,但是必
须有一个,也就是说对字符是什么没有要求但是对数量有要求。’am’ , ‘bm’ , ‘cm’都符合这个条件,但是’m’ , ‘aam’ , ‘22m’就不符合这个条件的要求了。 ‘%m_’表示m为倒数第二个字符的任意字符串。 ‘_m%’表示m为整数第二个字符的任意字符串。
‘%java%’表示含有’java’的任意字符串,无论java出现在开头,还是结尾,还是中间。 更多的标示方法,大家可以再以后的联系中慢慢熟悉。
在了解如何表示一个模糊查询条件之后,我们再来学习”like”关键字,在进行模糊条件判断是,不能使用我们前面学习的”=” , 而要使用like ,用法如下:
Select * from employees where phone_number like ‘011%’ 查询结果如下:
我们再次查询名字以’Al’开头的员工信息:
Select * from employees where first_name like ‘Al%’
再擦寻名字中包含”na”两个字母的员工信息:
Select * from employees where first_name like ‘%na%’
前面我们提到的模糊运算都是针对字符串类型进行的。其实对于数字和日期类型可以使用模糊查询。但是在进行模糊查询之前,oracle 会自动将数字和日期类型转化为字符串类型在进行查询。
第4讲使用SQL运算符和函数1
1. 算术运算符及相关函数
? 在oracle中可以使用 + - * / 对于数字类型进行算术运算,
Select first_name , last_name , salary , salary*2 from employees;
上述SQL除了查询了员工名字,薪水意外,还查询了2倍工资的数额。在使用算数用算符时,即可以有查询列参与,也可以没有查询列参与。比如我们想知道100+200等于多少,我们就可以写成 select 100 + 200 from employees ; 查询结果如下:
第10讲子查询
首先我们通过一个例子来了解什么是子查询。我们要将公司中工资最高的人的姓名,工资和电话查询出来。我们首先想到的方式是:
Select first_name , last_name , phone_number , salary From employees
Where salary = max( salary );
但是这条SQL在编译时会出现语法错误,原因也很简单,我们在上一讲中强调过,where语句是在分组之前执行的,在没有分组之前,max(salary) 是无法获得的。所以在where语句中无法直接使用组函数( count,max,min,sum,avg)作为查询条件。
所以我们只能把上述查询要求分成两个查询操作来完成: 1,查出公司的最高工资是多少。
2,以最高工资为条件,查询员工姓名等信息。 select max(salary) from employees
select first_name , phone_number , salary from employees where salary = 24000
在数据库操作中,我们期望使用最少的SQL语句完成查询要求,这样可以提高执行效率,也会使代码更加简洁。利用子查询,可以将上面两个查询语句,合并成一条查询语句:
select
first_name , phone_number , salary from
employees where
salary = ( select max(salary) from employees )
程序的执行结果完全一致。在上面的例子中,我们把select max(salary) from employees 的查询结果直接参与到了where条件的比较中,因此我们把这条查询语句称作子查询。
1. 子查询概念
1) 查询的结果如果是一行一列,可以将结果看做一个值,参与条件比较或显示在
SELECT子句。
2) 查询的结果如果是多列,可以将结果看做一个临时表,可以针对此临时表进行再次
查询、分组、排序、表连接等各种操作
2. 将子查询看做是一个值
在前面查询工资最高的员工例子中,我们已经看到了这种子查询的用法,需要注意的是对于主查询的每一行都会运行子查询,回忆一下我们前面讲过的where的执行特点,表中的每条数据都会参与where运算,来决定这条数据是否满足查询条件。所以where条件是要重复执行的。那么子查询是where子句的一部分,每次where语句执行的时候,子查询都会被执行一次。
我们再来通过一个例子了解一下单值子查询的用法,查询工资低于公司平均工资的员工信息. select
first_name , phone_number , salary from
employees where
salary < ( select avg(salary) from employees ) 部分运行结果为:
接下来,我们再来看一个子查询的例子:查询每个部门具有最高工资的员工信息 select * from employees e1 where e1.salary =
(
select max(e2.salary) from employees e2 where e2.department_id = e1.department_id )
运行结果如下:
在上面的例子中,我们将在子查询中使用了外层查询的类作为where条件,
(where e2.department_id = e1.department_id) 这种用法看起来有些复杂,实际上,我们只要理解了子查询的执行策略就容易解释这个问题了。在前面我们介绍过,employees表中的每条数据都要进行where运算,也就是说针对employees表中的每条数据,都会进行一次子查询。在每次子查询运行的过程中,外层查询的department_id (e1.department_id)都是一个固定值:
比如,当前where条件是对101号员工进行判断,那么e1.department_id 就等于90(在employees表中,101员工的部门号为90) ,子查询代码就变成: select max(e2.salary) from employees e2 where e2.department_id = 90 当where条件对103号员工进行判断时,子查询语句就变成: select max(e2.salary) from employees e2 where e2.department_id = 60 当where条件对108号员工进行判断时,子查询语句变成
select max(e2.salary) from employees e2 where e2.department_id =100
这样我们可以保证,每次与员工与员工工资进行比较的都是该员工所在部门的最高工资。需要特殊说明的是在上例中,我们为了区分外层查询和子查询,我们为employees表取了两个别名,分别是e1 和 e2 ,这样做的目的是为了区分 e1.department_id = e2.department_id 。为表取别名不能使用”AS”。
大家可以自己思考一个问题:使用本题的思路实现显示员工信息的同时,显示他所在部门的最高工资
3. 将子查询看做一个临时表
我们来回忆一下以前遇到的一个问题,查询工资最高的前5名员工,当时我们的sql语句是这样写的: select * from employees where rownum <=5 order by salary , 通过观察查询结果我们发现,这条SQL查询的数据是错误的,因为排序是发生在查询之后的,所以上面的SQL语句只是对前五个员工的工资进行了排序,并不是对所有员工的工资进行排序。
现在可以通过子查询来间接解决这个问题。我们的思路是:先利用子查询将所有员工按照工资排序,将排序后的查询结果看成一张临时表临时表,再对此临时表进行查询,
使用ROWNUM限制返回行数 select * from ( select * from employees order by salary desc
)
where rownum <=5 ; 查询结果为:
思考:查询工资排在第6 到第10之间的5位员工。
第11讲连接查询
在我们前面学习的查询技术中,有一个共同的特点,就是查询的数据都是来自同一张表。在很多时候,我们需要同时查询多张表才能获取所需数据。比如我们熟悉的employee表中,保存了每个员工的部门ID号,而部门的详细信息,如部门名称,则保存在departments表里,如果我们现在需要查询每个员工的个人信息,以及所属部门名字的话,就需要同时查询employees表和departments表,这时就需要用到连接查询技术。 Employees表和departments表的表结构以及部分数据如下图所示:
Employees 表的部分数据:
Departments 表的部分数据: