这是本人复习兼学习两周oracle数据库后整理的一些知识,适合查询oracle的一些语法,也可以当作一个oracle数据库的知识架构梳理。
鉴于数据库语法繁琐,知识点繁多,还有很多知识点没有纳入。
数据库系统是由数据库、数据库管理系统、应用程序和数据库管理员组成的存储、管理、处理和维护数据的系统。
数据库,顾名思义,是存放数据的仓库,这个仓库是在计算机存储设备上,并且数据是按一定的格式存放的。
严格的讲,数据库时长期存储在计算机内、有组织的、可共享的大量数据的集合。
数据库中的数据按一定的数据模型组织、描述和储存,具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种用户共享。
有了数据库后,下一个问题就是如何科学地组织和存储数据,高效地获取和维护数据。完成这个任务的是一个系统软件——数据库管理系统。
数据库管理系统是位于用户与计算机操作系统之间的一层数据库管理软件,它的功能包括如下几个方面:
1970年,E. F. Codd博士发表了题为“A Relational Model of Data for Large Shared Data banks(大型共享数据库的关系模型)”的论文,首次提出了数据库的关系模型的概念,奠定了关系模型的理论基础。
1981年IBM公司又宣布了具有关系型特征的数据库产品SQL/DS问世。
由于关系模型简单明了、具有坚实的数学理论基础,所以一经推出就受到了学术界和产业界的高度重视和广泛响应,并很快成为数据库市场的主流。
关系数据库就是支持关系模型的数据库系统。
关系模型由关系数据结构、关系操作集合和关系完整性约束三部分组成。
关系数据结构
关系数据结构非常简单,只包含单一的数据结构——关系。在用户看来,关系就是一张二维的表(就像excel中的一张表),举例说明:
个人理解:
1.在设计中,一张表表示一个现实世界的一个实体,属性是相对实体而言,字段是相对表而言,但从一张表来看,其实两者说的是一个东西。
2.元组好像就是一个记录,表示表的一行,就是一个记录,而不是图中标识的那样是一个单元格。
关系操作集合
关系操作包括两大部分:
查询
插入、修改、删除
关系完整性约束
完整性约束就是对关系的某种约束条件,这些约束条件实际上是现实世界的要求,因为关系就是对现实世界的实体的一种简单化的表述方式,因此也必须符合现实世界的要求。
关系模型中有三类完整性约束:实体完整性、参照完整性和用户定义的完整性。
1.实体完整性是指关系的主关键字不能重复也不能取“空值"。
eg:学生的学号不能重复也不能是空值
2.参照完整性是定义建立关系之间联系的主关键字与外部关键字引用的约束条件。
eg:
选课表的中学号和课程号必须是学生表和课程表中存在的学号和课表号。
3.用户定义完整性则是根据应用环境的要求和实际的需要,对某一具体应用所涉及的数据提出约束性条件。
eg:学生姓名不能取空值、学生成绩取值范围在0~100之间。
结构化查询语言(Structured Query
Language,SQL)是关系数据库的标准语言,也是一个通用的、功能极强的的关系数据库语言。其功能不仅是查询,还包括数据库模式创建、数据库数据的插入与修改、数据库安全性完整性定义与控制等一系列功能。
SQL从功能上可以分为3部分:
数据定义、数据操纵和数据控制
SQL从操作类型上可以分为6部分:
1、数据查询语言(DQL):用以从表中获得数据。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。
2、数据操作语言(DML):其语句包括动词INSERT、UPDATE和DELETE。
3、事务控制语言(TCL):它的语句能确保被DML语句影响的表的所有行及时得以更新。包括COMMIT命令、SAVEPOINT命令、ROLLBACK命令。
4、数据控制语言(DCL):它的语句通过GRANT或REVOKE实现权限控制,确定单个用户和用户组对数据库对象的访问。
5、数据定义语言(DDL):其语句包括动词CREATE,ALTER和DROP。在数据库中创建新表或修改、删除表;为表加入索引等。
6、指针控制语言(CCL):它的语句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用于对一个或多个表单独行的操作。
SQL是关系型数据库的一套标准或规范,但实现SQL标准可以有不同的方式,目前比较主流的实现有MySql、SQL Sever和Oracle。
Oracle Database,又名Oracle
RDBMS,简称Oracle。是Oracle公司的一款关系数据库管理系统。它在数据库领域一直处于领先地位,被企业广泛使用;它可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境,是一种高效率、可靠性好的、适应高吞吐量的数据库系统方案。
create的对象有:表、索引、同义词
创建表的sql语句:
create table table_name(
coloumn_name1 datatype [null/not null] [primary key],
coloumn_name2 datatype [null/not null] [default value],
......
--在建表时添加约束,不过一般建议在alter语句中添加约束
[constarint] <约束名> 约束类型 (字段) ,
......
);
--eg
create table dept(
deptno number(2) not null primary key, --非空约束、主键约束
dname varchar2(14) null unique, --唯一性约束
loc varchar2(13) null
);
语句说明:
数据类型 | 参数 | 描述 |
---|---|---|
char(n) | 1 定长字符串,n字节长,如果不指定长度,缺省为1个字节长(一个汉字为2字节) |
|
varchar2(n) | 1可变长的字符串,具体定义时指明最大长度n,这种数据类型可以放数字、字母以及ASCII码字符集中的所有符号。VARCHAR2是最常用的数据类型。 |
|
number(p,s) | 1
| p是有效数字的位数,s是小数点以后的位数。NUMBER(5,2) 表示整数部分最大3位,小数部分为2位;NUMBER(5,-2) 表示数的整数部分最大7位,其中整数的倒数2位为0,前面取整。p,s都是可选的。 |
date | 无 | 有效日期范围从公元前4712年1月1日到公元后4712年12月31日 |
raw(n) | 1长度为n字节的原始二进制数据,必须为RAW指定一个n; |
|
long | 无 | 可变长度的字符数据,其长度可达2G个字节; |
long raw | 无 | 可变长度的原始二进制数据,其最长可达2G字节; |
clob | 无 | 一个字符大型对象,可容纳单字节的字符;不支持宽度不等的字符集;最大为4G字节 |
nclob | 无 | 与clob相同;储存国家字符集 |
blob | 无 | 一个二进制大型对象;最大4G字节 |
bfile | 无 | 包含一个大型二进制文件的定位器,其储存在数据库的外面;使得可以以字符流I/O访问存在数据库服务器上的外部LOB;最大大小为4G字节. |
更详细的参考见一位博客上的总结
ORACLE基本数据类型总结
注意:虽然create可以创建索引和同义词,但一般来说,索引都是在表填充数据后利用alter语句添加
alter的对象有:表名、字段、约束
修改表名
alter table table_name_old
rename to table_name_new;
修改字段
--修改现有列的类型
alter table table_name
modify column_name1 datatype [null/not null] [default '输入默认值']; --只能是modify,mysql才有change
--修改列名称
alter table table_name
rename column 旧列名 to 新列名;
--增加列
alter table table_name
add column_name1 datatype [null/not null] [default '输入默认值'];
--删除列
drop column_name1;
修改表中字段的约束
sql中有5中约束,分别是主键、外键、唯一性约束、检查约束和非空约束。
--添加约束
alter table table_name
add constraint 约束名 约束类型 被约束的字段名 [后缀根据约束填写];
--eg:
--1.添加主键
alter table emp
add constraint pk_deptno primary key (deptno);
--2.添加外键
alter table emp
add constraint fk_deptno Foreign key (deptno) references dept(deptno);
--3.添加唯一性约束
alter table emp
add constraint uq_deptno unique (deptno);
--4.添加检查约束
alter table emp
add constraint chk_deptno check (deptno = '检查值');
--5.添加非空约束
alter table emp
modify deptno number(2) not null;
--注:添加非空约束语法与前面四个不同,其实就是修改字段类型
---------------------------------------------------------------
--删除约束
alter table table_name
drop constraint 约束名;
--eg:
alter table emp
drop constraint fk_deptno;
drop的对象有:表、索引
注:这里所讲的drop是指不用在alter语句里面的drop。用在alter语句里面的drop还可以有其它对象
--删除表
drop table table_name;
--删除索引
drop index index_name;
SQL里基本的DML操作命令是:
--向指定列插入单行数据
insert into table_name
(column1,
column2,
......)
values
(value1,
value2,
......);
/*
注:1.若被插入的列是表中全部列,可省略列名。
2.Oracle里这种语句只能插入单行数据,mysql可以插入多行。想插入多行语法较复杂。
*/
----------------------------------------------------------------------------
--与select连用
insert into table_name1
(column1,
column2,
......)
select (column1,
column2,
......)
from table_name2
[条件];
/*
注:1.当select表中所有时,可使用select * from table_name
2.可以用null代替column
*/
update table_name
set column1 = value1,
column2 = value2,
......
[where condition];
delete from table_name
[where condition];
注:若不用where条件,delete会删除表中所有数据。一般来说,都要使用where控制条件,数据损失若无法恢复可能会造成严重后果。
查询:使用select语句对数据库中表的数据进行提取
select * or
column1 [as 别名],
column2 [运算符 可运算的表达式(值、列名等)], --eg: salary * 10
转换函数(column3[,格式]), --to_char(salary,'$9999,999.99')
聚组函数(* | column4), --count(*)
数值函数(value or column5), --abs()
字符函数(value or column6), --upper()
日期函数[(sysdate,格式)], --trunc(sysdate,'month') 本月初的日期
分析函数
其他函数 --nvl(exp1,0) 若exp1为null,用返回0
(select语句) --这里select语句选出来的只能是单个字段?
常量、形参、实参
from table_name1,
table_name2 别名,
(select语句) 别名 --这里可以是是多个字段,即表的形式
left | right [outer] join table_name --外连接:选择某一张表的某个属性的全部值
on 条件
inner join table_name --内连接:选择两张表某个属性的共有值
on 条件
where column1 = column2
[操作符:比较操作符 (= != < > <= >= )
逻辑操作符 (is null between in like exists all/some/any)
连接操作符 (and or)]
求反操作符 (not 逻辑操作符)
算术操作符 (+ - * /)]
group by 列名 --
having 条件 --avg(salary) > 2000
order by column1 asc --asc一般是默认,可不填
column2 desc;
/*
注:oracle没有limit语句,但可以用rownum字段实现取部分结果的功能。
eg:使查询结果最多返回前10行
select *
from CLEAR
where rownum <= 10;
*/
下面举几个select语句的例子(可能稍微复杂一点)
表样子如下:
注:这里就不列出表字段的类型了,可以从数据中推测,对于查询来说也无伤大雅
--eg:
--1. 查询销售量最高的产品的前两名(pname,volume)
select P.pname,
Sum(Cast(D.volume As signed)) as volume
From Production P,
deal D
Where P.pid = D.pid
Group By D.pid,
P.pname
Order By volume DESC
Limit 2; --oracle中没有limit语法
--2.查询2017年生产的产品的总销量(pname,volume)
SELECT P.pname,
SUM(D.volume) as volume
from production P,
deal D
where P.pid = D.pid
and YEAR(P.pdate) = '2017'
GROUP BY D.pid;
--3.查询产品编号为2且销售量超过100的销售人员的姓名及所在的公司(sname,aname)
select Sales.sname,
Agent.aname
from Sales,
Agent
where Sales.aid=Agent.aid
and Sales.sid in(select sid
from Deal
where pid='2'
group by sid
having sum(Cast(volume As signed))>100);
--4.查询总销量最差的产品(pname,volume)
select *
from (select p.pname,
sum(volume) sumvolume
from production p,
deal d
where p.pid = d.pid
group by p.pname
order by sumvolume asc)
where rownum = 1;
--注:rownum表示记录所在的行数,oracle没有limit函数,只能用rownum来实现limit的功能,但也有区别。
--5. 查询每种产品销售量最高的销售人员(pname,sname,volume)
select p.pname,
s.sname,
b.volume
from production p,
sales s,
(select d.sid,a.pid,a.volume
from deal d,
(select pid,
max(volume) volume
from deal
group by pid) a
where d.volume = a.volume) b
where p.pid = b.pid and s.sid = b.sid
order by p.pname;
建好数据库后,就要开发应用系统了,但sql只是访问、操作数据库的语言,缺少流程控制能力,难以实现业务流程中的逻辑控制是非过程化的语言。只有程序设计语言才能用于应用软件的开发,SQL编程技术可以有效克服sql语言实现复杂应用方面的不足,SQL编程技术主要有:
- 嵌入式SQL
- 过程化SQL(PL/SQL)
- 开放数据库互联(ODBC)
- Java数据库互联(JDBC)
嵌入式SQL是指将sql语言嵌入到程序设计语言中,比如C、C++、Java等,利用这些程序设计语言的流程控制能力。
过程化SQL(PL/SQL)是Oracle开发的针对Oracle数据库的sql语言的扩展,是一种高级数据库程序设计语言,自带过程化语言功能。
开放数据库互联(ODBC)提出和产生的原因是目前广泛使用的数据库管理系统有多种,比如mysql、sql sever、oracle等,为了使得不同数据库系统之间可交互和移植,使数据库系统“开放”,能够实现“数据库互连”,微软公司开发了ODBC这样一个标准接口。ODBC应用系统体系结构如下:
Java数据库互联(JDBC)使Java的开发者sun公司制定的Java数据库连接技术的简称,是Java实现数据库访问的应用程序编程接口。
知识点:基本结构、变量类型、游标、过程、函数、触发器、包、自定义对象等。
过程与函数(另外还有包与触发器)是命名的PL/SQL块(也是用户的方案对象),被编译后存储在数据库中,以备执行。因此,其它PL/SQL块可以按名称来使用他们。所以,可以将商业逻辑、企业规则写成函数或过程保存到数据库中,以便共享。
过程和函数统称为PL/SQL子程序,均存储在数据库中,并通过输入、输出参数与其调用者交换信息。过程和函数的唯一区别是函数总向调用者返回数据,而过程则不返回数据。在本节中,主要介绍:
- 创建存储过程和函数
- 正确使用系统级的异常处理和用户定义的异常处理
- 建立和管理存储过程和函数
1. 创建过程与函数
--1.创建过程
CREATE [OR REPLACE] PROCEDURE procedure_name
([arg1 [ IN | OUT | IN OUT ]] type1 [DEFAULT value1],
[arg2 [ IN | OUT | IN OUT ]] type2 [DEFAULT value1]],
......
[ AUTHID DEFINER | CURRENT_USER ] --程序调用授权
{ IS | AS }
<局部变量>
BEGIN
<执行部分>:[流程控制、sql语句、系统交互等]
EXCEPTION
<异常错误处理>
END procedure_name;
--------------------------------------------
--2.创建函数
CREATE [OR REPLACE] FUNCTION function_name
(arg1 [ { IN | OUT | IN OUT }] type1 [DEFAULT value1],
[arg2 [ { IN | OUT | IN OUT }] type2 [DEFAULT value1]],
......
[ AUTHID DEFINER | CURRENT_USER ]
RETURN return_type --返回类型
IS | AS
<局部变量>
BEGIN
执行部分
RETURN expression --返回表达式
EXCEPTION
<异常处理部分>
END function_name;
说明:
1.函数声明时所定义的参数称为形式参数,应用程序调用时为函数传递的参数称为实际参数,形式参数只能定义数据类型,不能规定数据大小。
2.实参向行参传递有一定规则。
3.in为默认类型,表示输入,out 表示只输出,in out 表示即输入又输出;
例子:
--1.使用过程删除指定员工记录
CREATE OR REPLACE PROCEDURE DelEmp
(v_empno IN employees.employee_id%TYPE)
AS
No_result EXCEPTION;
BEGIN
DELETE FROM employees
WHERE employee_id = v_empno;
IF SQL%NOTFOUND THEN
RAISE no_result;
END IF;
DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'的员工已被删除!');
EXCEPTION
WHEN no_result THEN
DBMS_OUTPUT.PUT_LINE('温馨提示:你需要的数据不存在!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END DelEmp;
-------------------------------------------------
--2.使用过程向departments表中插入数据
CREATE OR REPLACE PROCEDURE insert_dept
(v_dept_id IN departments.department_id%TYPE,
v_dept_name IN departments.department_name%TYPE,
v_mgr_id IN departments.manager_id%TYPE,
v_loc_id IN departments.location_id%TYPE)
IS
ept_null_error EXCEPTION;
PRAGMA EXCEPTION_INIT(ept_null_error, -1400);
ept_no_loc_id EXCEPTION;
PRAGMA EXCEPTION_INIT(ept_no_loc_id, -2291);
BEGIN
INSERT INTO departments
(department_id,
department_name,
manager_id,
location_id)
VALUES
(v_dept_id,
v_dept_name,
v_mgr_id,
v_loc_id);
DBMS_OUTPUT.PUT_LINE('插入部门'||v_dept_id||'成功');
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20000, '部门编码不能重复');
WHEN ept_null_error THEN
RAISE_APPLICATION_ERROR(-20001, '部门编码、部门名称不能为空');
WHEN ept_no_loc_id THEN
RAISE_APPLICATION_ERROR(-20002, '没有该地点');
END insert_dept;
2. 调用过程与函数
存储过程建立完成后,只要通过授权,用户就可以在SQLPLUS 、ORACLE开发工具或第三方开发工具中来调用运行。对于参数的传递也有三种:按位置传递、按名称传递和组合传递,传递方法与函数的一样。ORACLE 使用EXECUTE 语句来实现对存储过程的调用。
调用过程与函数:
declare
<局部变量>
begin
执行部分
end;
例子:
--1.查询指定员工记录
CREATE OR REPLACE PROCEDURE QueryEmp
(v_empno IN employees.employee_id%TYPE,
v_ename OUT employees.first_name%TYPE,
v_sal OUT employees.salary%TYPE)
AS
BEGIN
SELECT last_name || last_name,
salary
INTO v_ename,
v_sal
FROM employees
WHERE employee_id = v_empno;
DBMS_OUTPUT.PUT_LINE('温馨提示:编码为'||v_empno||'的员工已经查到!');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('温馨提示:你需要的数据不存在!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END QueryEmp;
--调用
DECLARE
v1 employees.first_name%TYPE;
v2 employees.salary%TYPE;
BEGIN
QueryEmp(100, v1, v2);
DBMS_OUTPUT.PUT_LINE('姓名:'||v1);
DBMS_OUTPUT.PUT_LINE('工资:'||v2);
QueryEmp(103, v1, v2);
DBMS_OUTPUT.PUT_LINE('姓名:'||v1);
DBMS_OUTPUT.PUT_LINE('工资:'||v2);
QueryEmp(104, v1, v2);
DBMS_OUTPUT.PUT_LINE('姓名:'||v1);
DBMS_OUTPUT.PUT_LINE('工资:'||v2);
END;
说明:
1.建立过程与函数时is/as下面的局部变量定义和调用时declare下面的局部变量定义的区别:
没有直接关系,前者主要与in参数交互,后者主要与out参数交互。便于实现流程控制与输出展示功能。
3. 删除过程和函数
--1.删除过程
DROP PROCEDURE [user.]Procudure_name;
--2.删除函数
DROP FUNCTION [user.]Function_name;
4. 过程与函数的比较
使用过程与函数具有如下优点:
1、共同使用的代码可以只需要被编写和测试一次,而被需要该代码的任何应用程序(如:.NET、C++、JAVA、VB程序,也可以是DLL库)调用。
2、这种集中编写、集中维护更新、大家共享(或重用)的方法,简化了应用程序的开发和维护,提高了效率与性能。
3、这种模块化的方法,使得可以将一个复杂的问题、大的程序逐步简化成几个简单的、小的程序部分,进行分别编写、调试。因此使程序的结构清晰、简单,也容易实现。
4、可以在各个开发者之间提供处理数据、控制流程、提示信息等方面的一致性。
5、节省内存空间。它们以一种压缩的形式被存储在外存中,当被调用时才被放入内存进行处理。并且,如果多个用户要执行相同的过程或函数时,就只需要在内存中加载一个该过程或函数。
6、提高数据的安全性与完整性。通过把一些对数据的操作放到过程或函数中,就可以通过是否授予用户有执行该过程或的权限,来限制某些用户对数据进行这些操作。
过程与函数的相同功能有:
1、 都使用IN模式的参数传入数据、OUT模式的参数返回数据。
2、 输入参数都可以接受默认值,都可以传值或传引导。
3、 调用时的实际参数都可以使用位置表示法、名称表示法或组合方法。
4、 都有声明部分、执行部分和异常处理部分。
5、 其管理过程都有创建、编译、授权、删除、显示依赖关系等。
使用过程与函数的原则:
1、如果需要返回多个值和不返回值,就使用过程;如果只需要返回一个值,就使用函数。
2、过程一般用于执行一个指定的动作,函数一般用于计算和返回一个值。
3、可以SQL语句内部(如表达式)调用函数来完成复杂的计算问题,但不能调用过程。所以这是函数的特色。
- 概念
SQL是面向集合的,一条SQL语句处理多条记录;程序设计语言是面向记录的,一组变量一次只能存放一条记录。为了协调两种处理方式的不同,SQL引入了游标这个概念。
游标是系统为用户开设的数据缓冲区,用于存放SQL语句的执行结果,用户可以通过游标逐一获取记录并赋给程序设计语言的变量。
游标有显示游标和隐示游标
- 显式游标语法
ORACLE PL/SQL编程之四:把游标说透
这篇文章总结得很好
正如函数是储存过程的一种,触发器也是一种特殊的过程。主要的区别是函数和过程的需要用户显示调用才能执行,触发器的调用者是数据库里的一个事件,这个事件包括DML语句、DDL语句、数据库系统事件、用户登录事件等。
触发器的作用是完成由数据库的完整性约束难以完成的复杂业务规则的约束,或用来监视对数据库的各种操作,实现审计的功能。
- 触发器的语法和例子
ORACLE PL/SQL编程之八: 把触发器说透
这篇文章总结得很好
- 概念
程序包(PACKAGE,简称包)是一组相关过程、函数、变量、常量和游标等PL/SQL程序设计元素的组合,作为一个完整的单元存储在数据库中,用名称来标识包。包是对这些PL/SQL 程序设计元素的封装,包类似于c#和JAVA语言中的类,其中变量相当于类中的成员变量,过程和函数相当于类方法,具有面向对象语言的特性。
与高级语言中的类相同,包中的程序元素也分为公用元素和私用元素两种,这两种元素的区别是他们允许访问的程序范围不同,即它们的作用域不同。公用元素不仅可以被包中的函数、过程所调用,也可以被包外的PL/SQL程序访问,而私有元素只能被包内的函数和过程序所访问。
- 组成
程序包的定义分为程序包说明定义和程序包主体定义两部分组成。
程序包说明用于声明包的公用组件,如变量、常量、自定义数据类型、异常、过程、函数、游标等。包说明中定义的公有组件不仅可以在包内使用,还可以由包外其他过程、函数。但需要说明与注意的是,我们为了实现信息的隐藏,建议不要将所有组件都放在包说明处声明,只应把公共组件放在包声明部分。包的名称是唯一的,但对于两个包中的公有组件的名称可以相同,这种用“包名.公有组件名“加以区分。
包体是包的具体实现细节,其实现在包说明中声明的所有公有过程、函数、游标等。当然也可以在包体中声明仅属于自己的私有过程、函数、游标等。创建包体时,有以下几点需要注意:
- 优点
- 语法
ORACLE PL/SQL编程详解之七:程序包的创建与应用
ORACLE sequence 讲解
在博客园上发现一位大神把oracle数据库相关知识整理得很好,这篇总结里很多内容也是参考借鉴他的
随笔分类 - Oracle