数据库,保存数据的仓库,体现我们电脑中,就是一个文件系统,然后把数据都保存在这些特殊的文件中,并且需要使用固定的语言(SQL语言)去操作文件中的数据
数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的苍仓库
将程序中的数据保存到专业的软件中,这些软件称之为数据库
分为关系型数据库和非关系型数据库
关系数据库: | 数据库中的数据有关系 | oracle Mysql SqiSever DB2 |
非关系数据库: | 数据库中的数据没人有关系 | NoSql Cloudant |
关系型数据库:
关系型数据设置数据库的时候,需要使用E-R图来描述实体关系
DB | 数据库(database)存储数据的仓库,他保存了一系列有组织的数据 |
DBMS | 数据库管理系统,数据库是通过DBMS创建和操作的容器 |
SQL | 结构化查询语言:专门用来与数据库通信的语言 |
查询表中的单个字段
SELECT last_name from employees;
查询表中多个字段
SELECT last_name,first_name from employees;
查询表中的所有字段
SELECT *from employees;
选中哪个库去执行sql
在sql查询的最前端写
use 库名
着重号 ‘ ’
区分是否为关键字 为`不是引号
select `first_name` from `employees`;
查询常量值
select 100
查询字符串
select 'join';
查询表达式
select 100%2;
查询函数值
SELECT VERSION();
起别名(如果别名里面有特殊字段或者空格 建议用单引号或者双引号)
好处:
select name as name1 from emp;
#或者
select name name1 from emp;
去重— distinct
查询员工表中的涉及到的所有部门编号
select DISTINCT department_id from employees;
"+"的作用
查询员工的名和姓连接在一起并显示为姓名
#+ 号的作用 将字符型转换为数值型 如果转换成功就为数值型
# 转换失败则字符型相当于0 再做加法运算
# 只要一方为null则 结果为null
SELECT '123'+123;
SELECT 'tjk'+123;
连接字符串 concat(str, str,str)
#concat(str, str,str)
select CONCAT(last_name,first_name) as 姓名 from employees;
ifnull 判断是否为空
#IFNULL(判断是否空的字段,如果是的返回结果)
select IFNULL(commission_pct,0) AS 奖金率 from employees;
#查询 员工姓名中包含字符a 的员工信息‘
select
*
FROM employees
WHERE first_name LIKE '%a%';
通配符:
% 任意多个字符 包含0个字符
_ 任意单个字符
#查询员工名中第三个字符为a 第五个字符为a的员工信息
SELECT last_name ,salary FROM employees WHERE last_name like
'__a_a%';
#查询员工名中第二个字符为_的员工
SELECT last_name from employees WHERE last_name LIKE '_\_%';
声明某个字符是转义的标志
SELECT last_name from employees WHERE last_name LIKE '_a_%' ESCAPE 'a';
between… and…
注意:
包含两个端点的值
且端点不能颠倒 必须是从小到大
#查询员工编号在100-----120之间
SELECT *FROM employees where employee_id BETWEEN 100 and 120;
in()
#查询员工的工种编号AD_PRES AD_VP IT_PROG
select last_name, job_id FROM employees where job_id IN('AD_PRES','AD_VP','IT_PROG');
is null
#查询没有奖金的员工和奖金率
SELECT last_name ,commission_pct from employees where commission_pct is NULL;
is not null
#查询有奖金的员工和奖金率
SELECT last_name ,commission_pct from employees where commission_pct is NOT NULL;
安全等于<=>
既可以判断null值,又可以判断普通的数值
#查询没有奖金的员工和奖金率
SELECT last_name ,commission_pct from employees where commission_pct <=> NULL;
ifnull( , )
# 查询员工号为176的员工的姓名和部门号和年薪
select employee_id,last_name,salary*12*(1+IFNULL(commission_pct,0)) as 年薪
from employees where employee_id=176;
语法:
SELECT 查询列表
FROM 表
where 筛选条件
ORDER BY 排序列表 asc| DESC
注意:
SELECT last_name,salary from employees ORDER BY salary DESC;
SELECT * FROM employees where department_id>=90 ORDER BY hiredate ;
SELECT last_name,department_id,salary*12*(1+IFNULL(commission_pct,0))
年薪 from employees ORDER BY 年薪 DESC,last_name ASC;
SELECT last_name,salary FROM employees where salary NOT BETWEEN 8000 and 17000
ORDER BY salary DESC;
SELECT *from employees WHERE email LIKE '%e%' ORDER BY LENGTH(email) DESC,department_id ASC;
select 函数名(实参列表)from 表
select LENGTH("tjk");
SELECT CONCAT(last_name,"-",first_name) from employees;
SELECT UPPER("tjk");
示例 将姓名变大写 名变小写 然后拼接
select CONCAT(UPPER(first_name),"--",LOWER(last_name)) from employees;
SELECT SUBSTR("tjk xixixi",5);# 所有的标记都是从1开始算的 在sql中
SELECT TRIM(" tjk");
SELECT TRIM('-'FROM"------------tjk");
SELECT REPLACE("tjkdiditjktjktdiditjk",'didi','-');
SELECT ROUND(3.11);
SELECT ROUND(3.11,1);#默认保留几位小数
SELECT CEIL(5.1);
SELECT FLOOR(4.2);
SELECT TRUNCATE(2.11,1);
SELECT MOD(10,3);
SELECT CURDATE();
SELECT CURRENT_TIME();
SELECT CURTIME();
SELECT YEAR('1999-01-02');
SELECT MONTH('1999-01-01');
select DAY("1999-01-01");
SELECT STR_TO_DATE('1999-01-01','%Y-%m-%d') as 日期;
SELECT DATE_FORMAT(NOW(),'%Y年-%m月-%d日');
SELECT VERSION();# 版本号
select DATABASE();#数据库
SELECT USER();#返回用户
SELECT IF(5>2,1,0);
SELECT salary 原始工资,department_id,CASE department_id
WHEN 30 THEN '一倍'
WHEN 40 THEN '二倍'
WHEN 50 THEN '三倍'
ELSE salary
END AS 新工资
FROM employees;
SELECT salary 原始工资,department_id,
CASE
WHEN salary=30 then '是30啊'
WHEN salary>30 THEN '比30大啊'
WHEN salary<30 THEN '没有30大啊'
ELSE '是其他啊'
END
FROM employees
分类:
sum | 求和 |
avg | 平均值 |
max | 最大值 |
min | 最小值 |
count | 计算个数 |
*/
简单使用:
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT COUNT(salary) FROM employees;
参数支持哪些类型
以上分组函数都会自动忽略null
可以和 DISTINCT 搭配
SELECT SUM(DISTINCT salary) from employees;
SELECT COUNT(salary) FROM employees;
select COUNT(*) FROM employees;
SELECT count(1) FROM employees;
效率:
MYISAM存储引擎下 count()的效率高
INNODB存储引擎下 count()和count(1)效率差不多 比count (字段)要高一些
#和分组函数一同查询的字段有限制
SELECT avg(salary),employee_id FROM employees;-----无意义
语法:
SELECT 分组函数,列(要求出现在group by的后面)
FROM 表
where 筛选条件
GROUP BY 分组列表
ORDER BY 字句
注意:查询列表比较特殊 要求分组函数和group by后出现的
#引入 查询每个部门的平均工资
SELECT department_id, AVG(salary)
from employees
GROUP BY department_id;
案例 查询每个工种的最高工资
SELECT MAX(salary) ,job_id
FROM employees
GROUP BY job_id;
查询每个位置上部门的个数
SELECT COUNT(*),location_id
FROM departments
GROUP BY location_id;
#查询那个部门 员工个数大于2
select COUNT(*) ,department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2
查询每个工种有奖金的员工的最高工资》12000的公众编号和最高工资
#① 查询每个工种有奖金的员工的最高工资
SELECT MAX(salary), job_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING max(salary)>12000;
案例三 查询领导编号>102 的每个领导手下的最低工资
SELECT MIN(salary) 最低工资, manager_id
FROM employees
GROUP BY manager_id
HAVING manager_id>102;
特点:
- | 数据源 | 位置 | 关键字 |
分组前筛选 | 原始表 | GROUP BY 子句的前面 | WHERE |
分组后筛选 | 分组后的结果集 | GROUP BY 子句的后面 | HAVING |
按员工姓名的长度分组 查询每一组的员工个数,筛选员工个数>5的数据
SELECT count(*),LENGTH(last_name)
FROM employees
GROUP BY LENGTH(last_name);
HAVING count(*)>5
按多个字段分组
案例 查询每个部门每个工种的员工的平均工资
SELECT avg(salary),department_id,job_id
FROM employees GROUP BY department_id,job_id
#添加排序
查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示
SELECT avg(salary),department_id,job_id
FROM employees GROUP BY department_id,job_id
ORDER BY avg(salary) DESC;
总结:
1. 分组函数做条件 一定放在having子句中
2. 能用分组前筛选的就用分组前的
3. GROUP BY 子句支持单个字段分组,多个字段分组(多个字段用逗号隔开 没有顺序要求) 也可以用表达式 但是用的较少
4. 后面也可以跟排序 ORDER BY
含义: 又称多标查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象: 表有m行 表2有n行 结果为m*n行
发生原因: | 没有有效的连接条件 |
如何避免: | 添加有效的连接查询 |
分类:
按年代分类
sql92 | 仅支持内连接 |
sql99 | (推荐) 支持内连接 外连接 交叉连接 |
按功能分类:
注意:
SELECT boyName,beauty.`name`
from boys,beauty
where boyfriend_id=boys.id;
#非等值连接
SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.lowest_sal AND g.highest_sal;
实际上是等值连接 但是是一张表中的数据
SELECT e.employee_id,e.last_name,m.employee_id
FROM employees e,employees m
WHERE e.manager_id=m.manager_id;
#sql99 语法
/*
语法:
select 查询列表
from 表1 别名 连接类型
join 表2 别名
on 连接条件
where 筛选条件
GROUP BY 分组
HAVING 筛选条件
ORDER BY 排序列表
分类:
内连接:INNER
外连接
左外连接 LEFT
右外连接 RIGHT
全外 FULL
交叉连接 CROSS
*/
1.查询员工名 部门名
SELECT last_name,department_name
FROM departments d
INNER JOIN employees e
ON e.department_id=d.department_id
2.查询姓名中包含e的员工名和工种名(添加筛选)
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.job_id=j.job_id
WHERE e.last_name LIKE '%e%';
3.部门个数大于3 的城市名和部门个数 (添加分组和筛选)
select city,count(*) 部门个数
FROM departments d
INNER JOIN locations l
on d.location_id=l.location_id
GROUP BY city #聚合以后才能进行条件审判
HAVING count(*)>3
ORDER BY 是进行排序筛选
4. 查询那个部门的员工个数>3 的部门名和员工个数 病案个数进行降序(添加排序)
select department_name, count(*) 员工个数
FROM employees e
INNER JOIN departments d
ON e.department_id=d.department_id
GROUP BY e.department_id
HAVING count(*)>3
ORDER BY count(*) DESC
总结: 特点:
查询员工的工资级别
select salary,grade_level
FROM employees e
INNER JOIN job_grades g
ON e.salary BETWEEN g.lowest_sal AND g.highest_sal
查询员工的名字 上级的名字
SELECT e.last_name,m.last_name
FROM employees e
INNER JOIN employees m
ON e.manager_id=m.employee_id
应用场景 用于查询一个表中,另一个表中没有的记录
特点:
SELECT b.name,bo.*
from beauty b
LEFT OUTER JOIN boys bo
ON b.boyfriend_id=bo.id
WHERE bo.id IS NULL
查询那个部门没有员工SELECT d.department_id,d.department_name
FROM departments d
LEFT JOIN employees e
ON d.department_id=e.department_id
WHERE e.employee_id IS NULL
USE girls;
SELECT beauty.*,boys.*
FROM beauty b
FULL OUTER JOIN boys
ON beauty.boyfriend_id = boys.'id';
SELECT b.*,bo.*
FROM beauty b
CROSS JOIN boys bo
含义:
出现在其他语句中的select语句,称为只查询或内查询
外部的查询语句,称为主查询或外查询
分类:
按子查询出现的位置
标量子查询 | (结果集只有一行一列) |
列子查询 | (结果集只有一列多行) |
行子查询 | (结果集有一行多列) |
表子查询 | (结果集一般为多行多列) |
*/
一.重点:where 或having 后面
特点:
子查询放在小括号内
子查询一般放在条件的右侧
标量子查询一般搭配着当行操作符使用
> < >= <= = <>
列子查询 一般搭配多行操作符使用
in any/some ALL
SELECT last_name,salary
FROM employees
WHERE salary>(select salary
FROM employees
where last_name = 'Abel')
例二: 返回job_id 与 141 号员工相同,salary 比143号员工多的员工的 姓名 job_id 和工资
SELECT last_name ,job_id, salary
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE employee_id=141)
&& salary >
(SELECT salary
FROM employees
WHERE employee_id=143);
例三:返回公司工资最少的员工的last_name job_id salarly
SELECT last_name ,job_id,salary
from employees
WHERE salary=
(SELECT MIN(salary)
FROM employees);
例四:查询最低工资大于50号部门最低工资的部门id 和其最低工资
SELECT MIN(salary)
from employees
WHERE department_id =50
SELECT department_id ,MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary)>
(SELECT MIN(salary)
from employees
WHERE department_id =50)
ORDER BY MIN(salary) ASC
SELECT MIN(employee_id)
FROM employees
SELECT MAX(salary )
FROM employees
SELECT *
from employees
WHERE employee_id=
(SELECT MIN(employee_id)
FROM employees)
and
salary =
(SELECT MAX(salary )
FROM employees)
进化:(这个是有局限性的 所以用的比较少)
SELECT *
FROM employees
WHERE (employee_id,salary) =
(SELECT MIN(employee_id),MAX(salary)
FROM employees )
二. select后面
案例 查询每个部门的员工个数
select count(*),employees.*
FROM employees GROUP BY department_id
SELECT d.*,(SELECT COUNT(*) FROM employees e WHERE e.department_id=d.department_id) 个数
FROM departments d;
三 from 后面
案例 查询每个部门的平均工资的工资等级
SELECT avg(salary),department_id
FROM employees
GROUP BY department_id
SELECT *FROM job_grades;
SELECT ag_dep.*,g.grade_level
FROM (SELECT avg(salary) ag,department_id
FROM employees
GROUP BY department_id) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN lowest_sal and highest_sal
四 exists 是否存在 后面(也就是相关子查询)
select EXISTS
(SELECT employee_id
from employees)
SELECT 查询列表
from 表
【JOIN type JOIN 表2】
ON 连接条件
where 筛选条件
GROUP BY 分组数据
HAVING 分组后的筛选
ORDER BY 排序字段
LIMIT OFFSET,size
page-1 * size
SELECT *from employees LIMIT 11,1
union 联合 合并 将多条查询语句的结果合并成一个结果
语法:
查询语句1
UNION
查询语句2
UNION
…
特点:
1. 要求多表查询语句的查询列表是一致的
2. 要求多条查询语句的查的每一列的类型和熟悉怒最好一致
3. union关键字默认去重 ,如果使用union all 可以包含重复项
查询部门编号》90或邮箱包含a的员工信息
SELECT *
FROM employees
WHERE email LIKE '%a%'
UNION
SELECT *
FROM employees
WHERE department_id >90
查询总算完了 下来是插入
方式一:
语法:
INSERT INTO 表名(列名,…)
VALUES (值1,…);
SELECT *from beauty;
INSERT INTO beauty
(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,"tjk","男", '1990-4-23','19998888888',NULL,NULL);
注意:
方式二:
语法:
INSERT into 表名
set 列名= 值,
set 列名= 值,
方式1 支持多行同时插入 方式2 不支持 UPDATE 表1,表2
SET 列=值
WHERE 连接条件
and 筛选条件
sql 99语法:
UPDATE 表1 别名
INNER /LEFT /RIGHT JOIN 表2 别名
ON 连接条件
SET 列=值,
SET 列=值
WHERE 筛选条件
DELETE 表1的别名,表二的别名
FROM 表1 别名,表二 别名
where 连接条件
AND 筛选条件
sql99
DELETE 表1 的别名,表2的别名
from 表1 别名
INNER /LEFT /right JOIN
表2 别名
ON 连接条件
TRUNCATE (后面不能跟条件语句 所以是删除全表的数据的时候)
语法 TRUNCATE table 表名
数据定义语言
库和表的管理
创建: create
修改: alter
删除: drop
create DATABASE 库名;
RENAME DATABASE books to 新库名
更改库的字符集
ALTER DATABASE books CHARACTER set gbk
DROP DATABASE IF EXISTS books
)
创建表author
CREATE TABLE author
( id INT,
au_name VARCHAR(20),
nation VARCHAR(10)
);
DESC author;
表的修改
ALTER TABLE 表名
add/DROP /MODIFY /change
COLUMN 列名 类型名 约束
1.修改列名
2.修改列的类型弧或约束
3.添加新列
4.修改表名
5.删除列
ALTER TABLE book
CHANGE COLUMN
publishdate pubDate DATETIME;
ALTER TABLE book
MODIFY pubDate int ;
DESC book
ALTER TABLE author
ADD COLUMN
annual DOUBLE;
ALTER TABLE author
DROP COLUMN
annual;
ALTER TABLE author
RENAME TO book_author;
DROP TABLE if EXISTS book_author;
SHOW TABLE
CREATE TABLE author1
LIKE author;
CREATE TABLE author2
SELECT *FROM author
CREATE table author3
select
id, au_name
from author
WHERE nation="chong "
int 特点:
浮点型
所选择的类型越简单越好 能保存数值的类型越小越好
char: 固定的字符串长度
varchar:可变长度的字符串
- | 写法 | M的意思 | 特点 | 空间的耗费 | 效率 |
char | char() | 最大的字符数 | 固定长度的字符 | 比较耗费 | 高 |
varchar | varchar() | 最大的字符数 | 可变长度的字符 | 比较节省 | 低 |
其它:
BINARY 和varbinary 用于保存较短的二进制
enum用于保存枚举 但是不区分大小写 并且长度不限
set 用于保存集合
date 只有年月日
datatime 年月日 时分秒
TIMESTAMP
time 时分秒
year 年
特点:
字节 | 范围 | 时区等的影响 | |
datetime | 8 | 1000-9999 | 不受 |
TIMESTAMP | 4 | 1970–2030 | 是 |
常见约束
含义: 一种限制 用于限制表中的数据 为了保证表中的数据的准确好可靠性
分类 六大约束
CREATE TABLE 表名(
字段名 字段类型 约束
字段名 字段类型 约束
)
创建表时添加约束
1.添加列级约束
CREATE table stuinfo(
id int PRIMARY key,#主键
stuName VARCHAR(20) not NULL,#非空
gender char(1) CHECK(gender='男' or gender ='女'),#检查
seat int UNIQUE,#唯一
age int DEFAULT 18,
majorId int REFERENCES major(id)#外键
)
CREATE TABLE major(
id int PRIMARY key,
majorName VARCHAR(20)
)
CREATE table stuinfo(
id int,
stuName VARCHAR(20),
gender char(1),
seat int ,
age int ,
majorId int ,
CONSTRAINT pk PRIMARY KEY(id),
CONSTRAINT uq UNIQUE(seat),
CONSTRAINT ck CHECK(gender = '男' or gender='女'), #检查
CONSTRAINT fk_stuinfo_major FOREIGN key(majorid) REFERENCES major(id)#外键
)
主键和唯一的大对比
保证唯一性 | 是否允许为空 | 一表中可以有多个 | |
主键 | 是 | 不 | 至多有一个 |
唯一 | 是 | 是 | 可以有多个 |
外键的特点:
1.要求在从表这只外键关系
2.从表的外键列的类型好主表的关联列的类型要求一致或兼容,名称无要求
3.主表的关联类必须是一个key(主键或 唯一 )
alert table stuinfo MODIFY COLUMN stuname VARCHAR(20) not NULL
alter TABLE stuinfo MODIFY COLUMN age int DEFAULT 18
3.添加主键
ALTER TABLE stuinfo MODIFY COLUMN id int PRIMARY KEY
ALTER TABLE stuinfo ADD PRIMARY KEY(id);
4.添加唯一键
ALTER table stuinfo MODIFY COLUMN seat int UNIQUE
ALTER TABLE stuinfo ADD UNIQUE (seat)
5.添加外键
ALTER TABLE stuinfo add CONSTRAINT fk_stuinfo_major FOREIGN key(majorid) REFERENCES major(id)
ALTER table stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL
删除默认约束
ALTER table stuinfo MODIFY COLUMN age int
删除主键
alter TABLE stuinfo DROP PRIMARY key
删除唯一
ALTER TABLE stuinfo drop INDEX seat
删除外键
ALTER TABLE stuinfo DROP FOREIGN key fx_stuinfo_major
特点:
一.创建表时设置标识列
CREATE TABLE tab_identity(
id int PRIMARY key AUTO_INCREMENT,
NAME VARCHAR(20)
)
INSERT INTO tab_identity VALUES(null,'join')
SELECT *from tab_identity
二. 修改表时设置标识列
ALTER TABLE tab_identity MODIFY COLUMN id int PRIMARY KEY AUTO_INCREMENT
三. 修改表时删除标识列
ALTER TABLE tab_identity MODIFY COLUMN id int