SQL基础

一 SQL分类

SQL语句主要划分为以下3个类别

1.DDL语句:数据定义语言,这些语句定义了不同的数据段,数据库,表,列,索引等数据库对象的定义。通常的语句关键字包括create,drop,alter等
2.DML语句:数据操纵语句,数据操纵语句,用于添加,删除,更新和查询数据库记录,并检查数据完整性,常用的关键字主要包括insert,delete,update和select等
3.DCL语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句,这些语句定义了数据库的,表,字段,用户的访问权限和安全级别。主要的语句关键字包括grant,revoke等。

 DDL语句:

DDL是数据定义语言的缩写,简单来说,就是对数据库内部的对象进行创建,删除,修改的操作语言。他和DML语言最大的区别是DML只是对表内部数据的操作,而不涉及到表的定义,结构的修改,更不会涉及到其他对象。DDL语句更多的被数据库管理员使用。下面通过一些例子来介绍mysql中常用的DDL语句的使用方法。

  1. 创建数据库

  启动mysql服务之后,输入以下命令连接到mysql服务器:

  在以上的命令行中,mysql代表客户端命令,-u后面跟连接的数据库用户,-p表示需要输入数据库密码

  如果数据库设置正常,并输入正确的密码,将看到上面一段欢迎界面和一个mysql>提示符。在欢迎界面中介绍了以下几部分内容。

1.命令的结束符,用;或者g结束
2.客户端的连接ID,这个数字记录了mysql服务到目前为止的连接次数,每次新连接都会自动加1
3.mysql服务器的版本,本例中是5.6.45
4.通过“help;”或者是“h”命令来显示帮助的内容,通过“c”命令来清除命令行buffer。
在mysql>提示符后面输入索要执行的SQL语句,每个SQL语句以分号或者g结束,按回车键执行

  因为所有的数据都存储在数据库中,现在学习的第一个命令是创建数据库,语法如下所示:

CREATE DATABASE dbname;

  例如,创建数据库test1,命令执行如下:

mysql> create database test1;
Query OK, 1 row affected (0.03 sec)

  可以发现,执行完创建命令之后,下面有一行提示“Query OK, 1 row affected (0.03 sec)”,这段提示可以分为3部分,“Query Ok”表示上面的命令执行成功,读者可能会奇怪,又不是执行查询操作,为什么会显示查询成功?这是mysql的一个特点,所有的DDL和DML(不包含select)操作执行成功后都显示“Query Ok”,这里理解为执行成功就可以了;“1 row affected”表示操作只影响了数据库中一行记录。

  如果已经存在这个数据库,系统会提示:

mysql> create database test1;
ERROR 1007 (HY000): Can't create database 'test1'; database exists

  这个时候想知道都存在哪些数据库,可以用以下命令来查看:

  可以发现上面的列表中除了刚刚创建的test1之外,还存在其他的数据库,其中information_schema,cluster,mysql,test是安装mysql时系统自动创建的

information_schema:主要存储了系统中的一些数据库对象信息。比如用户信息,列信息,权限信息,字符集信息,分区信息等

cluster:存储了系统的集群信息。

mysql:存储了系统的用户权限信息。

test:系统自动创建的测试数据库,任何用户都可以使用。

  在查看了系统中已有的数据库后,可以用如下命令选择要操作的数据库:

USE dbname

  例如,选择数据库test1:

mysql> use test1;
Database changed

  然后再用命令查看test1数据库中创建的所有的数据表:

mysql> show tables;
Empty set (0.05 sec)

  由于test1是刚创建的数据库,还没有表,所以显示为空。命令行下面的“Empty set”表示操作的结果集为空。如果查看一下mysql数据库里面的表,则可以得到以下信息:

  2. 删除数据库

  删除数据库的语法很简单,如下所示:

drop database dbname;

  例如,要删除test1数据库可以使用以下语句:

drop database test1

  注意:数据库删除之后,下面所有的表数据都会被全部删除,所以删除之前一定要仔细检查并做好相应的备份

  3. 创建表

  在数据库中创建一张表的基本语法如下:

CREATE TABLE tablename (column_name_1 column_type_1 constraints,
column_name_2  column_type_2  constraints , ……column_name_n  column_type_n
constraints)

  因为mysql的表名是以目录的形式存在于磁盘上,所以表名的字符可以用任何目录名允许的字符。column_name是列的名字,column_type是列的数据类型,contains是这个列的约束条件。

  例如创建一个名称为emp的表,表中包含3个字段,ename(姓名)hiredate(雇用日期),sal(薪水),字段类型为varchar(10),date,int(2):

mysql> create table emp(ename varchar(10),hiredate date,sal decimal(10,2),deptno int(2));
Query OK, 0 rows affected (0.14 sec)

  表创建完毕后,如果需要查看表的定义,可以使用如下命令:

DESC tablename;

  例如查看emp表,将输出以下信息:

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(10)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.05 sec)

  4. 删除表

  表的删除命令如下:

DROP TABLE tablename

   5. 修改表

  对于已经创建好的表,尤其是已经有大量数据的表,如果需要对表做一些结构上的改变,我们可以先将表删除(drop),然后再按新的表的定义重建表,这样做没有什么问题,但是必须做一些额外的工作,比如数据的重新加载。而且,如果有服务在访问表,也会对服务产生影响。因此,在大多数情况下,表结构的更改一般都使用alter table语句,以下是一些常用的命令。

  (1)修改表类型,语法如下:

ALTER TABLE tablename MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]

  例如,修改表emp的ename字段定义,将varchar(10)改为varchar(20):

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(10)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.06 sec)

mysql> alter table emp modify ename varchar(20);
Query OK, 0 rows affected (0.12 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.04 sec)

  (2)增加字段,语法如下:

ALTER TABLE tablename ADD [COLUMN] column_definition [FIRST | AFTER col_name]

  例如,表emp上新增加字段age,类型为int(3):

mysql> alter table emp add column age int(3);
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
| age      | int(3)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.06 sec)

  (3)删除表字段,语法如下:

ALTER TABLE tablename DROP [COLUMN] col_name

  例如,将字段age删掉:

mysql> alter table emp drop column age;
Query OK, 0 rows affected (0.06 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno   | int(2)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.02 sec)

  (4)字段改名,语法如下:

ALTER TABLE tablename CHANGE [COLUMN] old_col_name column_definition
[FIRST|AFTER col_name]

  例如,将deptno改名为deptno1,同时修改字段类型我int(4):

mysql> alter table emp change deptno deptno1 int(4);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno1  | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.01 sec)

  注意:change和modify都可以修改表定义,不同的是change后面需要写两次列名,不方便。但是change的优点是可以修改列名称,modify则不能。

  (5)修改字段排列顺序

  前面介绍的字段增加和修改语法(ADD/CNAHGN/MODIFY)中,都有一个可选项first|alter column_name,这个选项可以用来修改字段在表中的位置,默认ADD增加的新字段是加在表的最后位置,而CHANGN/MODIFY默认都不会改变字段的位置。

  例如,将新增的字段birth date 加在ename之后:

mysql> alter table emp add birth date after ename;
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno1  | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.04 sec)

  (6)表改名,语法如下:

ALTER TABLE tablename RENAME [TO] new_tablename

  例如,将表emp改名为emp1,命令如下:

mysql> alter table emp rename emp1;
Query OK, 0 rows affected (0.05 sec)

mysql> desc emp
    -> ;
ERROR 1146 (42S02): Table 'test1.emp' doesn't exist
mysql> desc emp1;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename    | varchar(20)   | YES  |     | NULL    |       |
| birth    | date          | YES  |     | NULL    |       |
| hiredate | date          | YES  |     | NULL    |       |
| sal      | decimal(10,2) | YES  |     | NULL    |       |
| deptno1  | int(4)        | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
5 rows in set (0.05 sec)

 

DML语句

  DML操作是指对数据库中表记录的操作,主要包括表记录的插入(insert),更新(update),删除(delete)和查询(select),是开发人员日常使用最频繁的操作。

  1. 插入记录

  表创建以后,就可以往里插入数据了,插入数据的基本语法如下:

INSERT INTO tablename (field1,field2,……fieldn) VALUES(value1,value2,……valuesn);

  例如,向表emp中插入以下记录:ename为zzx1,hiredate为2000-01-01,sal为2000,deptno1为1,命令执行如下:

mysql> insert into emp1 (ename,hiredate,sal,deptno1) values('zzx1','2000-01-01','2000',1);
Query OK, 1 row affected (0.06 sec)

  对于含可空字段,非空但是含有默认值的字段,自增字段,可以不用在insert后的字段列表里面出现,values后面只写对应字段名称的value,这些没写的字段可以自动设置为NULL,默认值,自增的下一个数字,这样在某些情况下可以大大缩短SQL语句的复杂性。

  例如,只对表中的ename和sal字段显式插入值:

mysql> insert into emp1 (ename,sal) values('dony',1000);
Query OK, 1 row affected (0.05 sec)

  来看一下实际插入值:

mysql> select * from emp1;
+-------+-------+------------+---------+---------+
| ename | birth | hiredate   | sal     | deptno1 |
+-------+-------+------------+---------+---------+
| zzx1  | NULL  | 2000-01-01 | 2000.00 |       1 |
| dony  | NULL  | NULL       | 1000.00 |    NULL |
+-------+-------+------------+---------+---------+
2 rows in set (0.04 sec)

  在mysql中,insert语句还有一个很好的特性,可以一次性的插入多条数据,语法如下:

INSERT INTO tablename (field1, field2,……fieldn)
VALUES
(record1_value1, record1_value2,……record1_valuesn),
(record2_value1, record2_value2,……record2_valuesn),
……
(recordn_value1, recordn_value2,……recordn_valuesn)
;

  可以看出,每条记录之间都用逗号进行了分隔。

  2. 更新记录

  对于表里面的记录值,可以通过update命令进行更改,语法如下:

UPDATE tablename SET field1=value1,field2.=value2,……fieldn=valuen [WHERE CONDITION]

  例如,将表emp中的ename为zzx1的薪水从3000更改为4000:

mysql> update emp1 set sal=4000 where ename='zzx1'
    -> ;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

  3. 删除记录

  如果记录不再需要,可以用delete命令进行删除,语法如下:

DELETE FROM tablename [WHERE CONDITION]

  4. 查询记录

  数据插入到数据库中后,就可以用select命令进行各种各样的查询,使得输出的结果符合我们的要求。由于select的语法很复杂,这里就只介绍最基本的语法:

SELECT * FROM tablename [WHERE CONDITION]

  (1)查询不重复的记录

  有时需要将表中的记录去掉重复后显示出来,可以用distinct关键字来实现:

mysql> select ename,hiredate,sal,deptno1 from emp1;
+-------+------------+---------+---------+
| ename | hiredate   | sal     | deptno1 |
+-------+------------+---------+---------+
| zzx1  | 2000-01-01 | 4000.00 |       1 |
| dony  | NULL       | 1000.00 |    NULL |
+-------+------------+---------+---------+
2 rows in set (0.00 sec)

  select distinct deptno from emp;

  (2)条件查询

  在很多情况下,用户并不需要查询所有的记录,而只是需要根据限定条件来查询一部分数据,用where关键字可以来实现这样的操作。

  例如,查询所有deptno为1的记录:

mysql> select * from emp1 where deptno1=1;
+-------+-------+------------+---------+---------+
| ename | birth | hiredate   | sal     | deptno1 |
+-------+-------+------------+---------+---------+
| zzx1  | NULL  | 2000-01-01 | 4000.00 |       1 |
+-------+-------+------------+---------+---------+
1 row in set (0.04 sec)

  结果集中将符合条件的记录列出来。上面的例子中,where后面的条件是一个字段的“=”比较除了‘=’之外,还可以使用>,<,>=,<=,!=等比较运算符;多个条件之间还可以使用or,and等逻辑运算符进行多条件联合查询。

  以下是一个使用多字段条件查询的例子:

mysql>  select * from emp1 where deptno1=1 and sal<3000;
+-------+-------+------------+---------+---------+
| ename | birth | hiredate   | sal     | deptno1 |
+-------+-------+------------+---------+---------+
| zzx   | NULL  | 2000-01-01 | 2000.00 |       1 |
+-------+-------+------------+---------+---------+
1 row in set (0.00 sec)

  (3) 排序和限制

  我们经常会有这样的需求,取出按照某个字段进行排序后的记录结果集,这就用到了数据库的排序操作,用关键字ORDER BY来实现,语法如下:

SELECT * FROM tablename [WHERE CONDITION] [ORDER BY field1 [DESC|ASC],field2
[DESC|ASC],……fieldn [DESC|ASC]]

   其中,DESC和ASC是排序顺序的关键字,DESC表示按照字段进行降序排序,ASC则表示升序排列,如果不写此关键字默认是升序排列。ORDER BY后面可以跟多个不同的排序字段,并且每个排序字段可以有不同的排序顺序。

  例如把emp表中的记录按照工资高低进行显示:

mysql> select * from emp1 order by deptno1;
+-------+-------+------------+---------+---------+
| ename | birth | hiredate   | sal     | deptno1 |
+-------+-------+------------+---------+---------+
| dony  | NULL  | NULL       | 1000.00 |    NULL |
| zzx1  | NULL  | 2000-01-01 | 4000.00 |       1 |
| zzx   | NULL  | 2000-01-01 | 2000.00 |       1 |
+-------+-------+------------+---------+---------+
3 rows in set (0.06 sec)

  如果排序字段的值一样,则值相同的字段按照第二个排序字段进行排序,以此类推。如果只有一个排序字段,则这些字段相同的记录将会无序排列。

  对于排序后的记录,如果希望只显示一部分,而不是全部,这时,就可以使用LIMIT关键字来实现,LIMIT的语法如下:

SELECT ……[LIMIT offset_start,row_count]

  其中offset_start表示记录的起始偏移量,row_count表示显示的行数。

  在默认的情况下,起始偏移量为0,只需要写记录行数就可以,这时候,显示的实际就是前n条记录,看下面例子:

  例如,显示emp表中按照sal排序后的前2条记录:

mysql> select * from emp1 order by sal limit 2;
+-------+-------+------------+---------+---------+
| ename | birth | hiredate   | sal     | deptno1 |
+-------+-------+------------+---------+---------+
| dony  | NULL  | NULL       | 1000.00 |    NULL |
| zzx   | NULL  | 2000-01-01 | 2000.00 |       1 |
+-------+-------+------------+---------+---------+
2 rows in set (0.00 sec)

  limit经常和order by一起配合使用来进行记录的分页显示。

  (4)聚合。

  很多情况下,我们需要进行一些汇总操作,比如统计整个公司的人数或者统计每个部门的人数,这个时候就要用到SQL的聚合操作。

  聚合操作的语法如下:

SELECT [field1,field2,……fieldn] fun_name
FROM tablename
[WHERE where_contition]
[GROUP BY field1,field2,……fieldn
[WITH ROLLUP]]
[HAVING where_contition]

  对其参数进行以下说明。

  fun_name表示要做的聚合操作,也就是聚合函数,常用的有sum,count(*),max(),min()。

  group by关键字表示要进行分类聚合的字段,比如按照部门分类统计员工数量,部门就应该写在group by后面。

  with rollup是可选语法,表名是否对分类聚合后的结果进行再汇总。

  having关键字表示对分类后的结果再进行条件的过滤

  ***注意:having和where的区别在于having是对聚合后的结果进行条件的过滤,而where是在聚合前对记录进行过滤,如果逻辑允许,我们尽可能用where先过滤记录,这样因为结果集减少,将对聚合的效率大大提高,最后再根据逻辑看是否用having进行再过滤。

  例如,要emp表中统计公司的总人数:

  在此基础上,要统计各个部门的人数:

   统计人数大于1人的部门:

   最后统计公司所有员工的薪水总额,最高和最低薪水:

   (5)表连接

  当需要同时显示多个表中的字段时,就可以用表连接来实现这样的功能。

  从大类上分,表连接分为内连接和外连接,他们之间的最重要区别是内连接仅选出两张表中互相匹配的记录,而外连接会选出其他不匹配的记录。我们最常用的是内连接。

  例如,查询出所有雇员的名字和所在的部门名称,因为雇员名称和部门分别放在表emp和dept中,因此,需要使用表连接来进行查询:

   外连接有分为左连接和右连接,具体定义如下。

  左连接:包含所有的左边表中的记录甚至是右边表中没有和它匹配的记录

  右连接:包含所有的右边表中的记录甚至是左边表中没有和它匹配的记录

  (6) 子查询

  某些情况下,当我们查询的时候,需要的条件是另外一个select语句的结果,这个时候,就要用到子查询。用于子查询的关键字主要包括in, not in ,=, !=,exists, not exists等。如果子查询记录数唯一,还可以用=代替in。

 

二 mysql支持的数据类型

  2.1 数据类型

  mysql支持所有标准SQL中的数值类型,其中包括严格数据类型(INTEGER,SMALLINT,DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT, REAL和DOUBLE PRECISION),并在此基础上做了扩展。扩展后增加了TINYINT,MEDIUMINT和BIGINT这三种长度不同的整型,并增加了BIT类型,用来存放位数据,表中列出来Mysql5.0中支持的所有数值类型,其中INT是INTEGER的同名词,DEC是DECIMAL的同名词。

  在整数类型中,按照取值范围和存储方式不同,分为 tinyint、smallint、mediumint、int、bigint 这 5 个类型。如果超出类型范围的操作,会发生“Out of range”错误提示。为了避免此类问题的发生,在选择数据类型时要根据应用的实际情况确定其取值范围,最后根据确定的结果慎重选择数据类型。

  对于数据库,mysql还支持在类型名称后面的小括号内指定显示宽度,例如int(5)表示当前数值宽度小于5位的时候在数字后面填满宽度,如果不显示指定宽度则默认为int(11)。一般配合zerofill使用,就是用0填充的意思,数字位不够的空间用字符“0”充满。以下几个例子分别描述了填充前后的区别。

  (1)创建表t1,有id1和id2两个字段,指定其数值宽度分别为int和int(5)。

mysql> use test1;
Database changed
mysql> create table t1(id1 int,id2 int(5));
Query OK, 0 rows affected (0.07 sec)

mysql> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id1   | int(11) | YES  |     | NULL    |       |
| id2   | int(5)  | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.06 sec)

  (2) 在id1和id2中插入数值1,可以发现格式没有异常

mysql> select * from t1;
+------+------+
| id1  | id2  |
+------+------+
|    1 |    1 |
+------+------+
1 row in set (0.00 sec)

  (3)分别修改id1和id2的字段类型,假如zerofill参数:

mysql> alter table t1 modify id1 int zerofill;
Query OK, 1 row affected (0.10 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> alter table t1 modify id2 int(5) werofill;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'werofill' at line 1
mysql> alter table t1 modify id2 int(5) zerofill;
Query OK, 1 row affected (0.11 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+------------+-------+
| id1        | id2   |
+------------+-------+
| 0000000001 | 00001 |
+------------+-------+
1 row in set (0.00 sec)

  可以发现在数值前面用字符“0”填充了剩余的宽度。大家可能会有所疑问,设置了宽度之后,如果插入大于宽度限制的值,会不会截断或者插不进去而报错?答案肯定的:不会对插入的数据有任何的影响,还是按照类型的实际精度进行保存,这时,宽度格式已经没有实际意义,左边不会在填充任何的“0”字符。下面在表t1的字段id1中插入数值1,id2插入数值1111111,位数为7,大于id2的显示位数5,再观察一下测试结果:

mysql> insert into t1 values(1,1111111);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+------------+---------+
| id1        | id2     |
+------------+---------+
| 0000000001 |   00001 |
| 0000000001 | 1111111 |
+------------+---------+
2 rows in set (0.00 sec)

  很显然,id2中显示了正确的数值,并没有受宽度限制影响。

  所有的整数类型都有一个可选属性UNSIGNED(无符号),如果需要在字段里面保存非负数或者需要较大的上限值时,可以用此选项,他的取值范围是正常值得下限取0,上限取原值的2倍,例如tinyint有符号范围是-128----+127,而无符号范围是0---255.如果一个列指定为zerofill,则mysql自动为该列添加UNSIGNED属性。

  另外,整数类型还有一个属性:AUTO_INCREMENT值一般从1开始,每行增加1,在插入NULL到一个AUTO_INCREMENT列时,mysql插入一个比该列中当前最大值大1的值,一个表中最多只能有一个AUTO_INCREMENT列,对于任何想要使用AUTO_INCREMENT的列,应该定义为NOT NULL,并定义为PRIMARY或者为UNIQUE键。例如,可按下列任何一种方式定义AUTO_INCREMENT列:

CREATE TABLE AI (ID INT AUTO_INCREMENT NOT NULL PRIMARY KEY);
CREATE TABLE AI(ID INT AUTO_INCREMENT NOT NULL ,PRIMARY KEY(ID));
CREATE TABLE AI (ID INT AUTO_INCREMENT NOT NULL ,UNIQUE(ID));

  对于小数的表示,mysql分为两种方式:浮点数和定点数。浮点数包括float(单精度)和double(双精度),而顶点数则只有decimal一种表示。定点数在mysql内部以字符串形式存放,比浮点数更精确,适合用来表示货币等精度高的数据。

  浮点数和顶点数都可以用类型名称后“(M,D)”的方式来进行表示,“(M,D)”表示该值一共显示M位数字(整数位+小数位),其中D位位于小数点后面,M和D又称为精度和标度。例如,定义为float(7,4)的一个列可以显示为-999.9999.mysql保存值进行四舍五入,因此如果在float(7,4)列内插入999.00009,近似结果是999.0001.值得注意的是,浮点数后面跟“(M,D)”的用法是非标准用法,如果要用于数据库的迁移,则最好不要这么使用。float和double在不指定精度时,默认会按照实际的精度(由实际的硬件和操作系统决定)来显示,而decimal在不指定精度时,默认的整数位10,默认的小数为0.

  下面通过一个例子来比较float,double和decimal三者之间的不同。

  (1)创建测试表,分别将id1,id2,d3字段设置为float(5,2),double(5,2),decimal(5,2)

CREATE TABLE `t2` (
`id1` float(5,2) default NULL,
`id2` double(5,2) default NULL,
`id3` decimal(5,2) default NULL
)

  (2)往id1,id2和id3这三个字段中插入数据1.23.

CREATE TABLE `t2` (
`id1` float(5,2) default NULL,
`id2` double(5,2) default NULL,
`id3` decimal(5,2) default NULL
)
mysql> insert into t2 values(1.23,1.23,1.23);
Query OK, 1 row affected (0.03 sec)

mysql> select * from t2;
+------+------+------+
| id1  | id2  | id3  |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
+------+------+------+
1 row in set (0.00 sec)

  可以发现数据都正确的插入了表t2.

  (3)再向id1和id2字段中插入数据1.234,而id3字段中仍然插入1.23.

mysql> insert into t2 values(1.234,1.234,1.23);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t2;
+------+------+------+
| id1  | id2  | id3  |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
| 1.23 | 1.23 | 1.23 |
+------+------+------+
2 rows in set (0.00 sec)

  可以发现id1,id2,id3都插入了表t1,但是id1和id2由于标度的限制,舍去了最后一位,数据变成了1.23.

  (4)同时向id1,id2,id3字段中都插入数据1.234.

mysql> insert into t2 values(1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.05 sec)

mysql> show warnings;
+-------+------+------------------------------------------+
| Level | Code | Message                                  |
+-------+------+------------------------------------------+
| Note  | 1265 | Data truncated for column 'id3' at row 1 |
+-------+------+------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from t2;
+------+------+------+
| id1  | id2  | id3  |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
| 1.23 | 1.23 | 1.23 |
| 1.23 | 1.23 | 1.23 |
+------+------+------+
3 rows in set (0.00 sec)

  此时发现,虽然数据都插入进去,但是系统出现了一个warnings,报告id3被截断。如果是传统的SQLMode(下面会详细介绍SQLMode)下,这条记录是无法插入的。

  (5)将id1,id2, id3字段的精度和标度全部去掉,再次插入数据1.23。

mysql> alter table t2 modify id1 float;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table t2 modify id2 float;
Query OK, 3 rows affected (0.06 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> alter table t2 modify id double;
ERROR 1054 (42S22): Unknown column 'id' in 't2'
mysql> alter table t2 modify id2 double;
Query OK, 3 rows affected (0.05 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> alter table t2 modify id3 decimal;
Query OK, 3 rows affected, 3 warnings (0.05 sec)
Records: 3  Duplicates: 0  Warnings: 3

mysql> desc t2;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id1   | float         | YES  |     | NULL    |       |
| id2   | double        | YES  |     | NULL    |       |
| id3   | decimal(10,0) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+
3 rows in set (0.05 sec)

mysql> insert into t2 values(1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+------------------------------------------+
| Level | Code | Message                                  |
+-------+------+------------------------------------------+
| Note  | 1265 | Data truncated for column 'id3' at row 1 |
+-------+------+------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from t2;
+-------+--------------------+------+
| id1   | id2                | id3  |
+-------+--------------------+------+
|  1.23 | 1.2300000190734863 |    1 |
|  1.23 | 1.2300000190734863 |    1 |
|  1.23 | 1.2300000190734863 |    1 |
| 1.234 |              1.234 |    1 |
+-------+--------------------+------+
4 rows in set (0.00 sec)

  这时候可以看到id3字段的小数位被截断。

  这个例子验证了上面提到的浮点数如果不写精度和标度,则会按照实际精度值去显示,如果有精度和标度,则会将四舍五入的结果插入,系统不会出现报错;定点数如果不写精度和标度,则按照默认值decimal(10,0)来进行操作,,并且如果数据超越了精度和标度值,系统则会报错

   2.2 日期时间类型

  mysql中有多种数据类型可以用于日期和时间的表示,不同版本可能有所差异,表中列出了mysql5.0中所支持的日期和时间类型。

   这些数据类型的区别主要如下:

1.如果要用来表示年月日,通常用DATE来表示。
2.如果要表示年月日时分秒,通常用DATETIME来表示。
3.如果只用来表示时分秒,通常用TIME来表示
4.如果需要经常插入或者更新日期为当前系统时间,则通常使用TIMESTAMP来表示,TIMESTAMP 值返回后显示为“YYYY-MM-DD HH:MM:SS”格式的字符串,显示宽度固定
为 19 个字符。如果想要获得数字值,应在 TIMESTAMP 列添加+0。
5.如果只表示年份,可以用YEAR来表示,他比DATE占用更少的空间.YEAR有两位或4位格式的年。默认是4位格式。在4位格式中,允许的值是 1901~2155 和 0000。在
2 位格式中,允许的值是 70~69,表示从 1970~2069 年。MySQL 以 YYYY 格式显示 YEAR
值。

  从表中可以看出,每种日期时间类型都有一个有效的范围,如果超出这个范围,在默认的SQLmode下,系统会进行错误提示,并将以0值来进行存储,不同日期类型零值的表示如图:

  DATE,TIME和DATETIME是最长使用的3中日期类型,以下例子在3中类型字段插入了相同的日期值,看看他们的显示结果。

  首先创建表t3,字段分别是date,time, datetime三种数据类型:

 

mysql> create table t3(d date,t time,dt datetime);
Query OK, 0 rows affected (0.02 sec)

mysql> desc t3;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| d     | date     | YES  |     | NULL    |       |
| t     | time     | YES  |     | NULL    |       |
| dt    | datetime | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.01 sec)

 

  用now()函数插入当前日期:

mysql> insert into t3 values(now(),now(),now());
Query OK, 1 row affected, 1 warning (0.04 sec)

  查看显示结果:

mysql> select * from t3;
+------------+----------+---------------------+
| d          | t        | dt                  |
+------------+----------+---------------------+
| 2020-04-23 | 08:51:38 | 2020-04-23 08:51:38 |
+------------+----------+---------------------+
1 row in set (0.00 sec)

  显而易见,DATETIME是DATE和TIME的组合,用户可以根据不同的需要,来选择不同的,日期或时间类型以满足不同的应用。

  YEAR类型主要用来表示年份,当应用只需要记录年份时,用YEAR比DATE将更节省空间,下面的例子在表t5中定义了一个YEAR类型的字段,并插入一条记录:

 

mysql> create table t5 (y year);
Query OK, 0 rows affected (0.09 sec)

mysql> desc t5;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| y     | year(4) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.06 sec)

mysql> insert into t5 values(2100);
Query OK, 1 row affected (0.02 sec)

mysql> select * from t5;
+------+
| y    |
+------+
| 2100 |
+------+
1 row in set (0.00 sec)

 

  MySQL 以 YYYY 格式检索和显示 YEAR 值,范围是 1901~2155。当使用两位字符串表示年份时,其范围为“00”到“99”。

“00”-“69”范围是2000-2069范围的year值
“70”-“99”范围的值被转换为1970-1999范围的YEAR值

  2.3 字符串类型

  mysql中提供了多种对字符数据的存储类型,不同的版本可能有所差异,以5.0版本为例,mysql包括了char,varchar,binary,varbinary,blob,text,enum和set等多种字符串类型。

   

  

生前无需久睡,死后自会长眠,努力解决生活中遇到的各种问题,不畏将来,勇敢面对,加油,你是最胖的,哈哈哈
原文地址:https://www.cnblogs.com/panshao51km-cn/p/12737986.html