一、数据库基础知识
1.数据库技术的特点
数据管理的两个阶段
–文件管理
各种数据都是以文件为单位存储在外存,且由操作系统统一管理
文件相对独立,文件结构不能很好地反映现实世界中事物之间的联系,文件中存在大量的数据冗余
–数据库管理
以数据为中心组织数据,减少冗余,并提供更高的数据共享能力,由数据库系统进行管理
程序和数据具有较高的独立性,当数据的逻辑结构改变时,不涉及数据的物理结构,也不影响应用程序,从而降低应用程序研制与维护的费用
数据库技术有如下一些特点
– 面向企业或部门,以数据为中心组织数据,形成综合性的数据库为各应用共享
– 采用一定的数据模型。数据模型不仅要描述数据本身的特点,而且要描述数据之间的联系
– 数据冗余小,易修改、易扩充。不同的应用程序根据处理要求,从数据库中获取需要的数据,这样就减少了数据的重复存贮,也便于维护数据的一致性
– 程序和数据有较高的独立性。当数据的物理结构和逻辑结构改变时,有可能不影响或较少影响应用程序
– 具有良好的用户接口,用户可方便地开发和使用数据库
– 对数据进行统一管理和控制,提供了数据的安全性、完整性、以及并发控制
应用程序访问数据库的基本模式
–DBMS(数据库管理系统)是数据库的核心软件。数据库系统的各种操作,包括创建数据库对象、检索和修改数据库中的数据,都是通过DBMS实现的
2.数据模型
–数据库的逻辑结构
–所有的数据库系统都是基于某种数据模型的
–不同种类的数据库可能支持不同的数据模型
–关系数据库就是因为支持关系模型而得名
关系模型
– 形象地说就是二维表结构,也称之为关系表
– 一个关系数据库可以包含多个关系表,关系表是数据库中组织和存储数据的基本单位
– 每个表都用于存储面向某个主题的信息。例如:
l学生表存储学生信息
l系表存储各系的信息
l课程表存储课程信息等
– 关系表每一行存储一个记录,每一列表示记录的一个属性。设计一个关系表时需要
l为表命名
l设计表的列结构,其中包括列名及列的数据类型
3.关系表中的主键与外键
主键
– 为了保证关系表中没有重复的记录,需要为关系表定义一个主键,作用是唯一标识表中的一个记录
– 可以是表中的一列,也可以由几列组合而成
– 在建表时如果定义了主键,系统可以对输入该表的数据进行检查,要求主键不能重、也不能空(NULL)
– 例如在学生表中
学号可以作为主键,因为一个学号可以唯一地确定表中的一个学生记录
由于学生中有重名现象,姓名就不能用来做为主键
外键
– 现实世界中事物之间的联系反映到数据库中就体现为表之间的联系,在关系数据库中,借助“外键”实现存贮这种联系的信息
– 如果一个表中的某一列是另外一个表中的主键,那么该列称之为外键。
例如在学生表中,“系号”就是外键,因为系号是系表的主键,在学生表中设计了“系号”一列,就是为了存储学生和系之间的联系信息
– 通过外键和主键的等值连接将不同表里的相关记录连接在一起,从而实现数据库中相关数据的查找
可以查询每个学生所在系的信息,也可以查询指定系所包含的学生信息
4.SQL语言简介
(1)SQL语言
– 关系数据库的标准语言,从大型数据库(如Oracle)到微机数据库(如Access)都支持
– 可以实现对数据库的各种操作。例如
表及其他数据库对象的定义
数据的查询与数据维护
对数据库进行控制
– 是非过程化的语言,只需要告诉数据库做什么,而不需要描述怎么做
– 语句都是独立执行的,无上下文联系
– 本身不区分大小写
(2)SQL关键字
SQL 关键字
描述
SELECT
从一个或多个表中提取数据
FROM
SELECT查询的数据表格
WHERE
决定数据行被提取、删除或更新的标准
GROUP BY
对行进行分组的标准
ORDER BY
对行进行排序的标准
INNER JOIN 合并多个表格中的行
INSERT
向指定表中插入行
UPDATE
更新指定表中的行
DELETE
删除指定表格中的行
(3)SQL语言的读/写操作
在SQL语言中,对数据库中数据的操作可分为读写两种
– 读操作(查询)通过SELECT语句实现,该语句的执行不会改变数据库中的数据
可以返回一行或多行数据
也可能没有返回结果(没有查到满足条件的记录)
– 涉及到写操作的语句共有3个
INSERT
UPDATE
DELETE
(4)
建表语句
-定义表中各列的名称及数据类型
–有关列的数据类型可参考具体数据库的语法手册
CREATE TABLE person
( id INTEGER PRIMARY KEY, //定义该列为主键
name VARCHAR(10), //列定义,字符型
department INTEGER, //列定义,整型
occupation VARCHAR(10),
salary NUMBER,
education INTEGER);
插入语句
– 向指定表插入一条记录,插入的值要与表的定义匹配
插入一行数据
INSERT INTO table_name
VALUES(value1, value2,....)
插入一行数据在指定的字段上
INSERT INTO table_name (column1, column2,...)
VALUES (value1, value2,....)
– 例如在person表中插入一行
INSERT INTO person
VALUES(1, '张三', 1, 'manager', 3500, 5);
修改语句
– 修改指定记录中某列的值,更新表中原有数据
– 其格式为
UPDATE table_name SET column_name = new_value
WHERE column_name = some_value
– 例如:将person表中id号为1的人员的工资修改为3700元
UPDATE person
SET salary = 3700 //指定对哪列进行修改、如何修改
WHERE id = 1 ; //选择要修改的行
删除语句
–删除表中的指定的数据
–其格式为
DELETE FROM table_name WHERE column_name =
some_value
–例如删除部门号为4的员工记录
DELETE FROM person WHERE department = 4 ;
查询语句
– 从指定表中取出指定的数据
SELECT select_list
[ INTO new_table ]
FROM table_source
[ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]
–例:查询工资大于2000的员工的姓名及职务
SELECT * //“*”号表示输出全部列的值
FROM person //指定查询的表,本查询只用到person表
WHERE salary>2000 ; //查询条件
–例:查询员工“张三”的学历,输出学历名
SELECT education.name
FROM person , education //该查询用到两个表
WHERE person.name= '张三' AND person.education
=education.eduid ;
二、通过JDBC访问数据库
1.
JDBC (Java DataBase Connectivity)
– 是用于执行SQL语句的Java应用程序接口,由一组用Java语言编写的类与接口组成,是一种底层API
– 使开发人员可以用纯Java语言编写完整的数据库应用程序
– 用JDBC写的程序能够自动地将SQL语句传送给几乎任何一种数据库管理系统(DBMS)
– 是一种规范,它让各数据库厂商为Java程序员提供标准的数据库访问类和接口,这样就使得独立于DBMS的Java应用开发工具和产品成为可能
– 隔离了Java与不同数据库之间的对话,使得程序员只须写一遍程序就可让它在任何数据库管理系统平台上运行
– 使用已有的SQL标准,并支持其它数据库连接标准,如与ODBC (Open Database Connectivity) 之间的桥接
ODBC(Open Database Connectivity)
– 由微软公司提出,用于在数据库管理系统(DBMS)中存取数据
– 是一套用C语言实现的访问数据库的API
– 通过ODBC API,应用程序可以存取保存在多种不同数据库管理系统(DBMS)中的数据,而不论每个DBMS使用了何种数据存储格式和编程接口
– 对于没有提供JDBC驱动的数据库,从Java程序调用本地的C程序访问数据库会带来一系列安全性、完整性、健壮性等方面的问题,因而通过JDBC-ODBC桥来访问没有提供JDBC接口的数据库是一个常用的方案
ODBC的结构
– 应用程序(Application) :本身不直接与数据库打交道,主要负责处理并调用ODBC函数,发送对数据库的SQL请求及取得结果
– 驱动器管理器(ODBC manager) :为应用程序装载数据库驱动器
– 数据库驱动器(ODBC Drivers) :实现ODBC的函数调用,提供对特定数据源的SQL请求。
– 数据源(Data Sources,数据库) :由用户想要存取的数据以及与它相关的操作系统、DBMS和用于访问DBMS的网络平台组成。
访问数据库的模式
你的程序<--> ODBC管理器<--> ODBC驱动程序<--> 数据库
JDBC API
–是一组由Java语言编写的类和接口,包含在java.sql和javax.sql两个包中
java.sql为核心包,这个包包含于J2SE中
javax.sql包扩展了JDBC API的功能,成为了J2EE的一个基本组成部分
–可分为两个层次
面向底层的JDBC Driver API
–主要是针对数据库厂商开发数据库底层驱动程序使用
面向程序员的JDBC API
JDBC的Driver类型
JDBC的Driver可以分为4种类型
名称
解释
JDBC-ODBC和ODBC Driver
通过ODBC驱动器提供数据库连接。使用这种驱动器,要求每一台客户机都装入ODBC驱动。
Native-API partly-Java Driver
将数据库厂商的特殊协议转换成Java代码及二进制类码,客户机上需要装有相应DBMS的驱动程序。
JDBC-Net All-Java Driver
将JDBC指令转化成独立于DBMS的网络协议形式,再由服务器转化为特定DBMS的协议形式。目前一些厂商已经开始添加JDBC的这种驱动器到它们已有的数据库中介产品中。
Native-protocol All-Java Driver
将JDBC指令转化成网络协议后不再转换,而是由DBMS直接使用。
在这四种驱动器中,后两种“纯Java”的驱动器效率更高,也更具有通用性,它们能够充分表现出Java技术的优势,例如可以在applet中自动下载需要的JDBC驱动器
如果不能得到纯Java的驱动器,则可以使用前两种驱动器作为中间解决方案,因为它们比较容易获得,使用也较普遍。
JDBC API的任务
面向程序员的JDBC API可以完成以下主要任务
–首先建立和数据源的连接
–然后向其传送查询和修改等SQL命令
–最后处理数据源返回的SQL执行的结果
JDBC API中重要的接口和类
名称
解释
DriverManager
处理驱动的调入并且对产生新的数据库连接提供支持
DataSource
在JDBC 2.0 API中被推荐使用代替DriverManager实现和数据库的连接
Connection
代表对特定数据库的连接
Statement
代表一个特定的容器,容纳并执行一条SQL语句
ResultSet
控制执行查询语句得到的结果集
JDBC程序开发步骤
一个基本的JDBC程序开发包含如下步骤
– 设置环境,引入相应的JDBC类
– 选择合适的JDBC驱动程序并加载
– 分配一个Connection对象
– 分配一个Statement对象
– 用该Statement对象进行查询等操作
– 从返回的ResultSet对象中获取相应的数据
– 关闭Connection
1.设置环境
在本机上安装有关数据库软件(如:MySQL)
下载相应数据库驱动程序并安装(如:MySQL JDBC,MySQL Connector/J is the official JDBC driver for MySQL)
在Java程序中引入相应的类和包。任何使用JDBC的源程序都需要引入java.sql包,如必要的时候还需要装载相应的JDBC-ODBC驱动程序的包
import java.sql.*;
import sun.jdbc.odbc.JdbcOdbcDriver;
(1)通过JDBC-ODBC桥访问数据库
–安装Java 和JDBC API
安装JDK的同时就自动安装了
–安装数据库驱动程序
安装JDK的同时就自动安装了安装JDBC-ODBC桥驱动程序
–安装DBMS
–建立一个数据库,并注册数据源
(2)注册数据源
a.确定数据源名称和说明。依次进入本机的控制面板——>管理工具——>数据源(ODBC),弹出“ODBC数据源管理器”对话框,单击“系统DSN”选项卡,选择”Add”按钮
b. 单击“添加”按钮后弹出“创建数据源”对话框,选择“Microsoft AccessDriver”选项。单击“完成”按钮后,弹出“ODBC Microsoft Access安装”对话框,在“数据源名”输入框中填写“PIMS”;在“说明”输入中填写“员工信息管理系统”;单击选择按钮,弹出“选择数据库”对话框,在目录中选定已建好的数据库文件如“PMS.mdb”
找不到Microsoft Access Driver(*.mdb)ODBC驱动程序的解决方法:(选择ODBC 数据源(32 位))
打开目录:“C:\Windows\SysWOW64”,双击该目录下的“odbcad32.exe”文件,就进去ODBC数据源管理界面了,现在这个界面中就有access的驱动了!
c. 单击“高级”按钮,弹出“设置高级选项”对话框,在“登录名称”文本编辑框中设定登陆名称为“Test”,在“密码”文本编辑框中设定密码为“1234”。依次确定返回到“ODBC 数据源管理器”对话框,这时可以发现“系统数据源”选项中增添了一个新确定的数据源“PIMS”,单击“ODBC Microsoft Access”对话框的“确定”按钮,就完成了数据源的注册
2.建立连接
接下来要建立和DBMS的连接。包括两个步骤
(1) 装载驱动器,用Class.forName方法显式装载驱动程序,如:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
以完整的Java类名字符串为参数,装载此类,并返回一个Class对象描述此类
执行上述代码时将自动创建一个驱动器类的实例,并自动调用驱动器管理器DriverManager类中的RegisterDriver方法来注册它
这里“sun.jdbc.odbc.JdbcOdbcDriver”是驱动器类的名字,可以从驱动程序的说明文档中得到
需要注意的是,如果驱动器类有可能不存在,使用此方法就可能会抛出ClassNotFoundException异常,因此需要捕获这个异常:
try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");}
catch(ClassNotFoundException e){ System.out.println(e.getMessage);}
(2) 建立与数据库的连接,调用DriverManager.getConnection()方法。例如,我们要连接创建的Access数据库PIMS,语句如下:
Connection con = DriverManager.getConnection("jdbc:odbc:PIMS", "test","1234");
将返回与指定数据库建立的连接
该方法有三个字符串参数
– 第一个是JDBC URL,格式为jdbc:子协议:子名称
Jdbc表示协议,JDBC URL 中的协议总是jdbc;
子协议是驱动器名称;
子名称是数据库的名称,如果是位于远程服务器上的数据库,则还应该包括网络地址,//主机名:端口/数据库名
– 第二个是访问数据库所需的用户名
– 第三个是用户密码
Connection是一个接口,表示与指定数据库的连接
DriverManager类位于JDBC的管理层,作用于用户和驱动程序之间。它负责跟踪在一个系统中所有可用的JDBC驱动程序,并在数据库和相应驱动程序之间建立连接
3.对数据库进行操作
建立好到数据库的连接后,就可以进行对数据库的操作了,一般包括如下三个步骤
– 使用Connection对象创建Statement对象
– 使用Statement对象执行SQL命令
– 从上一步骤返回的ResultSet对象中提取执行结果
(1)创建Statement对象
Connection接口有3个方法可用来创建向数据库发送SQL语句的对象
– createStatement
创建向数据库发送SQL语句的Statement对象,用于简单的SQL语句
Statement stmt = con.createStatement();
– prepareStatement
创建向数据库发送SQL语句的PreparedStatement对象,用于带有一个或多个参数的SQL语句。在SQL语句执行前,这些参数将被赋值
– prepareCall
创建向数据库发送SQL语句的CallableStatement对象,用于调用数据库中的存储过程
(2)使用Statement对象执行语句
Statement 接口提供了三种执行SQL 语句的方法,使用哪一个方法由SQL 语句所产生的内容决定
– executeQuery
用于产生单个结果集的语句,例如SELECT 语句
ResultSet rs = stmt.executeQuery("Select * From Person");
– executeUpdate
用于执行INSERT、UPDATE 或DELETE 语句,以及CREATE TABLE
stmt.executeUpdate("DELETE FROM Person WHERE Name='李四'");
返回值是一个整数,表示受影响的行数(即更新计数),比如修改了多少行、删除了多少行等。对于CREATE TABLE 等语句,因不涉及到行的操作,所以executeUpdate的返回值总为零
– Execute
用于执行返回多个结果集(ResultSet 对象)、多个更新计数或二者组合的语句。例如执行某个已存储过程或动态执行SQL,这时有可能出现多个结果的情况
(3)提取执行结果
查询结果作为结果集(ResultSet)对象返回后,我们可以从ResultSet对象中提取结果
– 使用next方法
ResultSet对象中含有检索出来的行,其中有一个指示器,指向当前可操作的行,初始状态下指示器是指向第一行之前
方法next的功能是将指示器下移一行,所以第一次调用next方法时便将指示器指向第一行,以后每一次对next的成功调用都会将指示器移向下一行
–使用getXXX方法
使用相应类型的getXXX方法可以从当前行指定列中提取不同类型的数据。例如,提取VARCHAR类型数据时就要用getString方法,而提取FLOAT类型数据的方法是getFloat
允许使用列名或列序号作为getXXX方法的参数
String s = rs.getString("Name");
–提取当前行Name列中的数据,并把其从SQL的VARCHAR类型转换成Java的String类型,然后赋值给对象s
String s = rs.getString(2);//提取当前行的第2列数据
–这里的列序号指的是结果集中的列序号,而不是原表中的列序号
(4)执行带参数的SQL语句
JDBC支持带参数的SQL语句的执行,这给SQL语句的执行带来很大的灵活性
使用该功能时不能使用Statement类对象,必须利用PreparedStatement类对象