数据库原理和应用
数据库原理和应用
数据库基础知识
什么是数据库?
数据库有哪些种类?
常见的数据库软件有些?
SQL概述
标准化
特点
SQL功能
|
操作符
|
数据查询
|
SELECT
|
数据定义
|
CREATE,ALTER,DROP
|
数据操纵
|
INSERT,UPDATE,DELETE
|
数据控制
|
GRANT,REVOKE
|
SQL命令基础
基本的select命令
SELECT命令用于从数据库中获得想要的信息。
语法:SELECT { * , column [alias] , ……} FROM table;
一个最简单的查询语句至少要包括SELECT子句和FROM子句:
SELECT后面指定要选择的列
FROM后面指定从哪些表或视图中获取数据
select语法规则
SQL命令是大小写不敏感
SQL命令可写成一行或多行
一个关键字不能跨多行或缩写
子句通常位于独立行,以便编辑,并易读
空格和缩进使程序易读
关键字大写,其他小写
select * 显示所有列
例:select * from table
选择指定的列
例:select id,name from table
查看表具有哪些列
例:desc table
获取表的列信息
例:select id,name,age from table where age = 20
使用算术运算
例:select name,salary,salary*13 from table
关于空值
例:select salary,salary*12 from table
空值指不可用,不适用的值
空值不等于0也不等于空格
对空值进行的任何运算都是空值
定义列的别名
例:select name as '姓名',salary*13 ‘年薪’ from table
缺省情况下,列的别名是大写的。如果区别大小写,可加双引号,如有特殊字符如‘$’、‘#’也必须使用双引号将其括起来。 上面的例子中的as可以省略
列链接操作
例:select name||'''s salary is '||salary as '员工薪资' from table
双竖线‘||’操作符,可将列和运算表达式常量连起来显示,形成一个输出显示
去除重复记录
例:select distinct age from table
如果在DISTINCT后面指定了多个列,则DISTINCT将对所有被选择的列有效,其结果是不同的列的组合
SQL*PLUS程序介绍
SQL*PLUS是Oracle自带的与Oracle交互的一个工具。你可在SQL*PLUS中做以下操作:
执行SQL命令来修改、查询、增加、删除数据库中的数据
格式化、计算、存储、数据于一定格式的报告中
产生用于存储SQL命令的脚本,以便以后执行
SQL*PLUS专用命令可被分为如下类别:
环境:影响通常的SQL命令
格式化:格式化查询结果
文件处理:存储、调用、运行脚本文件
编辑:修改SQL缓存中的SQL命令
显示列的定义
登录到sql*plus
在命令中输入sqlplus/nolog
在sql>提示符后输入
例:connect username/password @database
编辑命令
SQL*PLUS的命令每次只能键入一行,且不能存于SQL缓存中
A[PPEND] text 将text加到当前行的后面
C[HANGE] /old/ new 将当前行的old改为new
C[HANGE] /text/ 从当前行中删除text
C[LEAR] BUFF[ER] 从缓存中删除所有的行
DEL 删除当前行
L[IST]: 列出SQL缓存中的所有行
L[IST] n: 列出一行(由n指出列出的行)
R[UN]: 显示并运行SQL缓存中的SQL语句
GET filename[.ext]:把文件的内容写到SQL缓存
@filename[.ext]:运行文件
ED[IT]:调用编辑器编辑当前缓存中的内容
ED[IT] filename.[ext]:调用编辑器编辑存的文件
SPOOL [filename[.ext]:将查询结果存于文件中
SPOOL OFF 结束结果内容输出
EXIT:退出SQL*PLUS
限定和排序数据
使用where限定返回的记录
select * from where 条件
where子句在from子句后面
注意:字符的大小写是敏感的
字符串和日期
在where子句的字符串和日期必须用单引号括起来,所有的字符是大小写敏感的
oracle存储日期是以内定的格式存放,它们代表世纪、年、月、日、分钟、秒,缺省显示的日期格式是DD-MON-YY,也可能是其他格式。为了避免日期字段查询条件不同格式下可能造成的错误,通常用TO_DATE函数来进行转换
例:select * from table where date='03-DEC-81'
select * from table where date=to_date('19811203','YYYYMMDD')
TO_DATE函数不再受日期格式的影响了。否则同样的查询,同样的表数据,不同的系统日期格式会导致结果不正确。
常用比较运算符
符号
|
含义
|
=
|
等于
|
<>
|
不等于
|
>
|
大于
|
<
|
小于
|
>=
|
大于等于
|
<=
|
小于等于
|
BETWEEN…AND…
|
在…之间(包含边界)
|
IN
|
在某个列表里
|
NOT IN
|
不在某个列表里
|
LIKE
|
包含
|
NOT LIKE
|
不包含
|
IS NULL
|
空值
|
IS NOT NULL
|
不为空值
|
使用between
例:select name,salare from table where salare between 1000 and 5000
between后面要先写低值,再写高值
使用in运算符
例:select id,name from table where salare in [1000,2000,3000]
使用like运算符
例:select name from table where name like 'zhang'
使用like运算符执行通配查询
查询条件可包含文字字符或数字
%可表示零个或多个字符
_可表示一个字符
用like和escape来查找包含特殊字符的数据
例:select id,name from table where name like '%\_%' escape '\'
ESCAPE后面单引号内只能有一个字符,表示前面的LIKE条件中这个字符后面的第一个字符当作普通字符处理
使用is null
例:select name,hobby from table where hobby is null
逻辑运算符
运算符
|
含义
|
AND
|
如果组合条件都是TRUE,返回TRUE
|
OR
|
如果组合条件之一是TRUE,返回TRUE
|
NOT
|
如果下面的条件是FALSE,返回TRUE
|
优先级次序:
1.所有的比较运算
2.NOT
3.AND
4.OR
括号将跨越所有优先级
使用and运算符
例:select id,name,job,salare from table where salare>=1000 and job='tese'
使用or运算符
例:select id,name,job,salare from table where salare>=1000 or job='test'
使用not运算符
例:select name,job from table where job not in ['test','analyst']
order by语句
例:select * from table where condition order by {column,expr} asc|desc
在缺省情况下,查询返回的结果是没被排序的。使用ORDER BY子可将记录排序。ORDER BY 子句放在最后。ASC表示升序排序,DESC表示降序排序,缺省为ASC
降序排列
例:select name,job from table order by job desc
单行函数
有两种不同的SQL函数
·单行函数
·多行函数
单行函数
这些函数仅作用于单行记录,并对每行记录返回一个值,有许多不同类型的单行函数,常用的类型有:
·字符函数
·数字函数
·日期函数
·转换函数
多行函数
这些函数作用于记录组,每组记录返回一个结果。
单行函数
单行函数操作数据项,它们接收一个或多个参数,并对查询出的每一条记录返回一个值。参数可以是:
·用户提供的常量
·一个列名
·一个表达式
单行函数的特性
·它们作用于查询的每一条记录
·每条记录返回一个结果
·它们可返回一个不同于它所参照的数据类型
·它们可嵌入到SELECT ,WHERE 和ORDER BY子句
字符函数被分为:
·大小写转换函数
·字符处理函数
LOWER(column | expression): 将字符转换为小写
UPPER(column | expression): 将字符转换不大写
INITCAP(column | expression): 将每一个单词的第一个字母大写其它小写
CONCAT(column | expression):返回第一个串接上第二个串,它的作用和'||'运算是相同的
SUBSTR(column | expression,m[,n]):返回从字母m开始,有n个字符长的字符串。
LENGTH(column | expression):返回字符串长度
INSTR(column 1 expression.m[n]):返回字符串中字符的位置
LPAD(column 1 cxpression,n,'string'):在字符串前填补字符,使其长度达到n。
RPAD(column 1 cxpression,n,‘string’):在字符串后填补字符,使其长度达到n。
例:select initcap(name) from table
select name,,substr(name,1,3) 'substr',rpad(name,1,"*") "rpad',length(name) "length" from table
数字函数
数字函数接收数字输入返回数字值
ROUND(column | expression, n):返回舍入到小数点右边n位的值
TRUNC(column | expression, n):返回截断到n位的值
MOD(m,n):返回m和n相除后的余数
例:select round(45.923,2),round(45.923,0),round(45.923,-1) from dual #45.92 46 50
select trunc(45.923,2),trunc(45.923,0),trunc(45.923,-1) from dual #45.92 45 40
select name,salare,comm,mod(salare,comm) from table where job='test'
日期函数
Oracle的日期函数
Oracle使用内部的数字化格式存储日期,它们代表世纪、年、月、日、小时、分钟和秒.
缺省显示的日期格式为DD-MON-YY,有效的日期在公元前4712年1月1日到公元后9999年12月31日
SYSDATE
SYSDATE是一个返回当前日期和时间的日期函数
DUAL
DUAL是一个SYS用户所拥有的表,所有的用户都可以访问。它包括一个列DUMMY和一条记录值为X。
例:select sysdate from sys.dual
日期运算
日期+数字=日期 加天数
日期-数字=日期 减天数
日期-日期=数字 两日期间的天数
日期+number/24=日期 加小时
注意:两个日期类型字段不能相加
例:select name,sysdate-hiredate from table
常用的日期函数
函数
|
含义
|
MONTHS_BETWEEN
|
返回两个日期间相差多少月,数字类型
|
ADD_MONTHS
|
返回给日期加上多少月后的日期
|
NEXT_DAY
|
返回日期的下一个星期几的日期
|
LAST_DAY
|
返回月份的最后一天
|
ROUND
|
对日期进行四舍五入
|
TRUNC
|
截断日期
|
例:select sysdate,add_months(sysdate,12),last_day(sysdate),next_day(sysdate,'friday') from dual
转换函数

转换函数用于数据类型之间的转换。SQL尽可能地自动进行转换,它会隐含地调用转换函数。但是你无法对隐含调用中使用的格式指定符进行控制,并且这会使得你的代码很难理解。因此使用显式转换函数而不依赖于隐式转换是一个很好的程序设计风格
Oracle提供了3个转换函数
•TO_CHAR(number | date,[ 'fmt']) :将数字或日期按格式转换成字符
•TO_NUMBER(char) :将字符串转换成数字,此字符串必须是数字
•TO_DATE(CHAR,[ 'fmt']) :将字符串按指定的格式转换成日期
例:select sysdate,to_char(sysdate,'YYYY/MM/DD HH24:MI:SS' detaildate from dual
select name,hiredate from table where hiredate>= to_date('19820101','YYYYMMDD')
select name,hiredate from table where hiredate>='19820101'
nvl函数
nvl(comm,0):如果comm为空,则转换为0
nvl(hiredate,‘01-jan-21’):如果hiredate为空,转换为‘01-jan-21’
nvl(job,'no job'):如果job为空,则转换为‘no job’
将空值转换为实际的值
数据格式可以是日期,字符,数字
数据类型必须匹配
例:select name,comm,salare,salare*12+nvl(comm,0) from table
从多个表中选择数据
定义连接
当从两个以上的表中获取数据时,就要使用连接条件。一个表中的记录可以根据两个表的相同列和另一个表的记录相连接。两表中的相同列一般是主键和外键列。
为了能显示两个或多个表中的数据,在WHERE子句中需要设简单的连接条件。语法如下:
table.column 指定取数据的表和它的列
table.column1 = table2.column2 将表连接起来的条件
当写一个有连接的SELECT命令时,为了避免同样的不同表具有同样的列名,应该在列前加表的名字或者表的别名。
当在表中有相同的列名时,并且这个列作为显示内容或者查询条件,必须在列名前加表名或表的别名作为前缀。
如果要将n个表连起来,你必须指定n-1个连接条件。因此连接4个表需要有3个连接条件。如果你的表有组合主键,此规则可能不适用,此时多一条记录需要多个列唯一标识
笛卡尔结果
笛卡尔结果形成于:
-连接条件被省略
-连接条件无效
-第一个表的所有记录连接到第二个表的所有记录
一个笛卡尔结果趋于产生一个巨大的记录数 ,通常没有意义。为了避免笛卡尔结果我们要在WHERE子句中使用有效连接
连接类型
有两种主要的连接条件
等值连接
非等值连接
其它的连接方式包括
多连接
自连接
定置运算符
什么是等值连接
就是两个表连接的WHERE条件是一个表的列等于另外一个表的列。通常情况下,这种连接是主键和外键的连接
select id,name,emp.deptid,loc from table,dept where table.deptid=dept.deptid and initcap(name)='zhang'
select id,name,t.deptid,loc from table t,dept d where t.deptid=d.deptid and initcap(name)='zhang'
表的别名
使用表名限定列名可能会很浪费时间,尤其是当表名特别长,这时你可以使用表的别名。使用表的别名会减少程序代码,因此占用较少的内存。注意,表的别名是在FROM子句中指定的。
表别名规则:
表的别名最长为30个字符,但通常以短字符为佳
表的别名最好有一定的含义
表的别名只在当前的SELECT语句有效
如果在FROM子句定义了表的别名,在SELECT子句中必须用它来替代表名。
非等值连接
select t.salare,t.name,s.grade from table t,salgrade s where t.salare between s.losal and s.hisal
外连接
select table.column,table.column from table1,table2 where table1.column(+)=table2.column
select table.column,table.column from table1,table2 where table1.column=table2.column(+)
使用外部连接,返回连接两边有一边为NULL的记录
外连接运算符是加号(+)
外连接运算符(+)可以加在左边, 也可以加在右边,但不能两边同时加外连接
有(+)的一边表示这边的值要么等于另外一边,要么为NULL
从9i开始,SQL支持ANSI SQL,也就是支持LEFT OUTER JOIN、RIGHT OUTER JOIN和FULL OUTER JOIN
SELECT ename,e.deptno "E.DEPTNO",d.deptno "D.DEPTNO",d.dname FROM EMP E,DEPT D WHERE E.DEPTNO(+)=D.DEPTNO
这个例子(+)在e.deptno这边,意味着e.deptno可以是NULL
SELECT ename,e.deptno "E.DEPTNO",d.deptno "D.DEPTNO",d.dname FROM EMP E,DEPT D WHERE E.DEPTNO=D.DEPTNO(+);
这个例子(+)在d.deptno这边,意味着d.deptno可以是NULL
SELECT E.ENAME,E.DEPTNO "E.DEPTNO",D.DEPTNO "D.DEPTNO",D.DNAME FROM EMP E FULL OUTER JOIN DEPT D ON (E.DEPTNO=D.DEPTNO)
可以用ANSI SQL语法来写外连接,这样也提供了一个以前的(+)不能实现的功能:全外连接
表的自连接
有的时候,需要对表进行自连接。例如上图所示,EMP表中的MGR列的代表员工的经理的员工编号,所以要想显示出每个员工的经理就要对EMP进行自连接,用MGR=EMPNO。实际上,自连接只是等连接(等外连接)的一个特例,同一张表用不同的别名,区别成了不同的表。
SELECT E.ENAME ||' works for '|| NVL(M.ENAME,'himself') RELATIONS FROM EMP E,EMP M WHERE E.MGR=M.EMPNO(+)
这个例子相当一个等外连接。如果员工有经理,则显示出员工为谁工作(打工者),否则显示员工为自己干活(老板)
使用分组函数
什么是分组函数
和单行函数不同,分组函数作用于一组记录,每一组返回一个结果。这些组可能是整个表,也可能是由GROUP BY子句将表分成的多个组
主要的分组函数
COUNT({*/[DISTINCE/ALL]expr}) 返回记录数,这里expr赋非空值,*表示所有被选择的记录,包括重复记录和空值。
MAX([DISTNCT/ALL]expr):表达式的最大值,忽略空值
MIN([DISTNCT/ALL]expr):表达式的最小值,忽略空值
AVG([DISTNCT/ALL]expr):平均值,忽略空值
STDDEV[DISTINCT/ALL]X):返回标准差,忽略空值
SUM([DIXNTICT/ALL]n):求和,忽略空值
VARIANCE([DISTINCT/ALL]X):返回统计方差
这些分组函数中,COUNT是不计算NULL值的,其它函数忽略NULL值
select sum(salare),max(salare),min(salare),avg(salare) from table
selext count(*) from table
select count(id) from table
select count(mgr) from table
产生数据组:group by 子句
使用GROUP BY 子句将一个表分成许多小组,并对每一个小组返回一个计算值。
Group_by_expression:指定按什么列分组
规则:
在SELECT子句中,如果使用分组函数,不能对GROUP BY子句中指定的列使用分组函数。
使用WHERE子句,可预先排除某些记录
在GROUP BY 子句中必须有表中的列
在GROUP BY子句中不能使用列的别名
缺省情况下在GROUP BY子句中的列以升序排,你可以使用order by子句改变它。
select deptid,sum(salare),max(salare),min(salare),avg(salare) from table group by deptid
注意:不是分组的列不能出现在select后面,否则会报错。阻焊输液不能出现在where子句中。
select deptid,job,sum(salare),avg(salare) from table group by deptid,job
先以部门分类,在以职位分类
使用having子句限定分组函数结果值
select deptid,job,sum(salare),avg(salare)from table group by deptid,job having avg(salare)>2000
分组函数不能写在where子句中,如果对分组函数结果值进行限定,可以写having子句
子查询
子查询语法
select * from table where job=(select job from table where name='zhangsan')
子查询在主查询前执行一次
主查询使用子查询的结果
子查询类别
单行子查询:内部select命令返回一条记录
多行子查询:内部select命令返回多条记录
多列子查询:内部select命令返回多个数据行
子查询使用规则
子查询要用括号括起来
将子查询放在比较运算符的右边
子查询中不要加 ORDER BY子句
对单行子查询使用单行运算符(如=,>,<),也可以使用多行运算符
对多行子查询使用多行运算符,IN,ANY,ALL属于多行运算符
例:select name,deptid,salare from table where salare in(select max(salare) from table group by deptid)
select name,deptid,job,salare from table salare < any(select salare from table where job='test') and job <>'test'
操作数据
insert语句
insert into table [(column[,cloumn])] values (value)
通过INSERT语句在表中增加一条新记录。如果省略表后面的列,那么要在VALUES后面按照表的顺序指定所有的列的值
从其他表拷贝数据
insert into table(id,name,salare) select id,name,salare from table where job='manager'
update语句
用UPDATE语句可以一次修改一条或者多条记录。如果没有WHERE条件,则所有的SET后面的列的值都会被更新
UPDATE EMP SET SAL=SAL*1.2 WHERE DEPTNO=30
delete语句
用DELETE语句从表中删除数据。如果不加WHERE条件,那么所有的记录都将被删除
DELETE FROM DEPT WHERE DNAME='DEVELOPMENT'
提交所作修改
用INSERT、UPDATE和DELETE语句对数据进行改动后,数据并没有真正的保存。这些改动的数据别的会话中看不到。为了真的保存,需要执行COMMIT命令
一些隐式的COMMIT
如果在SQLPLUS中执行了DML语句,然后虽然没有执行COMMIT,但是如果存在如下情形之一,Oralce会执行一个隐式的COMMIT,一定要注意:
1.正常退出SQLPLUS
2.执行了一条DDL语句,例如创建了一个表
取消所作的修改
可以用ROLLBACK命令取消所做的修改
隐式的rollback
如果修改数据后,没有COMMIT,也没有提交,那么下列情况下Oracle会取消所做的修改:
1.系统崩溃
2.程序异常退出
DML语句应该注意的问题
一定要加合适的WHERE条件,避免错误修改数据
执行DML后因该尽快的显式执行COMMIT或者ROLLBACK,因为被改动的数据别的用户是不能修改的,长时间不结束事务会增加死锁的可能性
创建并管理表
常用的数据库对象
表(Table):存储数据
视图(View):一个或几个表数据的子集
序列(sequence):生成主要健值
索引(index):加快某些查询速度
同义词(synonym):给出对象的另一个可选用名字
命名规则
数据库表和列的命名是根据Oracle数据库对象的标准命名规则进行的。
·表名和列必须由字母开头,最多有30个字符长。
名字只能包含这些字符,大小字母A-Z、小写字母a-z、数字0-9、下划线(_)、$、和#。
在同一个数据库用户中表名不能重复。
名字不能是Oracle的保留字。
创建表
create table table(id number(4) primary key,name varchar2(30),phone varchar2(30))
查询自己拥有的对象
select object_name,object_type from user_objects
通过查询USER_OBJECTS数据字典,可以查看到本用户拥有哪些数据对象。提示:如果想看其它用户用有的数据对象,可以查看ALL_OBJECTS
查看自己拥有的表
select table_name from user_bables
常用数据类型
类型
|
含义
|
VARCHAR2(size)
|
不定长字符类型,最多4000字节
|
CHAR(size)
|
定长字符类型,最多2000字节
|
NUMBER
|
数字类型
|
DATE
|
日期类型
|
BLOB
|
最大可存4G的二进制数据
|
CLOB
|
最大可存4G的字符数据
|
使用子查询创建表
CREATE TABLE EMP2 AS SELECT * FROM EMP
SELECT COUNT(*) FROM EMP2
用CREATE TABLE…AS SELECT…可以将一个表的结构复制给另外一个表,同时包含满足条件的数据
用ALTER TABLE增加列
ALTER TABLE NOTEBOOK ADD ADDRESS VARCHAR2(80)
用ALTER TABLE修改列
ALTER TABLE notebook MODIFY address VARCHAR2(120)
如果发现表的某个列的长度太小,则可以用ALTER TABLE…MODIFY…来修改。本例子把ADDRESS改成VARCHAR2(120)
删除表 drop table
drop table notebook
表中所有的数据将被删除
事务被提交
所有索引被删除
不能回退
给表重命名
rename table2 to table10
如果表和其他表之间存在约束关系则不能重命名
清空表的内容TRUNCATE TABLE
truncate table table10
TRUNCATE TABLE命令将表的全部数据都清空,释放表的存储空间,不需要WHERE语句,而且不可以回退,因此运用此命令一定要慎重!
索引和其它对象简介
什么是索引
索引是一种模式对象。是为了加快某些查询的访问速度。它的目的是使用索引路径快速定位数据,减少磁场盘I/O。
索引在Oracle中是自动引用和维护的。
当删除一个表时,对应的索引也将被删除。
关于索引要考虑到的
一个设计优良的系统应该充分考虑索引的设计。
索引不是越多越好,不合适的索引同样会导致系统性能下降。
是否需要创建、修改一个索引不是使用者需要考虑的问题,是系统架构师应该考虑的问题。
查看某个表具有的索引
SELECT TABLE_NAME,COLUMN_NAME,INDEX_NAME FROM USER_IND_COLUMNS WHERE TABLE_NAME='CASE_M_AJZLZ';
查看系统中状态无效的索引
SELECT index_name,status FROM user_indexes WHERE status<>'VALID';
其它Oracle对象
约束(constraints):用来防止存入不合法的数据,可以从user_constraints查看
序列(sequences):通常用来一个序列编号,可以从user_sequences中查看
同义词(synonyms):给其他Oracle对象的一个别名,可以从user_synonyms中查看
函数和过程(procedures):执行某些复杂的、无法用简单语句实现的特殊处理的代码块。可以从user_procedures中查看。
包(packages):可以把函数和过程集中在一个包里进行管理。在ALL_OBJECTS字典中的OBJECT_TYPE等于‘PACKAGE’的就是包
查看状态无效的对象
SELECT OBJECT_NAME,OBJECT_TYPE,STATUS FROM USER_OBJECTS WHERE STATUS<>'VALID'
重新编译状态无效的对象
正常情况下,不应该有无效对象。无效对象在第一次被使用的时候可能自动重新编译,从而重新变为有效的对象。但是也可能无法重新编译过去,从而导致系统不正常。我们定期检查无效对象,如果发现无效对象,则应该重新编译一下。注意不同对象的编译方法。编译完成之后,再查其状态则应该为VALID,如果仍然是INVALID,则应该反馈给开发人员或者DBA
SQL> ALTER INDEX TJL_FK2 REBUILD;
Index altered.
SQL> ALTER INDEX TJL_FK2 REBUILD ONLINE;
Index altered.
SQL> ALTER PROCEDURE SP_AJ_XQSS COMPILE;
Procedure altered.
SQL> ALTER FUNCTION FISFETCHED COMPILE;
Function altered
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)