DBA DAY2
一、常用函数、
常用函数
按使用方式分类 | 按用途分类 |
○单行函数 ○分组函数 | ○字符函数 ○数学函数 ○日期函数 |
字符函数实例:
●LENGTH(str):返字符串长度,以字节为单位
mysql> select length('abc');
+---------------+
| length('abc') |
+---------------+
| 3 |
+---------------+
1 row in set (0.00 sec)
mysql> select length('你好');
+------------------+
| length('你好') |
+------------------+
| 6 |
+------------------+
1 row in set (0.00 sec)
mysql> select name, email, length(email) from employees where name='李平';
+--------+----------------+---------------+
| name | email | length(email) |
+--------+----------------+---------------+
| 李平 | liping@tedu.cn | 14 |
+--------+----------------+---------------+
1 row in set (0.00 sec)
●CHAR_LENGTH(str): 返回字符串长度,以字符为单位
mysql> select char_length('abc');
+--------------------+
| char_length('abc') |
+--------------------+
| 3 |
+--------------------+
1 row in set (0.00 sec)
mysql> select char_length('你好');
+-----------------------+
| char_length('你好') |
+-----------------------+
| 2 |
+-----------------------+
1 row in set (0.00 sec)
●CONCAT(s1,s2,...): 返回连接参数产生的字符串,一个或多个待拼接的内容,任意一个为NULL则返回值为NULL
# 拼接字符串
mysql> select concat(dept_id, '-', dept_name) from departments;
+---------------------------------+
| concat(dept_id, '-', dept_name) |
+---------------------------------+
| 1-人事部 |
| 2-财务部 |
| 3-运维部 |
| 4-开发部 |
| 5-测试部 |
| 6-市场部 |
| 7-销售部 |
| 8-法务部 |
+---------------------------------+
8 rows in set (0.00 sec)
●UPPER(str)和UCASE(str): 将字符串中的字母全部转换成大写
mysql> select name, upper(email) from employees where name like '李%';
+-----------+----------------------+
| name | upper(email) |
+-----------+----------------------+
| 李玉英 | LIYUYING@TEDU.CN |
| 李平 | LIPING@TEDU.CN |
| 李建华 | LIJIANHUA@TARENA.COM |
| 李莹 | LIYING@TEDU.CN |
| 李柳 | LILIU@TARENA.COM |
| 李慧 | LIHUI@TARENA.COM |
| 李静 | LIJING@TARENA.COM |
| 李瑞 | LIRUI@TARENA.COM |
+-----------+----------------------+
8 rows in set (0.00 sec)
●LOWER(str)和LCASE(str):将str中的字母全部转换成小写
# 转小写
mysql> select lower('HelloWorld');
+---------------------+
| lower('HelloWorld') |
+---------------------+
| helloworld |
+---------------------+
1 row in set (0.00 sec)
●SUBSTR(s, start, length): 从子符串s的start位置开始,取出length长度的子串,位置从1开始计算
mysql> select substr('hello world', 7);
+--------------------------+
| substr('hello world', 7) |
+--------------------------+
| world |
+--------------------------+
1 row in set (0.00 sec)
# 取子串,下标从7开始取出3个
mysql> select substr('hello world', 7, 3);
+-----------------------------+
| substr('hello world', 7, 3) |
+-----------------------------+
| wor |
+-----------------------------+
1 row in set (0.00 sec)
●INSTR(str,str1):返回str1参数,在str参数内的位置
# 子串在字符串中的位置
mysql> select instr('hello world', 'or');
+----------------------------+
| instr('hello world', 'or') |
+----------------------------+
| 8 |
+----------------------------+
1 row in set (0.00 sec)
mysql> select instr('hello world', 'ol');
+----------------------------+
| instr('hello world', 'ol') |
+----------------------------+
| 0 |
+----------------------------+
1 row in set (0.00 sec)
●TRIM(s): 返回字符串s删除了两边空格之后的字符串
mysql> select trim(' hello world. ');
+--------------------------+
| trim(' hello world. ') |
+--------------------------+
| hello world. |
+--------------------------+
1 row in set (0.00 sec)
数学函数实例
●ABS(x):返回x的绝对值
mysql> select abs(-10);
+----------+
| abs(-10) |
+----------+
| 10 |
+----------+
1 row in set (0.00 sec)
●PI(): 返回圆周率π,默认显示6位小数
mysql> select pi();
+----------+
| pi() |
+----------+
| 3.141593 |
+----------+
1 row in set (0.00 sec)
●MOD(x,y): 返回x被y除后的余数
mysql> select mod(10, 3);
+------------+
| mod(10, 3) |
+------------+
| 1 |
+------------+
1 row in set (0.00 sec)
●CEIL(x)、CEILING(x): 返回不小于x的最小整数
mysql> select ceil(10.1);
+------------+
| ceil(10.1) |
+------------+
| 11 |
+------------+
1 row in set (0.00 sec)
●FLOOR(x): 返回不大于x的最大整数
mysql> select floor(10.9);
+-------------+
| floor(10.9) |
+-------------+
| 10 |
+-------------+
1 row in set (0.00 sec)
●ROUND(x)、ROUND(x,y): 前者返回最接近于x的整数,即对x进行四舍五入;后者返回最接近x的数,其值保留到小数点后面y位,若y为负值,则将保留到x到小数点左边y位
mysql> select round(10.6666);
+----------------+
| round(10.6666) |
+----------------+
| 11 |
+----------------+
1 row in set (0.00 sec)
mysql> select round(10.6666, 2);
+-------------------+
| round(10.6666, 2) |
+-------------------+
| 10.67 |
+-------------------+
1 row in set (0.00 sec)
日期和时间函数实例
●CURDATE()、CURRENT_DATE(): 将当前日期按照"YYYY-MM-DD"或者"YYYYMMDD"格式的值返回,具体格式根据函数用在字符串或是数字语境中而定
mysql> select curdate();
+------------+
| curdate() |
+------------+
| 2021-03-09 |
+------------+
1 row in set (0.00 sec)
mysql> select curdate() + 0;
+---------------+
| curdate() + 0 |
+---------------+
| 20210309 |
+---------------+
1 row in set (0.00 sec)
●NOW(): 返回当前日期和时间值,格式为"YYYY_MM-DD HH:MM:SS"或"YYYYMMDDHHMMSS",具体格式根据函数用在字符串或数字语境中而定
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2021-03-09 02:28:26 |
+---------------------+
1 row in set (0.00 sec)
mysql> select now() + 0;
+----------------+
| now() + 0 |
+----------------+
| 20210309022848 |
+----------------+
1 row in set (0.00 sec)
●UNIX_TIMESTAMP()、UNIX_TIMESTAMP(date): 前者返回一个格林尼治标准时间1970-01-01 00:00:00到现在的秒数,后者返回一个格林尼治标准时间1970-01-01 00:00:00到指定时间的秒数
mysql> select unix_timestamp();
+------------------+
| unix_timestamp() |
+------------------+
| 1615275274 |
+------------------+
1 row in set (0.00 sec)
●FROM_UNIXTIME(date): 和UNIX_TIMESTAMP互为反函数,把UNIX时间戳转换为普通格式的时间
mysql> select from_unixtime(0);
+---------------------+
| from_unixtime(0) |
+---------------------+
| 1969-12-31 19:00:00 |
+---------------------+
1 row in set (0.00 sec)
●MONTH(date)和MONTHNAME(date):前者返回指定日期中的月份,后者返回指定日期中的月份的名称
mysql> select month('20211001120000');
+-------------------------+
| month('20211001120000') |
+-------------------------+
| 10 |
+-------------------------+
1 row in set (0.00 sec)
mysql> select monthname('20211001120000');
+-----------------------------+
| monthname('20211001120000') |
+-----------------------------+
| October |
+-----------------------------+
1 row in set (0.00 sec)
●DAYNAME(d)、DAYOFWEEK(d)、WEEKDAY(d): DAYNAME(d)返回d对应的工作日的英文名称,如Sunday、Monday等;DAYOFWEEK(d)返回的对应一周中的索引,1表示周日、2表示周一;WEEKDAY(d)表示d对应的工作日索引,0表示周一,1表示周二
mysql> select dayname('20211001120000');
+---------------------------+
| dayname('20211001120000') |
+---------------------------+
| Friday |
+---------------------------+
1 row in set (0.00 sec)
mysql> select dayname('20211001');
+---------------------+
| dayname('20211001') |
+---------------------+
| Friday |
+---------------------+
1 row in set (0.00 sec)
●WEEK(d): 计算日期d是一年中的第几周
mysql> select week('20211001');
+------------------+
| week('20211001') |
+------------------+
| 39 |
+------------------+
1 row in set (0.00 sec)
●DAYOFYEAR(d)、DAYOFMONTH(d): 前者返回d是一年中的第几天,后者返回d是一月中的第几天
mysql> select dayofyear('20211001');
+-----------------------+
| dayofyear('20211001') |
+-----------------------+
| 274 |
+-----------------------+
1 row in set (0.00 sec)
●YEAR(date)、QUARTER(date)、MINUTE(time)、SECOND(time): YEAR(date)返回指定日期对应的年份,范围是1970到2069;QUARTER(date)返回date对应一年中的季度,范围是1到4;
mysql> select year('20211001');
+------------------+
| year('20211001') |
+------------------+
| 2021 |
+------------------+
1 row in set (0.00 sec)
mysql> select quarter('20211001');
+---------------------+
| quarter('20211001') |
+---------------------+
| 4 |
+---------------------+
1 row in set (0.00 sec)
MINUTE(time)返回time对应的分钟数,范围是0~59;SECOND(time)返回制定时间的秒值
mysql> select year('20211001');
+------------------+
| year('20211001') |
+------------------+
| 2021 |
+------------------+
1 row in set (0.00 sec)
mysql> select quarter('20211001');
+---------------------+
| quarter('20211001') |
+---------------------+
| 4 |
+---------------------+
1 row in set (0.00 sec)
流程控制函数实例
●IF(expr,v1,v2): 如果expr是TRUE则返回v1,否则返回v2
mysql> select if(3>0, 'yes', 'no');
+----------------------+
| if(3>0, 'yes', 'no') |
+----------------------+
| yes |
+----------------------+
1 row in set (0.00 sec)
mysql> select name, dept_id, if(dept_id=1, '人事部', '非人事部') from employees where name='张亮';
+--------+---------+--------------------------------------------+
| name | dept_id | if(dept_id=1, '人事部', '非人事部') |
+--------+---------+--------------------------------------------+
| 张亮 | 7 | 非人事部 |
+--------+---------+--------------------------------------------+
1 row in set (0.00 sec)
●IFNULL(v1,v2): 如果v1不为NULL,则返回v1,否则返回v2
mysql> select dept_id, dept_name, ifnull(dept_name, '未设置') from departments;
+---------+-----------+--------------------------------+
| dept_id | dept_name | ifnull(dept_name, '未设置') |
+---------+-----------+--------------------------------+
| 1 | 人事部 | 人事部 |
| 2 | 财务部 | 财务部 |
| 3 | 运维部 | 运维部 |
| 4 | 开发部 | 开发部 |
| 5 | 测试部 | 测试部 |
| 6 | 市场部 | 市场部 |
| 7 | 销售部 | 销售部 |
| 8 | 法务部 | 法务部 |
+---------+-----------+--------------------------------+
8 rows in set (0.00 sec)
mysql> insert into departments(dept_id) values(9);
mysql> select dept_id, dept_name, ifnull(dept_name, '未设置') from departments;
+---------+-----------+--------------------------------+
| dept_id | dept_name | ifnull(dept_name, '未设置') |
+---------+-----------+--------------------------------+
| 1 | 人事部 | 人事部 |
| 2 | 财务部 | 财务部 |
| 3 | 运维部 | 运维部 |
| 4 | 开发部 | 开发部 |
| 5 | 测试部 | 测试部 |
| 6 | 市场部 | 市场部 |
| 7 | 销售部 | 销售部 |
| 8 | 法务部 | 法务部 |
| 9 | NULL | 未设置 |
+---------+-----------+--------------------------------+
9 rows in set (0.00 sec)
●CASE expr WHEN v1 THEN r1 [WHEN v2 THEN v2] [ELSE rn] END: 如果expr等于某个vn,则返回对应位置THEN后面的结果,如果与所有值都不想等,则返回ELSE后面的rn
mysql> select dept_id, dept_name,
-> case dept_name
-> when '运维部' then '技术部门'
-> when '开发部' then '技术部门'
-> when '测试部' then '技术部门'
-> when null then '未设置'
-> else '非技术部门'
-> end as '部门类型'
-> from departments;
+---------+-----------+-----------------+
| dept_id | dept_name | 部门类型 |
+---------+-----------+-----------------+
| 1 | 人事部 | 非技术部门 |
| 2 | 财务部 | 非技术部门 |
| 3 | 运维部 | 技术部门 |
| 4 | 开发部 | 技术部门 |
| 5 | 测试部 | 技术部门 |
| 6 | 市场部 | 非技术部门 |
| 7 | 销售部 | 非技术部门 |
| 8 | 法务部 | 非技术部门 |
| 9 | NULL | 非技术部门 |
+---------+-----------+-----------------+
9 rows in set (0.00 sec)
mysql> select dept_id, dept_name,
-> case
-> when dept_name='运维部' then '技术部门'
-> when dept_name='开发部' then '技术部门'
-> when dept_name='测试部' then '技术部门'
-> when dept_name is null then '未设置'
-> else '非技术部门'
-> end as '部门类型'
-> from departments;
+---------+-----------+-----------------+
| dept_id | dept_name | 部门类型 |
+---------+-----------+-----------------+
| 1 | 人事部 | 非技术部门 |
| 2 | 财务部 | 非技术部门 |
| 3 | 运维部 | 技术部门 |
| 4 | 开发部 | 技术部门 |
| 5 | 测试部 | 技术部门 |
| 6 | 市场部 | 非技术部门 |
| 7 | 销售部 | 非技术部门 |
| 8 | 法务部 | 非技术部门 |
| 9 | NULL | 未设置 |
+---------+-----------+-----------------+
9 rows in set (0.00 sec)
分组函数
用于统计,又称为聚合函数或统计函数
●sum() :求和
mysql> select employee_id, sum(basic+bonus) from salary where employee_id=10 and year(date)=2018;
+-------------+------------------+
| employee_id | sum(basic+bonus) |
+-------------+------------------+
| 10 | 116389 |
+-------------+------------------+
1 row in set (0.00 sec)
- avg() :求平均值
mysql> select employee_id, avg(basic+bonus) from salary where employee_id=10 and year(date)=2018;
+-------------+------------------+
| employee_id | avg(basic+bonus) |
+-------------+------------------+
| 10 | 29097.2500 |
+-------------+------------------+
1 row in set (0.00 sec)
max() :求最大值
mysql> select employee_id, max(basic+bonus) from salary where employee_id=10 and year(date)=2018;
+-------------+------------------+
| employee_id | max(basic+bonus) |
+-------------+------------------+
| 10 | 31837 |
+-------------+------------------+
1 row in set (0.00 sec)
- min() :求最小值
mysql> select employee_id, min(basic+bonus) from salary where employee_id=10 and year(date)=2018;
+-------------+------------------+
| employee_id | min(basic+bonus) |
+-------------+------------------+
| 10 | 24837 |
+-------------+------------------+
1 row in set (0.00 sec)
- count() :计算个数
mysql> select count(*) from departments;
+----------+
| count(*) |
+----------+
| 9 |
+----------+
1 row in set (0.00 sec)
二、处理查询结果
分组查询
- 在对数据表中数据进行统计时,可能需要按照一定的类别分别进行统计。比如查询每个部门的员工数。
- 使用GROUP BY按某个字段,或者多个字段中的值,进行分组,字段中值相同的为一组
语法格式
- 查询列表必须是分组函数和出现在GROUP BY后面的字段
- 通常而言,分组前的数据筛选放在where子句中,分组后的数据筛选放在having子句中
SELECT 字段名1(要求出现在group by后面),分组函数(),……
FROM 表名
WHERE 条件
GROUP BY 字段名1,字段名2
HAVING 过滤条件
ORDER BY 字段;#注意注意,where在分组前删选,having在分组后过滤。
应用实例
- 查询每个部门的人数
mysql> select dept_id, count(*) from employees group by dept_id;
+---------+----------+
| dept_id | count(*) |
+---------+----------+
| 1 | 8 |
| 2 | 5 |
| 3 | 6 |
| 4 | 55 |
| 5 | 12 |
| 6 | 9 |
| 7 | 35 |
| 8 | 3 |
+---------+----------+
8 rows in set (0.00 sec)
- 查询每个部门中年龄最大的员工
mysql> select dept_id, min(birth_date) from employees group by dept_id;
+---------+-----------------+
| dept_id | min(birth_date) |
+---------+-----------------+
| 1 | 1971-08-19 |
| 2 | 1971-11-02 |
| 3 | 1971-09-09 |
| 4 | 1972-01-31 |
| 5 | 1971-08-14 |
| 6 | 1973-04-14 |
| 7 | 1971-12-10 |
| 8 | 1989-05-19 |
+---------+-----------------+
8 rows in set (0.00 sec)
- 查询每个部门入职最晚员工的入职时间
mysql> select dept_id, max(hire_date) from employees group by dept_id;
+---------+----------------+
| dept_id | max(hire_date) |
+---------+----------------+
| 1 | 2018-11-21 |
| 2 | 2018-09-03 |
| 3 | 2019-07-04 |
| 4 | 2021-02-04 |
| 5 | 2019-06-08 |
| 6 | 2017-10-07 |
| 7 | 2020-08-21 |
| 8 | 2019-11-14 |
+---------+----------------+
8 rows in set (0.00 sec)
- 统计各部门使用qq.com邮箱的员工人数
mysql> select dept_id, count(*) from employees where email like '%@qq.com' group by dept_id;
+---------+----------+
| dept_id | count(*) |
+---------+----------+
| 1 | 5 |
| 2 | 2 |
| 3 | 4 |
| 4 | 32 |
| 5 | 7 |
| 6 | 5 |
| 7 | 15 |
| 8 | 1 |
+---------+----------+
8 rows in set (0.00 sec)
- 查看员工2018年工资总收入,按总收入进行降序排列
-
mysql> select employee_id, sum(basic+bonus) as total from salary where year(date)=2018 group by employee_id order by total desc;
- 查询部门人数少于10人
-
mysql> select dept_id, count(*) from employees where count(*)<10 group by dept_id; ERROR 1111 (HY000): Invalid use of group function mysql> select dept_id, count(*) from employees group by dept_id having count(*)<10; +---------+----------+ | dept_id | count(*) | +---------+----------+ | 1 | 8 | | 2 | 5 | | 3 | 6 | | 6 | 9 | | 8 | 3 | +---------+----------+ 5 rows in set (0.00 sec)
连接查询
- 也叫多表查询。常用于查询字段来自于多张表
- 如果直接查询两张表,将会得到笛卡尔积
mysql> select name, dept_name from employees, departments;
- 通过添加有效的条件可以进行查询结果的限定
-
mysql> select name, dept_name from employees, departments where employees.dept_id=departments.dept_id;
-
连接分类
-
按功能分类
- 内连接(重要)
-
- 等值连接
- 非等值连接
- 自连接
- 外连接
-
- 左外连接(重要)
- 右外连接(重要)
- 全外连接(mysql不支持,可以使用UNION实现相同的效果)
- 交叉连接
按年代分类
- SQL92标准:仅支持内连接
- SQL99标准:支持所功能的连接
- #时代在快速发展,技术更新换代速度快,现在用的都是新的99标准,毕竟人类社会是进步发展的,不可能越生活越倒退。
SQL99标准多表查询
● 语法格式
SELECT 字段... #表的表头字段
FROM 表1 [AS] 别名 [连接类型]
JOIN 表2 [AS] 别名
ON 连接条件 #连接第二、三张表
WHERE 分组前筛选条件
GROUP BY 分组
HAVING 分组后筛选条件
ORDER BY 排序字段#别名很好用,用于 一张表名字太长时,简写使用。它再怎么命名都还是原来的那张表,仅仅是换了个称呼。
内连接
● 语法格式
select 查询列表
from 表1 别名
inner join 表2 别名on 连接条件
inner join 表3 别名on 连接条件
[where 筛选条件]
[group by 分组]
[having 分组后筛选]
[order by 排序列表]
等值连接 #用于两边一起联合查询,通过相同的字段名称相连接。
- 查询每个员工所在的部门名
mysql> select name, dept_name
-> from employees
-> inner join departments
-> on employees.dept_id=departments.dept_id;
- 查询每个员工所在的部门名,使用别名
mysql> select name, dept_name
-> from employees as e
-> inner join departments as d
-> on e.dept_id=d.dept_id;
查询11号员工的名字及2018年每个月工资
mysql> select name, date, basic+bonus as total
-> from employees as e
-> inner join salary as s
-> on e.employee_id=s.employee_id
-> where year(s.date)=2018 and e.employee_id=11;
非等值连接
#使用场景不多,生产环境大多数是使用等值连接,表多了不用等值连接,脑瓜子都是翁翁的。
附:创建工资级别表
创建表语法:
创建工资级别表:
- id:主键。仅作为表的行号
- grade:工资级别,共ABCDE五类
- low:该级别最低工资
- high:该级别最高工资
向表中插入数据:
- 向wage_grade表中插入五行数据:
- CREATE TABLE 表名称
(
列名称1 数据类型,
列名称2 数据类型,
列名称3 数据类型,
....
)
具体写法
mysql> use tarena;
mysql> create table wage_grade
-> (
-> id int,
-> grade char(1),
-> low int,
-> high int,
-> primary key (id));
- 查询2018年12月员工基本工资级别
-
mysql> select employee_id, date, basic, grade -> from salary as s -> inner join wage_grade as g -> on s.basic between g.low and g.high -> where year(date)=2018 and month(date)=12;
- 查询2018年12月员工各基本工资级别的人数
-
mysql> select name, date, basic, grade -> from employees as e -> inner join salary as s -> on e.employee_id=s.employee_id -> inner join wage_grade as g -> on s.basic between g.low and g.high -> where year(date)=2018 and month(date)=12;
自连接
-
● 要点:
-
○ 将一张表作为两张使用
-
○ 每张表起一个别名
-
● 查看哪些员的生日月份与入职月份相同
mysql> select e.name, e.hire_date, em.birth_date
-> from employees as e
-> inner join employees as em
-> on month(e.hire_date)=month(em.birth_date)
-> and e.employee_id=em.employee_id;
+-----------+------------+------------+
| name | hire_date | birth_date |
+-----------+------------+------------+
| 李玉英 | 2012-01-19 | 1974-01-25 |
| 郑静 | 2018-02-03 | 1997-02-14 |
| 林刚 | 2007-09-19 | 1990-09-23 |
| 刘桂兰 | 2003-10-14 | 1982-10-11 |
| 张亮 | 2015-08-10 | 1996-08-25 |
| 许欣 | 2011-09-09 | 1982-09-25 |
| 王荣 | 2019-11-14 | 1999-11-22 |
+-----------+------------+------------+
7 rows in set (0.00 sec)
外连接
● 常用于查询一个表中有,另一个表中没有的记录
● 如果从表中有和它匹配的,则显示匹配的值
● 如要从表中没有和它匹配的,则显示NULL
● 外连接查询结果=内连接查询结果+主表中有而从表中没有的记录
● 左外连接中,left join左边的是主表
● 右外连接中,right join右边的是主表
● 左外连接和右外连接可互换,实现相同的目标
左外连接
SELECT tb1.字段..., tb2.字段
FROM table1 AS tb1
LEFT OUTER JOIN table2 AS tb2
ON tb1.字段=tb2.字段
- 查询所有部门的人员以及没有员工的部门
mysql> select d.*, e.name
-> from departments as d
-> left outer join employees as e
-> on d.dept_id=e.dept_id;
右外连接
查询所有部门的人员以及没有员工的部门
mysql> select d.*, e.name
-> from employees as e
-> right outer join departments as d
-> on d.dept_id=e.dept_id;
交叉连接
SELECT <字段名>
FROM <表1>
CROSS JOIN <表2>
[WHERE子句]
- 查询员工表和部门表的笛卡尔积
mysql> select name, dept_name
-> from employees
-> cross join departments;
三、管理表记录
插入表记录
查看表头
mysql> desc tarena.user;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | char(20) | YES | | NULL | |
| password | char(1) | YES | | NULL | |
| uid | int | YES | | NULL | |
| gid | int | YES | | NULL | |
| comment | varchar(50) | YES | | NULL | |
| homedir | varchar(80) | YES | | NULL | |
| shell | char(30) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
插入1条记录给所有表头赋值
mysql> insert into tarena.user values(40,"jingyaya","x",1001,1001,"teacher","/home/jingyaya","/bin/bash");
Query OK, 1 row affected (0.05 sec)
id表头的值不能重复,字段太多可以分行写。
再次查看效果
select * from tarena.user where name="jingyaya";
插入多行记录给所有列赋值
insert into tarena.user values
(41,"jingyaya2","x",1002,1002,"teacher","/home/jingyaya2","/bin/bash"),
(42,"jingyaya3","x",1003,1003,"teacher","/home/jingyaya3","/bin/bash");
插入1行给指定列赋值,必须写列名,没赋值的列 没有数据 值是NULL
-
mysql> insert into tarena.user(name,uid,shell)values("benben",1002,"/sbin/nologin");
插入多行给指定列赋值,必须写列名,没赋值的列 没有数据 值是NULL
-
mysql> insert into tarena.user(name,uid,shell)values("benben2",1002,"/sbin/nologin"),("benben3",1003,"/sbin/nologin");
查看记录
-
mysql> select * from tarena.user where name like "benben%"; +----+---------+----------+------+------+---------+---------+---------------+ | id | name | password | uid | gid | comment | homedir | shell | +----+---------+----------+------+------+---------+---------+---------------+ | 41 | benben | NULL | 1002 | NULL | NULL | NULL | /sbin/nologin | | 42 | benben2 | NULL | 1002 | NULL | NULL | NULL | /sbin/nologin | | 43 | benben3 | NULL | 1003 | NULL | NULL | NULL | /sbin/nologin | +----+---------+----------+------+------+---------+---------+---------------+ 3 rows in set (0.00 sec)
使用select查询结果赋值(查询表头个数和 插入记录表头个数要一致)
-
mysql> select user from mysql.user; +------------------+ | user | +------------------+ | mysql.infoschema | | mysql.session | | mysql.sys | | root | +------------------+ 4 rows in set (0.00 sec) mysql> insert into tarena.user(name) (select user from mysql.user); Query OK, 4 rows affected (0.09 sec) Records: 4 Duplicates: 0 Warnings: 0
查看插入后的数据
-
mysql> select * from tarena.user where name like "mysql%" or name="root"; +----+------------------+----------+------+------+--------------+----------------+------------+ | id | name | password | uid | gid | comment | homedir | shell | +----+------------------+----------+------+------+--------------+----------------+------------+ | 1 | root | x | 0 | 0 | root | /root | /bin/bash | | 26 | mysql | x | 27 | 27 | MySQL Server | /var/lib/mysql | /bin/false | | 44 | mysql.infoschema | NULL | NULL | NULL | NULL | NULL | NULL | | 45 | mysql.session | NULL | NULL | NULL | NULL | NULL | NULL | | 46 | mysql.sys | NULL | NULL | NULL | NULL | NULL | NULL | | 47 | root | NULL | NULL | NULL | NULL | NULL | NULL | +----+------------------+----------+------+------+--------------+----------------+------------+ 6 rows in set (0.00 sec)
使用set命令赋值
-
mysql> insert into tarena.user set name="yaya" , uid=99 , gid=99 ; Query OK, 1 row affected (0.06 sec) mysql> select * from tarena.user where name="yaya"; +----+------+----------+------+------+---------+---------+-------+ | id | name | password | uid | gid | comment | homedir | shell | +----+------+----------+------+------+---------+---------+-------+ | 28 | yaya | NULL | 99 | 99 | NULL | NULL | NULL | +----+------+----------+------+------+---------+---------+-------+ 1 row in set (0.00 sec)
修改表记录
修改前查看 #查看都是看效果
-
mysql> select name , comment from tarena.user where id <= 10 ; +----------+----------+ | name | comment | +----------+----------+ | root | root | | bin | bin | | daemon | daemon | | adm | adm | | lp | lp | | sync | sync | | shutdown | shutdown | | halt | halt | | mail | mail | | operator | operator | +----------+----------+ 10 rows in set (0.00 sec)
仅仅修改符合条件的
-
mysql> update tarena.user set comment=NULL where id <= 10 ; Query OK, 10 rows affected (0.09 sec) Rows matched: 10 Changed: 10 Warnings: 0
修改后查看
-
mysql> select name , comment from tarena.user where id <= 10 ; +----------+---------+ | name | comment | +----------+---------+ | root | NULL | | bin | NULL | | daemon | NULL | | adm | NULL | | lp | NULL | | sync | NULL | | shutdown | NULL | | halt | NULL | | mail | NULL | | operator | NULL | +----------+---------+ 10 rows in set (0.00 sec) [root@localhost ~]#
修改前查看
-
mysql> select name , homedir from tarena.user; +------------------+--------------------+ | name | homedir | +------------------+--------------------+ | root | /root | | bin | /bin | | daemon | /sbin | | adm | /var/adm | | lp | /var/spool/lpd | | sync | /sbin | | shutdown | /sbin | | halt | /sbin | | mail | /var/spool/mail | | operator | /root | | games | /usr/games | | ftp | /var/ftp | | nobody | / | | systemd-network | / | | dbus | / | | polkitd | / | | sshd | /var/empty/sshd | | postfix | /var/spool/postfix | | chrony | /var/lib/chrony | | rpc | /var/lib/rpcbind | | rpcuser | /var/lib/nfs | | nfsnobody | /var/lib/nfs | | haproxy | /var/lib/haproxy | | plj | /home/plj | | apache | /usr/share/httpd | | mysql | /var/lib/mysql | | bob | NULL | | jerrya | NULL | | jingyaya | /home/jingyaya | | benben | NULL | | benben2 | NULL | | benben3 | NULL | | mysql.infoschema | NULL | | mysql.session | NULL | | mysql.sys | NULL | | root | NULL | +------------------+--------------------+ 36 rows in set (0.00 sec)
不加条件批量修改
mysql> update tarena.user set homedir="/student" ;
Query OK, 36 rows affected (0.09 sec)
Rows matched: 36 Changed: 36 Warnings: 0
修改后查看
mysql> select name , homedir from tarena.user;
+------------------+----------+
| name | homedir |
+------------------+----------+
| root | /student |
| bin | /student |
| daemon | /student |
| adm | /student |
| lp | /student |
| sync | /student |
| shutdown | /student |
| halt | /student |
| mail | /student |
| operator | /student |
| games | /student |
| ftp | /student |
| nobody | /student |
| systemd-network | /student |
| dbus | /student |
| polkitd | /student |
| sshd | /student |
| postfix | /student |
| chrony | /student |
| rpc | /student |
| rpcuser | /student |
| nfsnobody | /student |
| haproxy | /student |
| plj | /student |
| apache | /student |
| mysql | /student |
| bob | /student |
| jerrya | /student |
| jingyaya | /student |
| benben | /student |
| benben2 | /student |
| benben3 | /student |
| mysql.infoschema | /student |
| mysql.session | /student |
| mysql.sys | /student |
| root | /student |
+------------------+----------+
36 rows in set (0.00 sec)
删除表记录
#生产环境用的操作较少,一般员工没权限。
删除前查看
-
mysql> select * from tarena.user where id <= 10 ; +----+----------+----------+------+------+---------+----------+----------------+ | id | name | password | uid | gid | comment | homedir | shell | +----+----------+----------+------+------+---------+----------+----------------+ | 1 | root | x | 0 | 0 | NULL | /student | /bin/bash | | 2 | bin | x | 1 | 1 | NULL | /student | /sbin/nologin | | 3 | daemon | x | 2 | 2 | NULL | /student | /sbin/nologin | | 4 | adm | x | 3 | 4 | NULL | /student | /sbin/nologin | | 5 | lp | x | 4 | 7 | NULL | /student | /sbin/nologin | | 6 | sync | x | 5 | 0 | NULL | /student | /bin/sync | | 7 | shutdown | x | 6 | 0 | NULL | /student | /sbin/shutdown | | 8 | halt | x | 7 | 0 | NULL | /student | /sbin/halt | | 9 | mail | x | 8 | 12 | NULL | /student | /sbin/nologin | | 10 | operator | x | 11 | 0 | NULL | /student | /sbin/nologin | +----+----------+----------+------+------+---------+----------+----------------+ 10 rows in set (0.00 sec)
仅删除与条件匹配的行
- mysql> delete from tarena.user where id <= 10 ;
- Query OK, 10 rows affected (0.06 sec)
查不到符合条件就OK
- mysql> select * from tarena.user where id <= 10 ;
- Empty set (0.00 sec)
DBA Day3
一、表管理
良好的数据库设计表现在以下几方面:
- 访问效率高
- 减少数据冗余,节省存储空间,便于进一步扩展
- 可以使应用程序的开发变得更容易
关系数据库的规范化理论为:关系数据库中的每一个关系都要满足一定的规范。根据满足规范的条件不同,可以分为6个等级:第一范式(1NF)、第二范式(2NF)……第五范式(5NF)。其中,NF是Normal Form的缩写。一般情况下,只要把数据规范到第三范式标准就可以满足需要了。
第一范式(1NF)
在一个关系中,消除重复字段,且各字段都是最小的逻辑存储单位。即,要满足原子性。
- 第一范式是第二和第三范式的基础,是最基本的范式。第一范式包括下列指导原则。
(1)数据组的每个属性只可以包含一个值。
(2)关系中的每个数组必须包含相同数量的值。
(3)关系中的每个数组一定不能相同。 - 在任何一个关系数据库中,第一范式是对关系模式的基本要求,不满足第一范式的数据库就不是关系型数据库。
第二范式(2NF)
- 第二范式是在第一范式的基础上建立起来的,即满足第二范式必先满足第一范式(1NF)。
- 第二范式要求数据库表中的每个实体(即各个记录行)必须可以被唯一地区分。
- 为实现区分各行记录通常需要为表设置一个“区分列”,用以存储各个实体的唯一标识。这个唯一属性列被称为主关键字或主键。
- 第二范式要求实体的属性完完全依赖于主关键字,即不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。
第三范式(3NF)
- 第三范式是在第二范式的基础上建立起来的,即满足第三范式必先满足第二范式。
- 第三范式要求关系表不存在非关键字列对任意候选关键字列的传递函数依赖,也就是说,第三范式要求一个关系表中不包含已在其他表中包含的非主关键字信息。
- 除主键外,其他字段必须依赖主键。
语法格式:
CREATE TABLE 表名称
(
列名称1 数据类型 [(长度) 约束],
列名称2 数据类型 [(长度) 约束],
列名称3 数据类型 [(长度) 约束],
....
)
步骤一:建库练习
库名命名规则:
仅可以使用数字、字母、下划线、不能纯数字
区分字母大小写,
具有唯一性
不可使用MySQL命令或特殊字符
库名区分字母大小写
mysql> create database gamedb ;
Query OK, 1 row affected (0.14 sec)
mysql> create database GAMEDB ;
Query OK, 1 row affected (0.08 sec)
mysql> create database GAMEDB ;
ERROR 1007 (HY000): Can't create database 'GAMEDB'; database exists //重名报错
加if not exists 命令避免重名报错
-
mysql> create database if not exists gamedb ; Query OK, 1 row affected, 1 warning (0.03 sec) //正常
查看创建的库
-
mysql> show databases; +--------------------+ | Database | +--------------------+ | GAMEDB | | gamedb | | information_schema | | mysql | | performance_schema | | sys | | tarena | +--------------------+ 7 rows in set (0.00 sec)
//删除库 #仅练习环境使用 (*´▽`)ノノ
#删库跑路是不可能的,小员工,小技术员没权限和胆子。即使你有,数据库的数据价值量巨大,删了也只能去吃大碗牢饭,。。。
- mysql> drop database gamedb;
- Query OK, 0 rows affected (0.11 sec)
// 删除没有的库报错
- mysql> drop database gamedb;
- ERROR 1008 (HY000): Can’t drop database ‘gamedb’; database doesn’t exist
//加if exists 删除没有的库,也不报错
- mysql> drop database if exists gamedb;
- Query OK, 0 rows affected, 1 warning (0.00 sec)
步骤二:建表练习
//创建 学生库
- mysql> create database 学生库;
- Query OK, 1 row affected (0.11 sec)
//建 学生信息表
-
mysql> create table 学生库.学生信息表( -> 姓名 char(10), -> 班级 char(9), -> 性别 char(4), -> 年龄 int -> ); Query OK, 0 rows affected (0.47 sec)
//进入库
- mysql> use 学生库;
- Reading table information for completion of table and column names
- You can turn off this feature to get a quicker startup with -A
- Database changed
//查看表
-
mysql> show tables; +---------------------+ | Tables_in_学生库 | +---------------------+ | 学生信息表 | +---------------------+ 1 row in set (0.00 sec)
//查看表头
- mysql> desc 学生信息表; #对应你取的,学生表名字
- +--------+----------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+----------+------+-----+---------+-------+
- | 姓名 | char(10) | YES | | NULL | |
- | 班级 | char(9) | YES | | NULL | |
- | 性别 | char(4) | YES | | NULL | |
- | 年龄 | int | YES | | NULL | |
- +--------+----------+------+-----+---------+-------+
- 4 rows in set (0.00 sec)
//删除表
- mysql> drop table 学生库.学生信息表;
//删除库
- mysql> drop database 学生库;
使用英文命名,重新建库、建表
【一般来说使用中文,表头,库名,表名容易出现未知BUG】
#其次就是不够专业,专业命名方法是”驼峰命名法”
-
mysql> create database studb; //建库 Query OK, 1 row affected (0.11 sec) mysql> create table studb.stu( //建表 -> name char(10), -> class char(9), -> gender char(4), -> age int -> ); Query OK, 0 rows affected (1.17 sec) mysql> desc studb.stu; //查看表头 +--------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+----------+------+-----+---------+-------+ | name | char(10) | YES | | NULL | | | class | char(9) | YES | | NULL | | | gender | char(4) | YES | | NULL | | | age | int | YES | | NULL | | +--------+----------+------+-----+---------+-------+ 4 rows in set (0.00 sec)
步骤三:修改表练习
//修改表名
- mysql> alter table studb.stu rename studb.stuinfo;
- Query OK, 0 rows affected (0.28 sec)
//进入库
- mysql> use studb;
- Reading table information for completion of table and column names
- You can turn off this feature to get a quicker startup with -A
- Database changed
//查看表
- mysql> show tables;
- +-----------------+
- | Tables_in_studb |
- +-----------------+
- | stuinfo |
- +-----------------+
- 1 row in set (0.00 sec)
//删除age表头
- mysql> alter table studb.stuinfo drop age ;
- Query OK, 0 rows affected (0.52 sec)
- Records: 0 Duplicates: 0 Warnings: 0
//查看表头
- mysql> desc stuinfo; //查看表头
- +--------+----------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+----------+------+-----+---------+-------+
- | name | char(10) | YES | | NULL | |
- | class | char(9) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- +--------+----------+------+-----+---------+-------+
- 3 rows in set (0.00 sec)
//添加表头,默认添加在末尾
- mysql> alter table studb.stuinfo add mail char(30) ;
- Query OK, 0 rows affected (0.24 sec)
- Records: 0 Duplicates: 0 Warnings: 0
//查看表头
- mysql> desc studb.stuinfo;
- +--------+----------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+----------+------+-----+---------+-------+
- | name | char(10) | YES | | NULL | |
- | class | char(9) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- | mail | char(30) | YES | | NULL | |
- +--------+----------+------+-----+---------+-------+
- 4 rows in set (0.00 sec)
//first 把表头添加首位
//after 添加在指定表头名的下方
- mysql> alter table studb.stuinfo
- add number char(9) first ,
- add school char(10) after name;
- Query OK, 0 rows affected (0.48 sec)
- Records: 0 Duplicates: 0 Warnings: 0
//查看表结构
#看具体位置变化
- mysql> desc studb.stuinfo;
- +--------+----------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+----------+------+-----+---------+-------+
- | number | char(9) | YES | | NULL | |
- | name | char(10) | YES | | NULL | |
- | school | char(10) | YES | | NULL | |
- | class | char(9) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- | mail | char(30) | YES | | NULL | |
- +--------+----------+------+-----+---------+-------+
- 6 rows in set (0.00 sec)
//修改表头数据类型
- mysql> alter table studb.stuinfo modify mail varchar(50);
- Query OK, 0 rows affected (1.17 sec)
- Records: 0 Duplicates: 0 Warnings: 0
- mysql> desc studb.stuinfo;
- +--------+-------------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+-------------+------+-----+---------+-------+
- | number | char(9) | YES | | NULL | |
- | name | char(10) | YES | | NULL | |
- | school | char(10) | YES | | NULL | |
- | class | char(9) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- | mail | varchar(50) | YES | | NULL | |
- +--------+-------------+------+-----+---------+-------+
- 6 rows in set (0.01 sec)
//修改表头名
- mysql> alter table studb.stuinfo change class 班级 char(9) ;
- Query OK, 0 rows affected (0.12 sec)
- Records: 0 Duplicates: 0 Warnings: 0
//查看表头
- mysql> desc studb.stuinfo;
- +--------+-------------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+-------------+------+-----+---------+-------+
- | number | char(9) | YES | | NULL | |
- | name | char(10) | YES | | NULL | |
- | school | char(10) | YES | | NULL | |
- | 班级 | char(9) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- | mail | varchar(50) | YES | | NULL | |
- +--------+-------------+------+-----+---------+-------+
- 6 rows in set (0.00 sec)
//一起删除多个表头
- mysql> alter table studb.stuinfo drop school , drop 班级 ,drop mail ;
- Query OK, 0 rows affected (0.73 sec)
- Records: 0 Duplicates: 0 Warnings: 0
//查看表头
- mysql> desc studb.stuinfo;
- +--------+----------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+----------+------+-----+---------+-------+
- | number | char(9) | YES | | NULL | |
- | name | char(10) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- +--------+----------+------+-----+---------+-------+
- 3 rows in set (0.00 sec)
- mysql>
//使用modify 修改表头的位置
- mysql> alter table studb.stuinfo modify gender char(4) after number;
- Query OK, 0 rows affected (0.77 sec)
- Records: 0 Duplicates: 0 Warnings: 0
//查看表头
- mysql> desc studb.stuinfo;
- +--------+----------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+----------+------+-----+---------+-------+
- | number | char(9) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- | name | char(10) | YES | | NULL | |
- +--------+----------+------+-----+---------+-------+
- 3 rows in set (0.00 sec)
//再修改回原来位置
- mysql> alter table studb.stuinfo modify gender char(4) after name;
- Query OK, 0 rows affected (0.50 sec)
- Records: 0 Duplicates: 0 Warnings: 0
//查看表头
- mysql> desc studb.stuinfo;
- +--------+----------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +--------+----------+------+-----+---------+-------+
- | number | char(9) | YES | | NULL | |
- | name | char(10) | YES | | NULL | |
- | gender | char(4) | YES | | NULL | |
- +--------+----------+------+-----+---------+-------+
- 3 rows in set (0.01 sec)
步骤四:复制表练习
复制表 (拷贝已有的表 和系统命令 cp 的功能一样 )
//复制tarena库salary表到 studb库 表名不变
- mysql> create table studb.salary select * from tarena.salary;
- Query OK, 8055 rows affected (2.66 sec)
- Records: 8055 Duplicates: 0 Warnings: 0
//查看表头,源表的key 不会被复制
#这个KEY就是一种外建或者主键编号。是有约束性的,有唯一值来区分识别。
- mysql> desc studb.salary;
- +-------------+------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +-------------+------+------+-----+---------+-------+
- | id | int | NO | | 0 | |
- | date | date | YES | | NULL | |
- | employee_id | int | YES | | NULL | |
- | basic | int | YES | | NULL | |
- | bonus | int | YES | | NULL | |
- +-------------+------+------+-----+---------+-------+
- 5 rows in set (0.00 sec)
//查看表行数
- mysql> select count(*) from studb.salary;
- +----------+
- | count(*) |
- +----------+
- | 8055 |
- +----------+
- 1 row in set (0.00 sec)
//仅仅复制表头,源表的key 会被复制
- mysql> create table studb.salary2 like tarena.salary;
- Query OK, 0 rows affected (0.95 sec)
//查看表头
- mysql> desc studb.salary2;
- +-------------+------+------+-----+---------+----------------+
- | Field | Type | Null | Key | Default | Extra |
- +-------------+------+------+-----+---------+----------------+
- | id | int | NO | PRI | NULL | auto_increment |
- | date | date | YES | | NULL | |
- | employee_id | int | YES | MUL | NULL | |
- | basic | int | YES | | NULL | |
- | bonus | int | YES | | NULL | |
- +-------------+------+------+-----+---------+----------------+
- 5 rows in set (0.00 sec)
//查看表行数
- mysql> select count(*) from studb.salary2; 只复制了表头 所以是零行
- +----------+
- | count(*) |
- +----------+
- | 0 |
- +----------+
- 1 row in set (0.00 sec)
- mysql>
二、数据类型
varchar 和 char 类型的区别 ?
使用场景:数据值长度不固定时选varchar,值长度固定时选char(电话号,身份证号)。
#varchar就好比英雄联盟中的适应性头盔一样,根据英雄脑袋大小而变化。而char类型则是固定的。
示例:
# 创建数据库mydb
mysql> create database mydb default charset utf8mb4;
Query OK, 1 row affected (0.00 sec)
mysql> use mydb;
Database changed
# 创建部门表
mysql> create table departments (
-> id int,
-> dept_name varchar(20)
-> );
Query OK, 0 rows affected (0.01 sec)
步骤一:练习字符类型的使用
//建表
- mysql> create table studb.t2(name char(3) , address varchar(5) );
- Query OK, 0 rows affected (0.30 sec)
//查看表头
- mysql> desc studb.t2;
//插入记录
mysql> insert into studb.t2 values ("a","a"); //正常
Query OK, 1 row affected (0.05 sec)
mysql> insert into studb.t2 values ("ab","ab"); //正常
Query OK, 1 row affected (0.08 sec)
mysql> insert into studb.t2 values ("abc","abc");//正常
Query OK, 1 row affected (0.04 sec)
mysql> insert into studb.t2 values ("abcd","abcd"); //超出字符个数报错
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql>
//查看字符集,mysql8 建表默认支持中文字符集
mysql> show create table studb.t2 \G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`name` char(3) DEFAULT NULL,
`address` varchar(5) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
说明 : ENGINE=InnoDB 定义存储引擎(存储引擎课程里讲) DEFAULT CHARSET=定义表使用的字符集
//插入记录
-
mysql> insert into studb.t2 values ("张翠山","武当山"); Query OK, 1 row affected (0.07 sec)
//查看记录
-
mysql> SELECT * FROM studb.t2; +-----------+-----------+ | name | address | +-----------+-----------+ | a | a | | ab | ab | | abc | abc | | 张翠山 | 武当山 | +-----------+-----------+ 4 rows in set (0.00 sec)
步骤二:练习数值类型的使用
表头说明:
name 姓名
level 游戏级别
money 游戏币
#游戏都有数据存储到数据库中,存放副本角色道具等各类数值。
//建表
//插入数据
mysql> insert into studb.t1 values("法师",80,88);
//超出范围报错
//整数类型 不存储小数位
//查看表记录
-
mysql> create table studb.t1( name char(10) , level tinyint unsigned , money double ); Query OK, 0 rows affected (0.72 sec)
//查看表头
mysql> desc studb.t1;
- mysql> insert into studb.t1 values("战士",301,1.292);
- ERROR 1264 (22003): Out of range value for column 'level' at row 1
- mysql>
-
mysql> insert into studb.t1 values ("英雄",1.292,6.78); Query OK, 1 row affected (0.07 sec)
-
mysql> select * from studb.t1 ; +--------+-------+-------+ | name | level | money | +--------+-------+-------+ | 法师 | 80 | 88 | | 英雄 | 1 | 6.78 | +--------+-------+-------+ 3 rows in set (0.00 sec) Query OK, 1 row affected (0.04 sec)
三、数据批量处理
案例3:数据批量处理
3.1 问题
- 修改检索目录为/myload。
- 将/etc/passwd文件导入db1库的user3表里,并添加行号字段。
- 将db1库user3表所有记录导出, 存到/myload/user.txt文件里。
3.2 方案
在mysql50主机完成练习。
3.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:修改检索目录为/myload。
登陆服务
- [root@mysql50 ~]# mysql -uroot -pNSD2023...a
查看与文件相关的配置项
- mysql> show variables like "%file%";
- +---------------------------------------+---------------------------------+
- | Variable_name | Value |
- +---------------------------------------+---------------------------------+
- | character_set_filesystem | binary |
- | core_file | OFF |
- | ft_stopword_file | (built-in) |
- | general_log_file | /var/lib/mysql/mysql50.log |
- | init_file | |
- | innodb_buffer_pool_filename | ib_buffer_pool |
- | innodb_buffer_pool_in_core_file | ON |
- | innodb_data_file_path | ibdata1:12M:autoextend |
- | innodb_disable_sort_file_cache | OFF |
- | innodb_doublewrite_files | 2 |
- | innodb_file_per_table | ON |
- | innodb_log_file_size | 50331648 |
- | innodb_log_files_in_group | 2 |
- | innodb_open_files | 4000 |
- | innodb_temp_data_file_path | ibtmp1:12M:autoextend |
- | keep_files_on_create | OFF |
- | large_files_support | ON |
- | local_infile | OFF |
- | lower_case_file_system | OFF |
- | myisam_max_sort_file_size | 9223372036853727232 |
- | open_files_limit | 10000 |
- | performance_schema_max_file_classes | 80 |
- | performance_schema_max_file_handles | 32768 |
- | performance_schema_max_file_instances | -1 |
- | pid_file | /run/mysqld/mysqld.pid |
- | relay_log_info_file | relay-log.info |
- | secure_file_priv | /var/lib/mysql-files/ |
- | slow_query_log_file | /var/lib/mysql/mysql50-slow.log |
- +---------------------------------------+---------------------------------+
- 28 rows in set (0.00 sec)
查看默认检索目录
- mysql> show variables like "secure_file_priv";
- +------------------+-----------------------+
- | Variable_name | Value |
- +------------------+-----------------------+
- | secure_file_priv | /var/lib/mysql-files/ |
- +------------------+-----------------------+
- 1 row in set (0.00 sec)
- mysql> exit
查看目录
- [root@mysql50 ~]# ls -ld /var/lib/mysql-files/
- drwxr-x--- 2 mysql mysql 6 Sep 22 2021 /var/lib/mysql-files/
- [root@mysql50 ~]#
修改检索目录
- [root@mysql50 ~]# vim /etc/my.cnf.d/mysql-server.cnf
- [mysqld]
- secure_file_priv=/myload 添加此行
- :wq
创建目录并修改所有者为mysql用户 ,并保证mysql用户对父目录有rx
- [root@mysql50 ~]# mkdir /myload
- [root@mysql50 ~]# chown mysql /myload
- 关闭selinux
- root@mysql50 ~]# setenforce 0 //禁用selinux
- setenforce: SELinux is disabled
重启服务
- [root@mysql50 ~]# systemctl restart mysqld
管理员登陆
- [root@mysql50 ~]# mysql -uroot -pNSD2023...a
查看目录
- mysql> show variables like "secure_file_priv";
- +------------------+----------+
- | Variable_name | Value |
- +------------------+----------+
- | secure_file_priv | /myload/ |
- +------------------+----------+
- 1 row in set (0.01 sec)
步骤二:将/etc/passwd文件导入db1库的user3表里。
建库
- [root@mysql50 ~]# mysql -uroot -pNSD2023...a
- mysql> create database db1;
建表( 根据导入的文件内容 创建表头)
- mysql> create table db1.user3(
- name varchar(30),
- password char(1),
- uid int ,
- gid int ,
- comment varchar(200),
- homedir varchar(50),
- shell varchar(30)
- );
- Query OK, 0 rows affected (0.41 sec)
查看表头
- mysql> desc db1.user3;
- +----------+--------------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +----------+--------------+------+-----+---------+-------+
- | name | varchar(30) | YES | | NULL | |
- | password | char(1) | YES | | NULL | |
- | uid | int | YES | | NULL | |
- | gid | int | YES | | NULL | |
- | comment | varchar(200) | YES | | NULL | |
- | homedir | varchar(50) | YES | | NULL | |
- | shell | varchar(30) | YES | | NULL | |
- +----------+--------------+------+-----+---------+-------+
- 7 rows in set (0.01 sec)
拷贝文件到检索目录
在MySQL 里执行系统命令 前加system 指令
- mysql> system cp /etc/passwd /myload/
- mysql> system ls /myload/ 查看文件
- passwd
- mysql>
导入数据
- mysql> load data infile "/myload/passwd" into table db1.user3
- fields terminated by ":"
- lines terminated by "\n" ;
查看表记录
- mysql> select count(*) from db1.user3; 查看行数
- +----------+
- | count(*) |
- +----------+
- | 23 |
- +----------+
- 1 row in set (0.00 sec)
- mysql> select * from db1.user3; 查看数据
- +------------------+----------+-------+-------+-----------------------------+-----------------+----------------+
- | name | password | uid | gid | comment | homedir | shell |
- +------------------+----------+-------+-------+-----------------------------+-----------------+----------------+
- | root | x | 0 | 0 | root | /root | /bin/bash |
- | bin | x | 1 | 1 | bin | /bin | /sbin/nologin |
- | daemon | x | 2 | 2 | daemon | /sbin | /sbin/nologin |
- | adm | x | 3 | 4 | adm | /var/adm | /sbin/nologin |
- | lp | x | 4 | 7 | lp | /var/spool/lpd | /sbin/nologin |
- | sync | x | 5 | 0 | sync | /sbin | /bin/sync |
- | shutdown | x | 6 | 0 | shutdown | /sbin | /sbin/shutdown |
- | halt | x | 7 | 0 | halt | /sbin | /sbin/halt |
- | mail | x | 8 | 12 | mail | /var/spool/mail | /sbin/nologin |
- | operator | x | 11 | 0 | operator | /root | /sbin/nologin |
- | games | x | 12 | 100 | games | /usr/games | /sbin/nologin |
- | ftp | x | 14 | 50 | FTP User | /var/ftp | /sbin/nologin |
- | nobody | x | 65534 | 65534 | Kernel Overflow User | / | /sbin/nologin |
- | dbus | x | 81 | 81 | System message bus | / | /sbin/nologin |
- | systemd-coredump | x | 999 | 997 | systemd Core Dumper | / | /sbin/nologin |
- | systemd-resolve | x | 193 | 193 | systemd Resolver | / | /sbin/nologin |
- | polkitd | x | 998 | 995 | User for polkitd | / | /sbin/nologin |
- | unbound | x | 997 | 994 | Unbound DNS resolver | /etc/unbound | /sbin/nologin |
- | tss | x | 59 | 59 | Account used for TPM access | /dev/null | /sbin/nologin |
- | chrony | x | 996 | 993 | | /var/lib/chrony | /sbin/nologin |
- | sshd | x | 74 | 74 | Privilege-separated SSH | /var/empty/sshd | /sbin/nologin |
- | tcpdump | x | 72 | 72 | | / | /sbin/nologin |
- | mysql | x | 27 | 27 | MySQL Server | /var/lib/mysql | /sbin/nologin |
- +------------------+----------+-------+-------+-----------------------------+-----------------+----------------+
- 23 rows in set (0.00 sec)
- mysql>
步骤三:将db1库user3表所有记录导出, 存到/myload/user.txt文件里。
导出数据
- mysql> select * from db1.user3 into outfile "/myload/user.txt" ;
- Query OK, 23 rows affected (0.00 sec)
查看文件
- mysql> system ls /myload/
- passwd user.txt
统计文件行数
- mysql> system wc -l /myload/user.txt
- 23 /myload/user.txt
- mysql>
查看文件内容
-
mysql> system vim /myload/user.txt root x 0 0 root /root /bin/bash bin x 1 1 bin /bin /sbin/nologin daemon x 2 2 daemon /sbin /sbin/nologin adm x 3 4 adm /var/adm /sbin/nologin lp x 4 7 lp /var/spool/lpd /sbin/nologin sync x 5 0 sync /sbin /bin/sync shutdown x 6 0 shutdown /sbin /sbin/shutdown halt x 7 0 halt /sbin /sbin/halt mail x 8 12 mail /var/spool/mail /sbin/nologin operator x 11 0 operator /root /sbin/nologin games x 12 100 games /usr/games /sbin/nologin ftp x 14 50 FTP User /var/ftp /sbin/nologin nobody x 65534 65534 Kernel Overflow User / /sbin/nologin dbus x 81 81 System message bus / /sbin/nologin systemd-coredump x 999 997 systemd Core Dumper / /sbin/nologin systemd-resolve x 193 193 systemd Resolver / /sbin/nologin polkitd x 998 995 User for polkitd / /sbin/nologin unbound x 997 994 Unbound DNS resolver /etc/unbound /sbin/nologin tss x 59 59 Account used for TPM access /dev/null /sbin/nologin chrony x 996 993 /var/lib/chrony /sbin/nologin sshd x 74 74 Privilege-separated SSH /var/empty/sshd /sbin/nologin tcpdump x 72 72 / /sbin/nologin mysql x 27 27 MySQL Server /var/lib/mysql /sbin/nologin
导出数据时 ,定义列的间隔符号 和 行的间隔符号
四、表头基本约束
约束
●约束是一种限制,用于限制表中的数据,为了保证表中数据的准确性和可靠性。
●创建表时可以添加约束
●修改表时可以添加约束
●PRIMARY KEY | ●NOT NULL : | ●DEFAULT: | ●UNIQUE: | ●FOREIGN KEY: |
---|---|---|---|---|
主键,用于保证该字段的值具有唯一性并且非空。 | 非空,用于保证该字段的值不能为空。 | 默认值,用于保证该字段有默认值。 | 唯一,用于保证该字段的值具有唯一性,可以为空。 | 外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值,在从表添加外键约束,用于引用主表中某些的值。 |
约束可应用在列级或表级。列表所有约束均支持,但外键约束没有效果;表级约束可以支持主键、唯一、外键约束。
●创建表时使用约束
mysql> create table employees2 (
-> employee_id int,
-> name varchar(20),
-> email varchar(20),
-> dept_id int,
-> primary key (employee_id), -- 主键
-> unique (email), -- 唯一
-> foreign key (dept_id) references departments(dept_id) -- 外键
-> );
# 查看约束
mysql> select * from information_schema.table_constraints where table_name='employees2' \G
●自定义约束名称
mysql> create table employees3 (
-> employee_id int,
-> name varchar(20),
-> dept_id int,
-> constraint pk primary key(employee_id), # 不报错,不生效
-> constraint fk_employees3_departments foreign key(dept_id) references departments(dept_id)
-> );
删除约束
●语法:ALTER TABLE <表名> DROP FOREIGN KEY <外键约束名>
DBA Day04
一、表头高级约束
二、MySQL索引
基本概念
●索引(Index)是帮助MySQL高效获取数据的数据结构。我们可以简单理解为:它是快速查找排好序的一种数据结构。
●可以用来快速查询数据库表中的特定记录,所有的数据类型都可以被索引。
●Mysql索引主要有两种结构:B+Tree索引和Hash索引
优点
●可以大大提高MySQL的检索速度
●索引大大减小了服务器需要扫描的数据量
●索引可以帮助服务器避免排序和临时表
●索引可以将随机IO变成顺序IO
缺点
●虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存索引文件。
●建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。
●如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
●对于非常小的表,大部分情况下简单的全表扫描更高效;
分类
普通索引
●不应用任何限制条件的索引,该索引可以在任何数据类型中创建。
●字段本身的约束条件可以判断其值是否为空或唯一。
●创建该类型索引后,用户在查询时,便可以通过索引进行查询。
唯一性索引
●使用UNIQUE参数可以设置唯一索引。
●创建该索引时,索引的值必须唯一,通过唯一索引,用户可以快速定位某条记录
●主键是一种特殊唯一索引。
全文索引
●使用FULLTEXT参数可以设置索引为全文索引。
●全文索引只能创建在CHAR、VARCHAR或者TEXT类型的字段上。查询数据量较大的字符串类型的字段时,使用全文索引可以提高查询速度。
●在默认情况下,应用全文搜索大小写不敏感。如果索引的列使用二进制排序后,可以执行大小写敏感的全文索引。
单列索引
●顾名思义,单列索引即只对应一个字段的索引。
●应用该索引的条件只需要保证该索引值对应一个字段即可。
●可以包括普通、唯一、全文索引
多列索引
●多列索引是在表的多个字段上创建一个索引。
●该索引指向创建时对应的多个字段,用户可以通过这几个字段进行查询。
●要想应用该索引,用户必须使用这些字段中的第一个字段。
创建索引
普通索引index
●一个表中可以有多个index
●字段的值可以重复,且可以赋值为null
●通常在where条件中的字段上配置Index
●index索引字段的标志为mul
●创建表时创建索引
语法格式
CREATE TABLE 表名(
字段列表,
index(字段名),
index(字段名),
);
●在已有表中创建索引
CREATE INDEX 索引名 ON 表名(字段名);
●查看索引
DESC 表名; # 注意观察Key这一列
或
SHOW INDEX FROM 表名 \G
●删除索引
DROP INDEX 索引名 ON 库.表名;
三、用户管理
授权
创建用户并授权
● 语法:#大小写都可以
GRANT 权限列表 ON 库名.表名 TO '用户名'@'客户端地址' IDENTIFIED BY '密码' WITH GRANT OPTION;
- 权限列表:用户的操作权限,如
SELECT
,INSERT
,UPDATE
等,如果要授予所的权限则使用ALL
- 表名:表名,如果要授予该用户对所有数据库和表的相应操作权限则可用
*
表示,如*.*
- WITH GRANT OPTION:用户拥有授权权限
- 示例:
# 授予dc用户在本地登陆的权限
mysql> grant select,update(phone_number,email)
on nsd2021.employees to dc@'localhost' identified by 'NSD2021@tedu.cn';
# 授予dc用户在任意地址登陆的权限
GRANT SELECT, INSERT, UPDATE(phone_number,email)
ON nsd2021.employees to dc@'%' IDENTIFIED BY 'NSD2021@tedu.cn';
客户端连接测试
#在另外一台虚拟机测试
# 安装mysql/mariadb客户端
[root@mysql51 ~]# yum install -y mariadb
[root@mysql51 ~]# mysql -h服务器 -u用户名 -p密码
相关查询指令
● 查看用户信息
SELECT USER();
● 显示登陆用户自己的权限
SHOW GRANTS;
● 管理员查看指定用户的权限,用户不存在则报错
SHOW GRANTS FOR 用户名@'客户端地址';
● 用户修改自己的密码
SET password=password('密码');
● 管理员修改指定用户密码
SET PASSWORD FOR 用户名@'客户端地址'=password('密码');
● 删除用户
DROP USER 用户名@'客户端地址';