Java知识梳理之数据库MySQL程序设计(十)

124 阅读12分钟

        部分代码的Github地址为:github.com/hzka/JavaBo…,本科时候学过数据库设计这门课程,无奈时间长了,都基本还给老师了。特此利用1-2天时间学习记录下。
(一)基础概念
1.关系型数据库系统
1.1数据库系统的应用

譬如:个人社保信息存储于政府数据库中;购物信息存储于网上商店的数据库中;学籍信息存储于学校数据库中。数据库系统可以存储、访问、处理和分析数据的方法。
1.2数据库系统的组成
数据库是由构成信息的数据组成的存储,譬如MySql、Oracle、SQL Server和Sybase等。需要在数据库管理系统(DBMS)上建立应用程序。
大多数数据库都是关系数据库系统,他们都是基于关系数据模型的,其有三要素:结构、完整性和语言,结构定义数据表示;完整性给出一些对数据的约束;语言提供了访问和操作数据的手段。


1.3数据库要素
所有关系型数据库都支持主键约束和外键约束。
1.3.1关系结构
关系结构围绕一个简单自然的结构建立;表的一行称为一个记录,表的一列称为该记录中一个属性的值。关系数据库理论,一行称为一个元组,一列称为一个属性。下表有八个记录,每个记录有五个属性。同一行的数据互相关联。不同表格的数据可以通过共同属性也可能互相关联。

                           
1.3.2 完整性约束
完整性约束是对表格强加了一个条件,表中所有合法值必须满足该条件。 如下所示:

                             
一般来说,有三种类型约束,内部关联约束(域约束、主键约束)和外键约束。前者每个约束涉及一个关系,后者相互关联。
1.3.2.1域约束
规定一个属性的允许值,
可以使用标准数据类型指定,也可以指定附加约束来缩小范围。譬如上图的numOfCredits的每个值必须大于0小于5等。
1.3.2.2主键约束
超键:一个或一组属性可以唯一表示一个关系,换句话说:没有两个记录具有相同超键。
键:K是最小的超键,K的任何真子集都不是超键。
候选键:一个关系可以有几个键,每个键都是一个候选键。
主键:数据库设计指定的候选键之一,表示一个关系的记录,譬如:上图中的courseId是Course的一个主键。
1.3.2.3外键约束
不同关系中的记录通过共同属性也是相互关联的,共同属性就是外键,外键约束定义了关系之间的关系。若有两个表A,B,C是A的主键,而B中也有C字段,则C就是表B的外键,外键约束主要用来维护两个表之间数据的一致性。譬如:coureseId是表Enrollment中一个外键,它引用了表Course中的主键CoureseId,每个CourseId值必须与表Course中的一个CoureseId匹配。
1.3.2.4强制完整性约束
数据库管理系统强制执行完整性约束并且拒绝违法约束的操作。譬如:插入一个表格已有主键的记录,报错等等。
2.SQL
SQL(结构化查询语言)是用来定义表格和完整性约束以及访问和操纵数据的通用语言。SQL可以用于MySql、Oracle、SQL Server等大多数关系型数据库。在这里我们用MySQL。
2.1.MySQL的搭建教程:
1.参考帖子:www.cnblogs.com/ziyoublog/p…
2.搭建过程中net提示不是内部或外部命令: https://blog.csdn.net/baidu_32542573/article/details/79759939
3.相关命令行:

//1.管理员身份打开命令控制符,进入mysql的bin目录下
cd “D:\Program Files\mysql\mysql-5.6.43-winx64\bin”
//2.启动服务
net start mysql
//3.登录mysql(第一次登录没有密码,直接按回车过)!
mysql -uroot -p
//4.root密码为空时用下面命令修改, 修改成12345:
mysqladmin -u root -p password  12345

2.2在SQL上创建用户账户

//1.在mysql提示符下初始化
use mysql;
//2.创建用户名为kevinhe,密码为123456的账户。
create user 'kevinhe'@'localhost' identified by '123456';
//3.授予权限给kevinhe
 grant select,insert,update,delete,create,drop,execute,references on *.* to 'kevinhe'@'localhost';
//4.如果希望该账号可以从任意的IP地址来远程访问。
grant all privileges on *.* to 'kevinhe'@'%' identified by '123456';
//5.如果希望该账号可以从一个特定的IP地址来进行远程访问。
grant all privileges on *.* to 'kevinhe'@'ipAddress' identified by '123456';
//6.退出(注意一定要加分号)
exit;

       注意:Windows自动启动MySQL数据库,输入命令net stop mysql可以终止,输入命令net start mysql可以启动。默认情况下,该服务器默认包含Mysql和test数据库。Mysql数据库包含存储服务器信息及其用户信息的表格,可以进行权限更改,但不能在这里创建用户表。test数据库来存储数据或者创建新的数据库,可以使用create database databasename来创建新数据库;用drop database databasename来删除已存在数据库。
2.3创建数据库

//1.登录mysql的kevinhe数据库,
mysql -ukevinhe -p123456
注意:第一次报错了,登录不上去,故而先删除已经创建的几个用户和一个空账户,参考帖子:https://blog.csdn.net/asty9000/article/details/80956583
//1.1删除已存在的用户,默认删除的是'XXX'@'%'这个用户,
 drop user kevinhe;
//1.2.如果还有其他的用户如'XXX'@'localhost'等,不会一起被删除。如果要删除'XXX'@'localhost',使用drop删除时需要加上host.
drop user 'kevinhe'@'localhost';
//1.3.删除一个空账户
drop user ''@'localhost';
//2.创建并使用数据库
create database javabook;
use javabook;
//3.安装Navicat和链接Mysql。
Navicat下载:http://www.3673.com/soft/804.html
链接Mysql教程:https://jingyan.baidu.com/article/0aa2237573c1e688cc0d6427.html

2.4创建和删除表
1.创建Course表,包含属性courseId,subjectId,courseNumber,title,numOfCredits,每个都有相应的数据类型。Char(5)是指courseID有五个字符组成;varchar(50)是指title是一个字符个数最多为50的可变长字符串,integer表明coursenumber是一个整数,主键是courseId。

create table Course
(courseId char(5),
subjectId char(4) not null,
courseNumber integer,
title varchar(50) not null,
numOfCredits integer,
primary key (courseId));

2.创建其他两个表Student和Enrollment。

create table Student
(ssn char(9),
firstName varchar(25),
mi char(1),
lastname varchar(25),
birthDate date,
street varchar(25),
phone char(11),
zipCode char(5),
deptId char(4),
priary key (ssn));

create table Enrollment
(ssn char(9),
courseId char(5),
dateRefisted date,
grade char(1),
primary key(ssn,courseId),
foreign key(ssn) references Student(ssn),
foreign key(courseId) references Course(courseId));

3.如果需要删除表,可以使用drop table命令永久删除。
drop table Course;
4.为了方便,将所有命令保存至test.sql文件,可以在SQL命令下输入source test.sql来运行该脚本文件。载入运行即可。

                                 
2.5简单插入、更新、删除
一旦创建表格,就可以添加、更新或者删除记录。
1.添加表格的语法是:

  

insert into Course(courseId,subjectId,courseNumber,title,numOfCredits)
values('11113','CSCI','3720','Database Systems',3);

2.更新表格的语法是:

--将title为Database Systems课程的numOfCredits值改为4.
update Course
set numOfCredits = 4
where title=’Database Systems’;

3.删除记录的语法是:

--从Course表中删除课程Database Systems;
delete from Course
where title=’Database Systems’;

eg:删除Course中的所有记录
delete from Course;
2.6简单查询
select需要遵循以下语法,colum-list是选中的列,from语句是指定查询所涉及的表,where语句指的是选择行的条件。

 

--查找Course表中numOfCredits=3的相关列。如果是select *的话则需要列出所有属性值。
 select courseId,courseNumber,title
 from Course
 where numOfCredits = 3;

2.7比较运算符和布尔运算符

****
2.8操作符like、between..and 和isnull
2.8.1模式匹配操作符like
检验字符串s是否含有模式p的语法是:s like p或者s not like p。在模式p中可以使用通配符%(百分号)和_(下划线),前者匹配零个或者多个字符;后者可与S中单个字符串匹配。eg:lastName like ‘_mi%’表示与第二个第三个字符分别为m和i在任意字符串匹配。lastName not like ‘_mi%’表示排除这种。
2.8.2 between...and
检查字符是否在值v1和v2之间。譬如:v between v1 and v2;等价于v>=v1 and v<=v2。V not between v1 and vw;等价于v<v1,v>v2;

                                      
2.8.3is null
检查值v是否为null,使用如下语法:s is null或者s is not null。
2.9列的别名
显示查询结果,SQL使用列名来作为列的标题。对列采用缩写。使用as关键字。

select courseId as id,courseNumber as num,title as tit
from Course
where numOfCredits = 3;

2.10算数运算符
在SQL中有+-*/四种。

                 
2.11显示互不相同的记录
SQL提供关键字distinct来去除输出重复的元组。
2.12显示排好序的记录
SQL提供关键字order by来对输出结果进行排序。降序是在后面desc,升序是asc,当指定多列时,先对第一列进行排序,在对第一列中具有相同值的行进行排列。以此类推。

                                              
2.13联结表
多个表中获取信息,完成如下查询,SQL语句: 

                          

select distinct lastName,firstName,courseId
from Student,Enrollment
where Student.ssn = Enrollment.ssn and lastName = 'Smith' and firstName = 'Jacob';

3.JDBC
JDBC是访问关系型数据库的API。
3.1什么是JDBC
JDBC表示Java数据库连接,JDBC提供访问和操纵众多关系数据库的一个统一接口。

                                                        
3.2IDEA配置Mysql数据库
链接:blog.csdn.net/wk992337444…
可能遇到的问题:
(1)若没有Database模块:
解决方法:IDEA重新下载Ultimate版本(再也不用Community版本了)

                                                  
2)链接MySQL数据库Test connnection报错:
原因:JDBC驱动程序的5.1.33版本与UTC时区配合使用,必须在连接字符串中明确指定serverTimezone。
解决方法:将URL改成

jdbc:mysql://localhost:3306/javabook?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

3.3使用JDBC开发数据库应用程序
3.3.1简单介绍

使用Java开发任何数据库应用程序都需要4个主要接口:Driver(加载一个合适驱动程序)、Connection(连接到数据库)、Statement(创建和执行SQL)和ResultSet(处理结果)。访问数据库的典型Java程序主要有以下几步:

                                               
3.3.2实施步骤:
(1)加载驱动程序:

程序加载不同的数据库,必须加载各自的去动程序,譬如:对于Mysql数据库而言。是Class.forName(“JDBCDriverClass”);
(2)建立连接:
为了建立一个数据库,需要使用DriverManager类的静态方法getConnection。eg:Connection connection = DraiverManager.getConnection(databaseURL);
(3)创建语句:
Connection是程序与数据库的缆道,statement是缆车。传输SQL语句并返回结果给程序。eg:Statement statement = connection.createStatement();
(4)执行语句
可以使用方法executeUpdate(String sql)来执行数据定义语言或者更新语句。可以使用executequery来查询语句。
(5)处理ResultSet
结果集ResultSet维护一张表,该表的当前行可以获得。getString来获取一些列。
3.3.3 代码示例(P3201代码)
若显示驱动报错,则按照这个帖子(www.cnblogs.com/tffan/p/959…)去使用IDEA加载mysql驱动(驱动版本号:mysql-connection-java-5.1.47)。

import java.sql.*;
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载JDBC驱动程序
        Class.forName("com.mysql.jdbc.Driver");
        System.out.println("Driver loaded");
        //2.链接mysql数据库
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javabook","kevinhe","123456");
        System.out.println("Database created");
        //3.创建一个statement对象
        Statement statement = connection.createStatement();
        //4.执行SQL查询语句并返回一个ResultSet对象
        ResultSet resultSet = statement.executeQuery(" select courseId,courseNumber,title\n" +
                " from Course\n" +
                " where numOfCredits = 3;");
        //5.从Resultset对象处获得查询结果。
        while (resultSet.next()){
            System.out.println(resultSet.getString(1)+"\t"+
                    resultSet.getString(2)+"\t"+
                    resultSet.getString(3));
        }
        //4.关闭链接,释放资源。
        connection.close();
    }
}

4.PreparedStatement
4.1优势及用法

可以创建参数化的SQL语句。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。
4.2代码示例
将P3201代码改为PrepaedStatement这种。

import java.sql.*;
public class Main {
    private static PreparedStatement preparestatement;
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        System.out.println("Driver loaded");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javabook", "kevinhe", "123456");
        System.out.println("Database created");
        String queryString = " select courseId,courseNumber,title\n" +
                " from Course\n" +
                " where numOfCredits = ?;";
        preparestatement = connection.prepareStatement(queryString);
        preparestatement.setString(1,"3");
        ResultSet resultSet = preparestatement.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getString(1) + "\t" +
                    resultSet.getString(2) + "\t" +
                    resultSet.getString(3));
        }
        connection.close();
    }
}

5.CallableStatement
5.1简介

CallableStatement为执行SQL存储过程而设计。有三个参数:IN(接受传递给过程的值)、OUT(结束返回一个值)以及INOUT。可以使用prepareCall来创建对象,譬如:


{call sample....}是SQL转义语法,通知驱动程序中的代码应该被不同处理。使用registerOutPParameter来注册OUT和IN OUT参数。
6.获取元数据
DatabaseMetaData接口来获取数据库的元数据。譬如数据库URL、用户名、JDBC驱动程序名称,ResultSetMeataData接口可以获取到结果集合的元数据,譬如表的列数和列名等。
6.1数据库元数据(P3205项目)
Connection接口用于建立与数据库的链接,先得到conncetion链接,再得到DatabaseMetaData对象,可以使用Connection对象的getMetaData方法。
6.2获取数据库表
getTables通过数据库元数据可以确定数据库中的表格,列出MySQL数据库javabook中的所有用户表。

import java.sql.*;
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载JDBC驱动程序
        Class.forName("com.mysql.jdbc.Driver");
        System.out.println("Driver loaded");
        //2.链接mysql数据库
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javabook", "kevinhe", "123456");
        System.out.println("Database created");
        //3.创建一个statement对象
        DatabaseMetaData dbMetaData = connection.getMetaData();
        System.out.println("URL:" + dbMetaData.getURL());
        System.out.println("username:" + dbMetaData.getUserName());
        System.out.println("product name:" + dbMetaData.getDatabaseProductName());
        System.out.println("product version:" + dbMetaData.getDatabaseProductVersion());
        System.out.println("JDBC diver name:" + dbMetaData.getDriverName());
        System.out.println("JDBC diver version:" + dbMetaData.getDriverVersion());
        System.out.println("Max number of connections:" + dbMetaData.getMaxConnections());
        System.out.println("MaxTableNameLength:" + dbMetaData.getMaxTableNameLength());
        System.out.println("MaxColumeNameLength:" + dbMetaData.getMaxColumnsInTable());
        //表名
        ResultSet rstables = dbMetaData.getTables(null,null,null,new String[]{"Table"});
        System.out.println("Table");
        while (rstables.next()){
            System.out.println(rstables.getString("TABLE_NAME")+" ");
        }
    }
}

6.3结果集元数据(P3207项目)
ResultSetMetaData描述结果集的信息,能找出相关列的类型和属性的信息。

import java.sql.*;
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载JDBC驱动程序
        Class.forName("com.mysql.jdbc.Driver");
        System.out.println("Driver loaded");
        //2.链接mysql数据库
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javabook","kevinhe","123456");
        System.out.println("Database created");
        //3.创建一个statement对象
        Statement statement = connection.createStatement();
        //4.执行SQL查询语句并返回一个ResultSet对象
        ResultSet resultSet = statement.executeQuery(" select *\n" +
                " from Course;");
        ResultSetMetaData rsMetaData = resultSet.getMetaData();
        //获取列数和每一列的名称;
        for(int i = 1;i<=rsMetaData.getColumnCount();i++){
            System.out.printf("%-12s\t",rsMetaData.getColumnName(i));
        }
        System.out.println();
        //所有内容。
        while (resultSet.next()){
            for(int i =1;i<=rsMetaData.getColumnCount();i++){
                System.out.printf("%-12s\t",resultSet.getObject(i));
            }
            System.out.println();
        }
        //4.关闭链接,释放资源。
        connection.close();
    }
}

(二)本章总结