MySQLデータベース
第四章データ整合性
役割:データベースへのユーザ入力データの保存を確実に正しいです。
=あなたがテーブルを作成するときにテーブルに追加されたデータ整合性制約を確認してください。
分類の整合性:
- エンティティ整合性。
- ドメインの整合性、
- 参照整合性;
4.1エンティティの整合性
エンティティ:実体(エンティティ)に代わってテーブル内の行(レコード)。
アクションのエンティティの完全性:データの各行を識別するは繰り返しません。
制約のタイプ:
主キー制約(主キー)
唯一の制約(ユニーク)
自動成長列(AUTO_INCREMENT)
4.1.1主キー制約(主キー)
注意:各テーブルには主キーを持っている必要があります
特徴:データのみとnullにすることはできません
例:
追加する最初の方法:
CREATE TABLE studdent(
id int primary key,
name varchar(50)
);
追加する2番目の方法:この方法での利点は、あなたが主キーを作成することができるということです
CREATE TABLE student(
id int,
name varchar(50),
primary key(id)
);
CREATE TABLE student(
classid int,
stuid int,
name varchar(50),
primary key(classid,stuid)
);
最初のテーブルを作成し、主キーを追加します。第三の方法を追加します。
CREATE TABLE studdent(
id int;
name varchar(50)
);
ALTER TABLE student ADD PRIMARY KEY(id);
唯一の制約(ユニーク)4.1.2
特徴:データを繰り返すことはできませんが、nullにすることができ
CREATE TABLE student(
id int primary key,
name varchar(50) unique
);
4.1.3自動成長列(AUTO_INCREMENT)
SQLServerデータベース(アイデンティティ)は、Oracle Database(シーケンス)
成長は自動的に主キー値に加え、唯一の整数列型とすることができます
CREATE TABLE student(
id int primary key auto_increment,
name varchar(50)
);
INSERT INTO student(name) values('tom');
初期値の自動増加を変更します。
ALTER TABLE tbl_name AUTO_INCREMENT = n;
4.2ドメインの整合性
ドメインの整合性作用:このセルのデータを制限するには、そのようなものがないので、列中の他の細胞と比較し、正しいです
ドメインは、現在のセルを表し、
ドメイン整合性制約:非空制約(nullでない)制約デフォルト値のデータ型(デフォルト)
制約をチェックする(MySQLがサポートしていません)チェック(性別=「男性」または性別=「女性」)
4.2.1データ型
数値型
タイプ | サイズ | レンジ(署名) | レンジ(符号なし) | 使用 |
---|---|---|---|---|
TINYINT | 1つのバイト | (-128127) | (0255) | 小さな整数値 |
SMALLINT | 2つのバイト | (-32768,32767) | (0から65535) | 大きな整数値 |
MEDIUMINT | 3つのバイト | (-8388608,8388607) | (0,16777215) | 大きな整数値 |
INTまたはINTEGER | 4つのバイト | (-2147483648,2147483647) | (0,4294967295) | 大きな整数値 |
BIGINT | 8つのバイト | (-9233372036854775808,9233372036854775807) | (0,18446744073709551615) | 最大の整数値 |
浮く | 4つのバイト | 単精度浮動小数点値 | ||
ダブル | 8つのバイト | 倍精度浮動小数点値 | ||
DOUBLE(M、D) | 8バイト、Mは長さ、Dは小数点以下の桁数を表します。 | 同上。、バウンドMとD | 同上。、バウンドMとD | 倍精度浮動小数点数 |
DECIMAL(M、D) | DECIMAL(M、D)、M> D、M + 2は、そうでなければD + 2である場合 | そしてDは、Mの値に依存しているMは、65の最大値であります | そしてDは、Mの値に依存しているMは、65の最大値であります | 小さな値 |
日付タイプ:
これは、日付と時刻のタイプは、時間値DATETIME、DATE、TIMESTAMP、TIME、およびYEARであることを示します。
指定された違法のMySQLの値が表現できない場合の各タイプは、時間有効範囲と「ゼロ」の「ゼロ」値の値を有します。
タイプ | サイズ(バイト) | スコープ | フォーマット | 使用 |
---|---|---|---|---|
日付 | 3 | 1000年1月1日/ 9999-12-31 | YYYY-MM-DD | 日付値 |
時間 | 3 | '-838:59:59' / '838:59:59' | HH:MM; SS | Time値または期間 |
年 | 1 | 1901/2155 | YYYY | 年の値 |
日付時刻 | 8 | 1000年1月1日00:00:00 / 9999-12-31 23時五十九分59秒 | YYYY-MM-DD HH:MM:SS | 日付と時刻の値の混合 |
TIMESTAMP | 4 | 1970-01-0100:00:00/2038終了時間は2,147,483,647秒、北京2038年1月19日11時14分07秒GMT、2038年1月19日早朝3時14分07秒です | YYYYMMDDHHMMSS | 日付と時刻の値、タイムスタンプをミキシング |
文字列型:
タイプ | サイズ | 使用 |
---|---|---|
CHAR | 0〜255の文字 | 固定長文字列 |
VARCHAR | 0から65536のバイト | 可変長文字列 |
TINYBLOB | 0〜255のバイト | バイナリ文字列ではありません以上255文字以下 |
TINYTEXT | 0〜255のバイト | 短いテキスト文字列 |
BLOB | 0から65536のバイト | バイナリ形式で長いテキストデータ |
テキスト | 0から65536のバイト | 長いテキストデータ |
MEDIUMBLOB | 0-16777215バイト | 中位の長さの形でバイナリテキストデータ |
MEDIUMTEXT | 0-16777215バイト | ミディアムの長さのテキストデータ |
LONGBLOB | 0-4294967295バイト | バイナリ形式のグレートテキストデータ |
LONGTEXT | 0-4294967295バイト | グレートテキストデータ |
CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
BINARY和VARBINARY类类似于CHAR和VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。
BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型: TINYBLOB、 BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。
有4种TEXT类型: TINYTEXT、 TEXT、MEDIUMTEXT和LONGTEXT。 这些对应4种BLOB类型,有相同的最大长度和存储需求。
4.2.2 非空约束
not null
CREATE TABLE student(
id int primary key,
name varchar(50) not null,
sex varchar(10)
);
INSERT INTO student values(1,'tom',null);
4.2.3 默认值约束
default
CREATE TABLE student(
id int primary key,
name varchar(50) not null,
sex varchar(10) default '男'
);
INSERT INTO student values(1,'marry','女');
INSERT INTO student values(2,'tom',default);
INSERT INTO student(id,name) values(1,'jack');
4.3 引用完整性
(参照完整性)
外键约束:FOREIGN KEY
示例:
#学生表
CREATE TABLE student(
sid int primary key,
name varchar(50) not null,
sex varchar(10) default '男'
);
#成绩表
CREATE TABLE score(
id int primary key,
score int,
sid int,
CONSTRAINT fk_score_sid FOREIGN KEY(sid) REFERENCES student(sid)
);
#第二种写法(简写)
CREATE TABLE score(
id int primary key,
score int,
sid int references student(sid),
);
-- 外键列的数据类型一定要与主键的类型一致
第二种添加外键方式。
#成绩表
CREATE TABLE score(
id int primary key,
score int,
sid int,
);
ALTER TABLE score ADD CONSTRAINT fk_score_sid FOREIGN KEY(sid) REFERENCES student(sid);
第五章 多表查询
多个表之间是有关系的,那么关系靠谁来维护?
多表约束:外键约束。
5.1 多表的关系
5.1.1 一对多关系
客户和订单,分类和商品,部门和员工。
一对多建表原则:在多的一方创建一个字段,字段作为外键指向一的一方的主键。
5.1.2 多对多关系
学生和课程:
多对多关系建表原则:需要创建第三张表,中间表至少两个字段,这两个字段分别作为外键指向各自一方的主键。
5.1.3 一对一关系
在实际开发中应用不多,因为一对一可以创建成一张表。
两种建表原则:
唯一外键对应:假设一对一是一个一对多的关系,在多的一方创建一个外键指向一的一方的主键,将外键设置为unique和 not null。
主键对应:让一对一的双方的主键进行建立关系。
5.2 多表查询
多表查询有如下几种:
合并结果集:UNION、UNION ALL
连接查询
2.1内连接[INNER] JOIN ON
2.2外连接OUTER JOIN ON
- 左外连接LEFT [OUTER] JOIN
- 右外连接RIGHT [OUTER] JOIN
- 全外连接(MySQL不支持)FULL Join
2.3自然连接NATURAL JOIN
子查询
5.2.1 合并结果集
作用:合并结果集就是把两个select语句的查询结果合并到一起。
合并结果集有两种方式:
UNION:去除重复记录,例如
SELECT * FROM t1 UNION SELECT * FROM t2;
UNION ALL:不去除重复记录,例如:
SELECT * FROM t1 UNION ALL SELECT * FROM t2;
注意:被合并的两个结果:列数、列类型必须相同。
5.2.2 连接查询
连接查询就是求出多个表的乘积,例如t1连接t2,那么查询的结果就是t1*t2。
连接查询会产生笛卡尔积,假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况。
那么多表查询产生这样的结果并不是我们想要的,那么怎么去除重复的,不想要的记录呢,当然是通过条件过滤。通常要查询的多个表之间都存在关联系,那么就通过关联关系去除笛卡尔积。
示例1:现有两张表
emp表:
CREATE TABLE emp(
empno int,
ename varchar(50),
job varchar(50),
mgr int,
hiredate date,
sal decimal(7,2),
deptno int
);
dept表:
CREATE TABLE dept(
deptno int,
dname varchar(14),
loc varchar(13)
);
执行如下语句:
SELECT * FROM emp,dept;
使用主外键关系作为条件来去除无用信息
SELECT * FROM emp,dept WHERE emp.deptno = dept.deptno;
上面查询会把两张表的所有列都查询出来,也许你不需要那么多列,这是就可以指定要查询的列了。
SELECT emp.ename,emp.sal,emp.comn,emp.deptno,emp.dname
FROM emp,dept
WHERE emp.deptno = dept.deptno;
一、内连接
上面的连接语句就是内连接,但它不是SQL标准中的查询方式。
SQL标准的内连接为:
SELECT *
FROM emp e
INNER JOIN dept d
ON e.deptno = d.deptno;
内连接的特点:查询结果必须满足条件。
二、外连接
包括左外连接和右外连接,外连接的特点:查询出的结果存在不满足条件的可能。
a、左外连接
SELECT * FROM emp e
LEFT OUTER JOIN dept d
ON e.deptno = d.deptno;
左连接是先查询出左表(即以左表为主),然后查询右表,右表中满足条件的显示出来,不满足条件的显示NULL。
我们还是用上面的例子来说明。其中emp表中"Bob"这条记录中,部门编号为50, 而dept表中不存在部门编号为50的记录,所以“张三”这条记录,不能满足e.deptno=d.deptno这条件。 但在左连接中,因为emp表是左表,所以左表中的记录都会查询出来,即“Bob"这条记录也会查出,但相应的右表部分显示NULL。
b、右外连接
右连接就是先把右表中所有记录都查询出来,然后左表满足条件的显示,不满足显示NULL。例如在dept表中的40部门并不存在员工,但在右连接中,如果dept表为右表,那么还是会查出40部门,但相应的员工信息为NULL。
SELECT * FROM emp e
RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno;
连接查询心得:
连接不限于两张表,连接查询也可以是三张、四张,甚至N张表的连接查询。通常连接查询不可能需要整个笛卡尔积,而只是需要其中一部分,那么这时就需要使用条件来去除不需要的记录。这个条件大多数情况下都是使用主外键关系去除。
两张表的连接查询一定有一个主外键关系,三张表的连接查询就一定有两个 主外键关系,所以在大家不是很熟悉连接查询时,首先要学会去除无用笛卡尔积,那么就是用主外键关系作为条件来处理。如果两张表的查询,那么至少有一个主外键条件,三张表连接至少有两个主外键条件。
5.2.3 子查询
一个select语句中包含另一个完整的select语句。
子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个或两个以上的SELECT,那么就是子查询语句了。里面的查询叫做子查询,外层的查询叫父查询,一般情况都是先执行子查询再执行父查询。
子查询出现的位置:
- where后,作为被查询的条件的一部分;
- from后,作表。
当子查询出现在where后作为条件时,还可以使用如下关键字:
- any
- all
子查询结果集的形式:
- 单行单列(用于条件)
- 单行多列(用于条件)
- 多行单列(用于条件)
- 多行多列(用于表)
示例:
1、查询工资高于JONES的员工
分析:
查询条件:工资>JONES,其中JONES工资需要一条子查询
第一步:查询JONES的工资
SELECT sal FROM emp WHERE ename = 'JONES';
第二步:查询高于JONES工资的员工
SELECT * FROM emp WHERE sal > (第一步的结果);
结果:
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename = 'JONES');
2、查询与SCOTT同一个部门的员工
子查询作为条件
子查询形式为单行单列
分析:
查询条件:部门=SCOTT的部门编号,其中SCOTT的部门编号需要一条子查询
第一步:查询SCOTT的部门编号
SELECT deptno FROM emp WHERE ename = 'SCOTT';
第二步:查询部门编号等于SCOTT的部门编号的员工
SELECT * FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'SCOTT');
3、工资高于30号部门所有人的员工信息
分析:
SELECT * FROM emp WHERE sal >(SELECT MAX(sal) FROM emp WHERE deptno = 30);
查询条件:工资高于30部门所有人工资,其中30号部门所有人工资是子查询,高于所有需要使用ALL关键字。
第一步:查询30号部门所有人工资
SELECT sal FROM emp WHERE deptno = 30;
第二步:查询高于30号部门所有人工资的员工信息
SELECT * FROM emp WHERE sal > ALL(第一步结果);
结果:
SELECT * FROM emp WHERE sal > ALL(SELECT sal FROM emp WHERE deptno = 30);
4、工资高于30号部门中任意一个人的员工信息
SELECT * FROM emp WHERE sal > ANY(SELECT sal FROM emp WHERE deptno = 30);
子查询作为条件
子查询形式为多行单列(当子查询结果集形式为多行单列时可以使用ALL或ANY关键字)
5、查询1982年后入职员工中工资最高的员工信息
SELECT *,MAX(sal) FROM (SELECT * FROM emp WHERE hiredate >= '1982-01-01') AS temp;
5.2.4 导出导入数据库
1、使用命令方式
导出数据库表:
mysqldump -u用户名 -p 数据库名 > 导出路径与文件名
导入数据库表:
mysql -u用户名 -p
mysql>use 数据库名
然后使用source命令,后面参数为脚本文件(如这里用到的.sql)
mysql>source 导出路径与文件名
2、使用工具导入导出工具
5.2.5 创建用户和授权
创建用户
CREATE USER 用户名及地址(`zhangsan`@`localhost`) IDENTIFIED BY 密码('123456');
授权
GRANT ALL(权限) ON school.*(数据库名.表名) TO `zhangsan`(用户名)
撤销授权
REVOKE ALL(权限) ON school.*(数据库名.表名) TO `zhangsan`(用户名);
删除用户
DROP USER `zhangsan`(用户名);