MySQL入门

佐手、 提交于 2020-02-25 17:23:33

 

mysql对大小写不是很敏感,要区分大小写的话,要自己去设置

workbench中建立数据表时的几个选项意思:

1.添加数据库: CREATE DATABASE test_db;

2.查看数据库: SHOW DATABASES;  注意最后有S

3.查看数据库的定义:SHOW CREATE DATABASE test_db \G;

4.删除数据库:DROP DATABASE test_db;

5.查看系统存储引擎:SHOW ENGINES \G;

6.存储引擎选择:如果要提供提交、回滚和崩溃恢复能力的事物安全能力,并要求实现并发控制,InnoDB是个很好的选择。如果数据表主要用来插入和查询记录,则MyISAM引擎能提供较高的处理效率,如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存中的Memory引擎,MySQL中使用该引擎作为临时表,存放查询的中间结果。如果只有INSERT和SELECT操作,可以选择Archive引擎,Archive存储引擎支持高并发的输入操作,但是本身并不是事物安全的,其非常适合存储归档数据,如记录日志信息可以使用Archive引擎。

7.cmd登录mysql:mysql -h localhost -u root -p

8.选择当前的数据库为test_db:   USE test_db;

9.查看默认存储引擎:SHOW VARIABLES LIKE ‘storage_engine’

10.修改默认存储引擎:首先打开my.ini文件,将[mysqld]字段下面的default-storage-engine参数后面的值,由InnoDB改为MyISAM,保存重启MySQL

11.创建tb_emp1表: 注意建表的时候是()而不是{}

CREATE TABLE tb_emp1
(
    id INT(11),
    name VARCHAR(25),
    deptId INT(11),
    salary FLOAT
);

这里面的int(M) M指示最大显示宽度。显示宽度与数据类型的取值范围无关,数值的位数小于指定的宽度时会由空格填充,如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能够显示出来。

varchar(M)是长度可变的字符串,eg:varchar(50)定义了一个最大长度为50的字符串,如果插入的字符串只有10个字符,则实际存储的字符串为10个字符和一个字符串结束字符。

12.查看表: SHOW TABLES;

13.使用主键约束:

13.1单字段逐渐

有两种定义情况:

CREATE TABLE tb_emp2 (
id INT(11)PRIMARY KEY, 
name VARCHAR(25), 
deptId INT(11), 
salary FLOAT 
);

或者:

CREATE TABLE tb_emp4 (
id INT(11),
name VARCHAR(25),
deptId INT(11),
salary FLOAT ,
PRIMARY KEY(id)
);

13.2多字段联合主键:

CREATE TABLE tb_emp5 (
name VARCHAR(25), 
deptId INT(11), 
salary FLOAT , 
PRIMARY KEY(name,deptId) 
);

14.使用外键约束

CREATE TABLE tb_dept1
(
id INT(11)PRIMARY KEY,
name VARCHAR(22) NOT NULL,
location VARCHAR(50)
);
CREATE TABLE tb_emp5     
(
    id int(11) PRIMARY KEY,
    name varchar(25),
    deptId int(11), 
    salary float,
    CONSTRAINT fk_emp_dept1 FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);

以上语句执行成功以后,在tb_emp5上添加了一个名称为fk_emp_dept1的外键约束,外键名称为deptId,其一代与表tb_dept1的主键id

上面的NOT NULL是非空约束,表示字段的值不能为空,对于使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统会报错。

15.唯一性约束

唯一性约束要求该列唯一,允许为空,但只能出现一个空值。唯一性约束可以确保一列或者几列不出现重复值。

其语法规则如下:

15.1 在定义完列之后直接指定唯一约束 

name varchar(22)UNIQUE;

15.2 在定义完所有列之后指定唯一约束

CONSTRANT STH UNIQUE (name) 

其中STH为约束名

16.设置默认约束

deptId INT(11)DEFAULT 1111

17.设置表的属性值自动增加

id INT(11)PRIMARY KEY AUTO_INCREMENT

AUTO_INCREMENT关键字初始值为1,没增加一条记录,字段值自动加一,一个表只能有一个字段使用AUTO_INCREMENT,且该字段必须是主键的一部分。

CREATE TABLE tb_emp8
 (
id INT(11)PRIMARY KEY AUTO_INCREMENT,
 name VARCHAR(25)NOT NULL,
deptId INT(11),
salary float,
CONSTRAINT fk_emp_dept5 FOREIGN KEY(deptId)REFERENCES tb_dept1(id)
);
mysql> insert into tb_emp8(name,salary)
    -> VALUES('Lucy',1000),('Lura',1200),('Kevin',1500);

结果:

mysql> SELECT *FROM tb_emp8;
+----+-------+--------+--------+
| id | name  | deptId | salary |
+----+-------+--------+--------+
|  1 | Lucy  |   NULL |   1000 |
|  2 | Lura  |   NULL |   1200 |
|  3 | Kevin |   NULL |   1500 |
+----+-------+--------+--------+
3 rows in set (0.00 sec)

可以看到我们并没有设置id值,但是插入后id值自动增加了

18.查看表结构 DESCRIBE和SHOW CREATE TABLE语句

18.1 DESCRIBE 

describe 表名;可以简化成desc 表名;

18.2 SHOW CREATE TABLE 表名 \G;

不加\G的话,结果显示会比较混乱

19.修改数据表

19.1 修改表名 alter table tb_empt3 rename deptment3;

19.2 修改字段数据类型   alter table 表名 modify 字段名 数据类型;

 alter table tb_dept1 modify name varchar(30)

19.3修改字段名 alter table 表名 change 旧的字段名 新的字段名 新数据类型;

19.4添加字段  alter table 表名 add 新的字段名 数据类型 [约束条件] [first|after 已存在的字段名];

[]表示可选。

mysql> alter table tb_dept1 add column3 int(11) after name;

mysql> desc tb_dept1;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int(11)     | NO   | PRI | NULL    |       |
| name     | varchar(30) | YES  |     | NULL    |       |
| column3  | int(11)     | YES  |     | NULL    |       |
| location | varchar(50) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

19.5 删除字段 alter table 表名 drop 字段名

19.6 修改字段的排列位置

alter table 表名 modify 字段1 数据类型 first|after 字段2

19.7修改表的存储引擎

alter table 表名 engine=更改后的引擎名

19.8删除表的外键约束

alter table 表名 drop foreign key 外键约束名

20 删除数据表

drop table 表1,表2...;

如果写成drop table if exists 表1,表2...;可以再删除前判断表是否存在,如果不存在,SQL语句可以顺利执行,只是会发出警告。

删除主表时,必须先删除关联的表的外键约束条件,才能删除主表。

21.一些不太一样的运算符:

21.1等于运算符=,用来判断是否相等的,等于返回1

21.2安全等于运算符<=>,在=的基础上可以用来判断null的值,如果都为null时,其返回值为1

21.3<>不等于运算符

21.4 IS NULL,IS NOT NULL运算符

21.5 between and运算符:expr between min and max,假如expr大于或等于min且小于或等于max,则返回1, eg: select 4 between 4 and 6;

21.6 least运算符 多个值返回最小值

21.7 greatest 运算符 多个值返回最大值

21.8 in 、not in运算符 in判断操作数是否为in列表中的其中一个是(not in相反)

21.9 like运算符 expr like 匹配条件

22.一些函数:

22.1 ceil(x)向上取整函数 floor(x)向下取整函数

22.2 rand(x)可以用来产生随机数,x是种子

22.3round(x)返回最接近x的整数

22.4sign(x)返回参数的符号,负数返回-1,0返回0,整数返回1;

22.5 radians(x)将参数由角度转化成弧度  degrees(x)将x由弧度转化为角度

22.6 char_length计算字符串字符个数  eg char_length('date')

22.7 concat(s1,s2) 合并字符串函数 concat_ws(x,s1,s2)x为连接处的分隔符

22.8 insert(s1,x,len,s2) 替换字符串函数,返回s1

22.9 获取指定长度的字符串函数 left(s,n) 从左边开始第n个保留,right(s,n)从右边开始第n个符号保留

22.10删除空格函数 ltrim(s)、rtrim(s)、trim(s)

23.查询

23.1 SELECT 字段名,字段名 FROM 表名;

23.2 SELECT * FROM 表名; *为通配符,可查询所有字段

23.3 SELECT 字段名1、字段名2.。。。FROM 表名 WHERE 查询条件; WHERE后面可以跟条件判断符(例如相等=、不相等<>、大于>、小于<、between、in、is null、以及带and或者or的多条件查询等)

eg :查询价格为10.2元的水果的名称:

SELECT f_name,f_price FROM fruits where f_price =10.2;  注意这里表示的是是否等于

SELECT f_name,f_price FROM fruits where s_id in (101,102);

SELECT f_name,f_price FROM fruits where f_price between 2.00 and 10.2;

SELECT f_name,f_price FROM fruits where s_id="101"and f_price>=5;

23.4查询结不重复:SELECT DISTINCT 字段名 FROM 表名;

SELECT DISTINCT s_id FROM fruits;

23.5对查询结果排序(默认升序): SELECT f_name FROM fruits order by f_name;

对查询结果按降序排序 :SELECT f_name,f_id FROM fruits order by f_name DESC;

23.6分组查询:

23.6.1 创建分组: SELECT s_id,COUNT(*)AS Total FROM fruits GROUP BY s_id;

GROUP BY关键字对数据进行分组,它经常跟MAX()、MIN()、COUNT()、SUM()、AVG()等一起使用,例如上面这个例子就是把s_id分成了好几个分组,并对每个分组进行集合计算。

其结果为:

要想将名字显示出来:

select s_id , group_concat(f_name)  as names from fruits group by s_id;

23.6.2 使用having 过滤分组

group by 可以与having一起来限定显示记录所需满足的条件

eg要将水果种类大于1的分组信息显示出来

select s_id,group_concat(f_name) as names from fruits group by s_id having count(f_name)>1;

23.6.3 在group by后面使用with rollup 可以记录计算查询出的所有记录的总和

select s_id,count(*) as total from fruits group by s_id with rollup;

23.6.4 多字段分组 

这里按照书上的去写:

select * from fruits group by s_id,f_name;

没找到原因。。

然后我想着用这个应该能成:

select f_id,s_id,group_concat(f_name) as f_name,f_price from fruits group by s_id,f_name;

这结果就是跟书上一致了。

23.6.5 group by 可以与 order by连用来对结果进行排序

select s_id, sum(f_price) as total_price
from fruits
group by s_id
having sum(f_price)>15
order by total_price;

将查询记录先按部门编号高低排列,再按员工工资由高到低排列

select e_name,dept_no,e_salary
from employee
order by dept_no desc,e_salary desc;

 

23.7 限制查询结果数量 limit[位置偏移量] 行数;

select * from fruits limit 4;  只显示了从第一行到第四行

select * from fruits limit 4,3; 显示了第四行开始的后面三行

23.8使用集合函数查询

23.8.1 count()函数

该函数主要用来计算总数

count(*)计算表中总的行数(如果分组了,就是分组的总得行数),不管某列有数值或者为空值。

count(字段名)计算指定列下总的行数,计算时将忽略空值的行

23.8.2 sum函数用来计算总和,可以与group by 一起用来计算每个分组的总和

23.8.3 acg()函数来计算数据平均值

select avg(f_price) as avg_price
from fruits
group by s_id;

23.8.4 MAX()函数、min()函数

23.9内连接查询

在同一个数据库中,fruits与suppliers有相同数据类型的字段s_id,两个表通过s_id来建立联系,然后从fruits表中查询f_name/f_price,在suplliers表中查询s_id、s_name:

select suppliers.s_id,s_name,f_name,f_price
from fruits,suppliers
where fruits.s_id=suppliers.s_id;

where子句使得两个表中s_id字段值相等的时候才符合连接查询的条件。

select suppliers.s_id,s_name,f_name,f_price
from fruits inner join suppliers
on fruits.s_id=suppliers.s_id;

上面的写法输出了同样的结果

23.10 自连接查询

自连接是一种特殊的内连接查询,它涉及到的两个表都是同一个表,它是指相互连接的表在物理上为同一张表,但在逻辑上可以分为两张表。

查询供应f_id='a1'的水果供应商的其他水果种类:

select f1.s_id,f1.f_id,f1.f_name
from fruits as f1,fruits as f2
where f1.s_id=f2.s_id and f2.f_id='a1';

其结果为

这里为了避免二义性,去了别名,然后再where处,首先是把两个表中的s_id对应了(跟内连接相同),然后选择出f_id='a1'(我觉得可以这样理解:f2.f_id把''a1选出来,把此时的f1.s_id与f2.s_id进行了对比,也就是说,where选出来的应该是f1.s_id)自己写了一个:

select f1.s_id,f1.f_id,f1.f_name
from fruits as f1,fruits as f2
where f1.s_id=f2.s_id and f1.f_id='a1';  这里吧f2.f_id换成了f1.f_id

这结果验证了我的想法,因为此时where选出来的是'a1'而不是s_id,所以最后输出的只有a1,但是不知道为什么,该结果重复了三次,想不懂。。等待以后考究

23.11外连接查询

有时候需要包含没有关联的行中数据,即返回查询结果中不仅包含符合连接的行,而且还包括坐标、右表或者两个连接表的所有数据行。外连接分为左外连接和右外连接。

23.11.1 left join连接

左连接的结果包括left outer子句汇总指定的左表的所有航,而不仅仅是连接列所匹配的行。如果左表的某行在右表没有匹配行,则在相关联的结果行中,右表的所有选择列表列均为空值。

select customers.c_id,orders.o_num
from customers left outer join orders
on custormers.c_id=orders.c_id;

23.11.2 right join连接同理

23.12子查询

子查询指一个查询语句嵌套在另一个查询语句内部的查询,其常用操作符:any、all、in、exists,子查询可以添加到select、update和delete语句中,而且可以进行多层嵌套,子查询也可以使用比较运算符。

23.13.1 any、some关键字

any 和 some 关键字是同义词,表示满足其中任一条件,它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中的任何一个比较条件,就返回一个叫结果作为外层查询条件。

any关键字姐在一个比较操作符后面,表示若与子查询返回的任何值比较为true,则返回true

首先建立两个数据表:

create table tbl1(num1 int not null);
create table tbl2(num2 int not null);
insert into tbl1 values(1),(5),(13),(27);
insert into tbl2 values(6),(14),(11),(20);

返回tbl2表的所有num2列,然后将tbl1中的num1的值与之进行比较,只要大于num2的任何一个值,即为符合查询条件的结果。
select num1 from tbl1 where num1 >any(select num2 from tbl2);

23.13.2 all关键字

all 关键字需要同时满足所有内层查询的条件

select num1 from tbl1 where num1 >all(select num2 from tbl2);

与前面的any不同,any是num1只要大于num2任意一个就输出,all是要比所有的都大,才能输出

23.13.3 exists关键字

该关键字用来判断是否有返回行,如果至少返回一行,则exists结果为ture,此时未曾查询语句将进行查询,如果子查询没有返回任何行,则exists返回结果为false。

查询tmp10 中是否有soc=100,如果有则返回fruits中的所有数据:

select * from fruits
where exists
(select * from tmp10 where soc = 100);

exists还可以和条件表达式连用:

select * from fruits
where f_price > 10.2 and exists
(select * from tmp10 where soc = 100);

not exists与exists使用方法相同,只是查询的是不存在

23.13.4 in关键字

内层查询语句返回一个数据列,这个数据列的值将提供给外层查询语句进行比较操作

这是orderitems

这是fruits:

通过查找orderitems中0_num=100的值,并返回orderitems中的f_id,将其返回给fruits的f_id,然后通过f_id来查询f_price

select f_price,f_id from fruits where f_id in 
(select f_id from orderitems where o_num = 100);

同时还有not in 就是返回的不满足条件的结果

23.13.5 带比较运算符的子查询

23.14 合并查询结果:

通过union来合并查询结果,合并时,两个表对应的列数和数据类型必须相同,加了all则不删除重复行也不对结果自动排序,不加all则删除重复消息

select s_id,f_name,f_price
from fruits
where f_price < 9
union all
select s_id,f_name,f_price
from fruits
where s_id in (101,103);

xbanana是union all上面的查询语句查询的结果,xbanana后面是union all下面的查询语句查询的结果

去掉all以后:没有了重复

23.15 用as可以为表和字段取别名

23.16使用正则表达式查询

mysql中使用regexp关键字指定正则表达式的字符匹配模式

^ 匹配文字开头

& 匹配文字结束

.  匹配任何单个字符

* 匹配零个或多个在它前面的字符

+ 匹配前面的字符一次或者多次

<字符串> 匹配包括指定的字符串的文本

[字符集合] 匹配字符集合中任何一个字符

[^]匹配不在括号中的任何字符 eg [^abc]就是不包括a、b、c

{n,}匹配前面的字符串至少n次

{n,m}匹配前面的字符串至少n次,至多m次

23.17 综合测试遇到的一些问题和思考 

做综合测试的时候想要显示max 或min对应的其他属性,发现报错了:

select e1.e_no,e1.e_name,e1.e_salary 
from employee as e1,employee as e2
group by e1.dept_no
having e1.e_no=e2.e_no and e2.e_salary=max(e2.e_salary);

select e1.e_no,e1.e_name,e1.e_salary 
from employee as e1,employee as e2
where e1.e_no=e2.e_no and e2.e_salary=max(e2.e_salary);

以上都报错了

改良版:

select e_no,e_name,e_salary 
from employee
group by dept_no 
having e_salary=
    (select max(e_salary)
    from employee);

但是这个只能射出最大的那个的相关信息

完成版:

select e1.e_no,e1.e_name,e1.e_salary from employee as e1
where e1.e_salary in 
    (select max(e2.e_salary) 
     from employee as e2
     group by e2.dept_no);

这个可以输出每个组最大的那个salary的其他信息。

子查询很好用啊,用来查询一个信息的相关信息的时候可以用(例子如上),还有一个可以用在横跨两个表之间,如果要查询员工BLAKE的所在部门和部门所在地,BLAKE的所在部门在employee表中,部门所在地在dept表中,这时候可以这样横跨:

select d_no , d_location 
from dept 
where d_no in 
(select dept_no from employee where e_name='BLAKE');

使用连接查询,查询所有员工的部门和部门信息:

select d_no , d_location 
from dept 
where d_no in 
(select dept_no from employee where e_name='BLAKE');

内连接查询,同时查了两块表

24插入

24.1 insert into 表名(插入数据的列) values (插入的数据)

eg:  insert into person (id,name,age ,info)
       values (1,'green',21,'lawyer');

还可以为指定位置插入值,

insert into person (age )
values (20);
没有插入的部分会被设为null,有默认的就会直接设置为默认值

24.2 同时插入多条记录

insert into 表名(插入数据的列) values(数据),(数据),(数据)

24.3 将查询结果插入到表中

insert into 表1 (列1) 

select (列2) from 表2 where (条件)

eg:

insert into person (id,name,age,info)
select id,name,age,info from person_old;

25 更新数据

update table_name

set 字段1=value1,字段2=value2

where (condition)

 

eg:

update person

set age=15,name='Liming'

where id=10;

eg:

update person

set info='student'

where age between 19 and 22;

上面是把age从19到22的职业全部改成student

eg:

update books set price = price +5 where note = 'novel';

26 删除

delete from table_name [where <condition>]

eg delete from person where id=10;

eg delete from person where age between 19 and 22;

上面这个删除在workbench中报错了,好像是进入了安全更新模式才出现的,设置一下编辑器就可以了

delete from person;

这个也是一样的报错了。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!