Mysql笔记
windows安装记录Windows中Mysql安装-CSDN博客
用到的库
通过网盘分享的文件:atguigudb.sql
链接: https://pan.baidu.com/s/1YfC20c2vK9odn-XRJJwUJw 提取码: utk7
--来自百度网盘超级会员v5的分享
Mysql4中表关联关系
1.1对1,比较少用,因为完全可以一张表,当有些数据是常用的,二有些数据是不常用的情况下,可以使用1对1关系,例如员工姓名,年龄,身份证号可能是常用的,但是员工的背景,教育等人员档案是常用的,可以考虑用1对1
2.1对多.例如顾客可能有多个订单
3.多对多,必须要有中间表,例如用户和角色,中间表记录用户和角色的主键
4.自我引用(自关联),例如部门表
cmd中
可以通过
net stop mysql80或者net start mysql80
来关闭或启动mysql,这里mysql80是安装时候指定的服务名称
net stop mysql80 && net start mysql80 就是先关闭在启动
另外也可以用
sc stop mysql80和sc start mysql80 作用差不多 sc方式看到的参数多些
进入mysql
mysql -h localhost -u root -p123456 -P 3306
如果是本机可以
mysql -uroot -p123456
这里注意一点, -p后面不能有空格,mysql会误认为空格也是密码,其他都可以有空格,另外不建议密码直接写上去,如果密码不直接写上去,例如端口是13306的话
mysql -uroot -P 13306 -p 考虑为什么把-p写最后面 原因密码写出来总不好吧 那么只能放在最后
退出mysql 使用 exit或者quit
cmd中可以通过命令
mysql --version;查看mysql数据库版本
当进入mysql之后可以通过命令
select version();来查看数据库版本
show databases;查看所有数据库
create database testdb1;创建数据库,没有指定字符集,默认用的是mysql默认字符集,可以在my.ini中进行修改,mysql8不需要 但是mysql5.7或者以下 这样创建数据库没有自定字符集的话,默认就是mysql默认字符集
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
在[mysql] 和 [mysqld]下 分别如图设置 mysql8不需要
注意,这样要重启MYSQL服务才可以生效
还需要注意一点,即使你改了,但是原先创建的数据库和表的字符集还是没有改变
ALTER DATABASE dbtest1 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
SHOW CREATE DATABASE dbtest1; 查看是否已经修改
ALTER TABLE employees CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
如果是修改特定字段
ALTER TABLE employees MODIFY name VARCHAR(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
show create table employees; 查看
use dbtest1;使用dbtest1数据库
show tables;查看dbtest1数据库中所有表
create table employees(id int,name varchar(15));创建表,没有指定字符集,默认按use的数据库的字符集
insert into employees values(1001,'Tom');
insert into employess values(1002,'Han'),(1003,'Jack');
select * from employees;查看表中所有数据
insert into employess values(1004,'中国');如果不是mysql8,5.7或者以下会报错
show variable like 'datadir';可以查看DB真实数据的保存目录
show variable like 'character_%';可以查看当前mysql系统使用的字符集
show variable like 'collation_%';查看当前mysql数据库的排序规则
DROP DATABASE db1;删除库
DROP TABLE tb1;删除表及结构
DELETE TABLE tb1;逐行删除表中数据
TRUNCATE TABLE tb2;;删除表中数据,大数据删除,执行速度快,因不记录日志
#基本的SELECT语言
#SQL的分类
/*
DDL:数据定义语言:CREATE \ ALTER \ DROP \ RENAME \ TRUNCATE
DML:数据操作语言:INSERT \ DELETE \ UPDATE
DQL:数据查询语言:严格来说SELECT属于DQL,但有时也被归纳为DML
DCL:数据控制语言:GRANT(授予权限) REVOKE(撤销权限)
TCL:事务控制语言:COMMIT \ ROLLBACK \ SAVEPOINT \ SET TRANSACTION
很多时候有些人把TCL归纳为DCL,都可以
*/
#以下主要是DQL 即SELECT 数据查询
USE dbtest1;
CREATE TABLE emp(id int,name varchar(15));
INSERT INTO emp
VALUES(1002,'Tom');
INSERT INTO emp
VALUES(1003,'Jerry');
SELECT * FROM emp;
DROP DATABASE dbtest1;
#字符串,日期时间类型的变量需要使用一对''表示
#在特殊情况下,别名用双引号表示("")
/*
数据导入2种方式
1:使用source 文件的全路径名(在命令行导入,工具中不行)
2:工具导入
*/
SOURCE C:/Users/user/Desktop/asd.sql;
SHOW DATABASES;
USE atguigudb;
SHOW TABLES;
SELECT * FROM employees;
#基本SELECT语句
SELECT 1;
SELECT 9/2;
SELECT 9/2,3*3;
SELECT 9/2 a,3*3 b;
SELECT 10/3;
SELECT 9.0/2;
SELECT 1+1.3*2;
SELECT 2+2+3*2+1.1 FROM DUAL;#DUAL是伪表
#在MYSQL中可以SELECT 1; 但是在Oracle中DUAL必须写 就是说必须SELECT 1 FROM DUAL;DUAL是Oracle 中的伪表,它是一个特殊的表,默认只有一行一列。
SELECT sysdate(); #2024-12-10 06:28:31
SELECT sysdate() "select";
/*
SQL的书写顺序 SELECT...FROM...JOIN...ON...WHERE...GROUP BY...HAVING...ORDER BY...LIMIT
SQL的执行顺序 FROM...JOIN...ON...WHERE...GROUP BY...HAVING...SELECT...DISTINCT...ORDER BY...LIMIT
*/
SELECT * FROM employees;
SELECT employee_id,last_name,salary FROM employees;
#列的别名,去重,NULL,排序DESC,默认ASC,注意:列别名不能是纯数字 例如1,2,3 可以是"1","2","3"
#列的别名AS,全称ALIAS,可以省略,特殊时候使用双引号"",不要使用'',原因是MYSQL中不规范,在其他数据库就不能用单引号 规范
SELECT employee_id emp_id,last_name AS lname,department_id "部门ID",salary*12 "annual sal" FROM employees;
#去除重复行 DISTINCT 如果后面是多个字段,去重条件会将后面几个字段做一个整体去去重
SELECT DISTINCT department_id FROM employees;
SELECT DISTINCT department_id,salary FROM employees;#将department_id,salary做为整体去重
#空值一旦参与运算 结果一定也为NULL 空值:NULL
SELECT employee_id,salary "月工资",salary*(1+commission_pct)*12 "年工资",commission_pct "绩效" FROM employees
#使用COALESCE(arg1,arg2,....argn)函数,从左到右依次检查,返回第一个非NULL表达式
SELECT
employee_id,
salary AS "月工资",
salary * (1 + COALESCE(commission_pct, 0)) * 12 AS "年工资",
commission_pct AS "绩效"
FROM
employees;
SELECT COALESCE(1,2);#结果是1
#使用IFNULL(ARG1,ARG2)如果ARG1不是NULL,使用ARG1;如果ARG1是NULL,使用ARG2
SELECT
employee_id,
salary AS "月工资",
salary * (1 + IFNULL(commission_pct, 0)) * 12 AS "年工资",
commission_pct "绩效"
FROM
employees;
#着重号 `` (1左边的这个键) 有张表,表明叫order,属于关键字
SELECT * FROM order;#报错
SELECT * FROM `order`;#可以
#查询常数
SELECT "XX有限公司",employee_id,last_name,salary FROM employees;
SELECT "XX有限公司" as "company",employee_id,last_name,salary FROM employees;
#显示表结构DESC 全称DESCRIBE(描述)
DESCRIBE employees;
DESC employees;#和SHOW COLUMNS FROM employees;作用一样
#过滤数据 WHERE
SELECT * FROM employees WHERE department_id=90;
SELECT * FROM employees WHERE last_name='King';
#查询员工12个月的工资总和,并起别名为annual salary
SELECT employee_id,last_name,salary*(1+IFNULL(commission_pct,0))*12 "annual salary" FROM employees;
#算数运算符的使用 加减乘除取模(即取余) + - * /(也可以用div表示) %(也可以用mod表示)(取余)
SELECT 100,100+0,100-0,100+50,100/3,100%3,100 DIV 3,100 MOD 3 FROM DUAL;#注意100 DIV 3要有空格
SELECT 100 整数,100+0 加法,100-0 减法,100+50 加法,100/3 除法,100%3 取余,100 DIV 3 除法,100 MOD 3 取余 FROM DUAL;
可以看出 / 和div还是有区别的
#查询员工ID为偶数的员工信息
SELECT * FROM employees WHERE (employee_id%2)=0;#别用==哈
= 等于
<=> 安全等于
<>(!=) 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
IS NULL 为空运算符
IS NOT NULL 不为空运算符
LEAST 最小值运算符
GREATEST 最大值运算符
BETWEEN AND 两者之间运算符
ISNULL 为空运算符(特定数据库)
IN 属于运算符
NOT IN 不属于运算符
LIKE 模糊匹配运算符
REGEXP 正则表达式运算符
RLIKE 正则表达式运算符
#查询时候好比for循环 条件成立:1是true 不成立:0是false NULL是个什么鬼
#既然有NULL参与比较结果一定是NULL
SELECT * FROM employees WHERE commission_pct=NULL;#一条数据也没有
SELECT * FROM employees WHERE commission_pct IS NULL;#查出commission_pct是NULL的
#安全等于和普通等于的区别 = <=> 唯一区别在NULL上面 NULL参与比较都是NULL 但是在安全等于的时候就会得出结果
#安全等于<=>
SELECT 1<=>2,1 != 2,1<=>'1',1<=>'A',0<=>'A','A'<=>'B','A'<=>'A',1<=>NULL,'A'<=>NULL,NULL<=>NULL FROM DUAL;
SELECT * FROM employees WHERE commission_pct<=>NULL;
SELECT * FROM employees WHERE commission_pct IS NULL;
SELECT * FROM employees WHERE ISNULL(commission_pct);#这三句效果是一样的
#LEAST(arg1,arg2,...argn)最小 GREATEST(arg1,arg2,...argn)最大 LENGTH(String)针对于字符串长度
#查询工资在6000-8000的员工信息 BETWENN...AND...(包含边界) 针对的范围
SELECT * FROM employees WHERE salary>=6000 AND salary<=8000;
SELECT * FROM employees WHERE salary>=6000 && salary<=8000;
SELECT * FROM employees WHERE salary BETWEEN 6000 AND 8000;#注意6000 和 8000顺序不能换 第一个是下限 第二个是上线
#查询不在6000到8000之内的 NOT BETWEEN AND 不包含边界
SELECT * FROM employees WHERE salary<6000 OR salary>8000;
SELECT * FROM employees WHERE salary<6000 || salary>8000;
SELECT * FROM employees WHERE salary NOT BETWEEN 6000 AND 8000;
#IN和NOT IN 针对的具体的值
#查询部门为10,20,30部门的员工信息
SELECT * FROM employees WHERE department_id=10 OR department_id=20 OR department_id=30;
SELECT * FROM employees WHERE department_id IN(10,20,30);
#查询员工工资不是6000,7000,8000的员工信息
SELECT * FROM employees WHERE salary!=6000 AND salary!=7000 AND salary!=8000;
SELECT * FROM employees WHERE salary NOT IN(6000,7000,8000);
#LIKE模糊查询
#查询last_name中包含字符'a'的员工信息 %:0个或多个字符 _:1个字符
SELECT * FROM employees WHERE last_name like '%a%';
#查询包含a和e的
SELECT * FROM employees WHERE last_name like '%a%e%' OR last_name like '%e%a%';
#查询第二个字符是a的
SELECT * FROM employees WHERE last_name like '_a%';
#查询第二个字符就是_第三个字符是a 或者说查询第一个字符就是_第二个字符是a,此时需要用转义字符:\
SELECT * FROM employees WHERE last_name like '_\_a%';#第二个字符开始是_a
SELECT * FROM employees WHERE last_name like '\_a%';#以_开头
#除了用转义字符\ 还可以用其他的 用ESCAPE说明它是一个转义字符 最好用些特殊符号
SELECT * FROM employees WHERE last_name like '_A_a%' ESCAPE 'A';
#正则表达式 REGEXP 或者 RLIKE
#查部门是50的但是工资少于10000的或者工资大于10000但是部门不是50的 XOR:追求的不同
SELECT last_name,salary,department_id FROM employees WHERE department_id=50 XOR salary>=10000
#注意 OR可以和AND一起使用,AND的优先级高于OR 先AND再OR
#查工资不在5000到12000之间的员工的姓名和工资
SELECT last_name,salary FROM employees WHERE salary NOT BETWEEN 5000 AND 12000;
#查询在20或者50号部门工作的员工姓名和部门号
SELECT last_name,department_id FROM employees WHERE department_id IN(20,50);
#查询公司中没有管理者的员工姓名和job_id
SELECT last_name,job_id FROM employees WHERE manager_id IS NULL;
#查询公司中有奖金的员工姓名,工资和奖金级别
SELECT last_name,salary,commission_pct FROM employees WHERE commission_pct IS NOT NULL;
#查询员工姓名第三个字母是a的员工姓名
SELECT last_name FROM employees WHERE last_name LIKE '__a%';
#查询姓名中有a和k的员工姓名
SELECT last_name FROM employees WHERE last_name like '%a%k%' OR last_name like '%k%a%';
SELECT last_name FROM employees WHERE last_name like '%a%' AND last_name like '%k%';
#查询姓名以e结尾的员工信息
SELECT * FROM employees WHERE last_name LIKE '%e';
#查询部门编号在80-100之间的姓名,工种
SELECT last_name,job_id FROM employees WHERE department_id BETWEEN 80 AND 100;
#查询manager_id是100,101,110的员工姓名,工资,管理者id
SELECT last_name,salary,manager_id FROM employees WHERE manager_id=100 OR manager_id=101 OR manager_id=110;
SELECT last_name,salary,manager_id FROM employees WHERE manager_id IN(100,101,110);
#排序与分页 排序默认ASC 写不写都在
#如果没有使用排序操作,默认使用添加数据的先后顺序显示的
SELECT * FROM employees;
#按salary从高到低排序
SELECT employee_id,last_name,salary FROM employees ORDER BY salary DESC;
#列的别名只能在ORDER BY后面使用 原因在于SQL的执行顺序
#这样会报错,原因执行WHERE时候,还不知道别名annual_sal是什么
SELECT employee_id,salary,salary*12 annual_sal FROM employees WHERE annual_sal>50000;#报错
SELECT employee_id,salary,salary*12 annual_sal FROM employees ORDER BY annual_sal DESC;#没有问题
#二级排序 显示员工信息,按department_id降序排序,当department_id相同时候,按salary升序排序
SELECT employee_id,salary,department_id FROM employees ORDER BY department_id DESC,salary ASC;
SELECT employee_id,salary,department_id FROM employees ORDER BY department_id DESC,salary;#ASC可以省略不写
#分页 LIMIT
SELECT employee_id,last_name FROM employees LIMIT 0,10;
SELECT employee_id,last_name FROM employees LIMIT 10;#0的话可以省略
SELECT employee_id,last_name FROM employees LIMIT 10,10;
SELECT employee_id,last_name FROM employees LIMIT 20,10;
SELECT employee_id,last_name FROM employees LIMIT 30,10;
#显示第pageNo页面,每页显示pageSize条记录.公式:LIMIT (pageNo-1)*pageSize,pageSize;
#查看第32,33条数据
SELECT * FROM employees LIMIT 31,2
#Mysql8.0新特性 LIMIT 3 OFFSET 4 效果和LIMIT 4,3效果相同
SELECT * FROM employees LIMIT 4,3;#意思是跳过前面4条,从第5条开始,显示3条
SELECT * FROM employees LIMIT 3 OFFSET 4;#和上面效果是一样的 颠倒换下位置就行了
#查询工资最高的员工信息
SELECT MAX(salary) AS max_salary FROM employees;#这样只是查最高工资,并没有查出员工信息
SELECT * FROM employees WHERE salary=(SELECT MAX(salary) FROM employees);
SELECT * FROM employees ORDER BY salary DESC LIMIT 1;
#查询员工的姓名,部门,年薪,按年薪降序,按姓名升序显示
SELECT last_name,department_id,salary*12 annual_salary FROM employees ORDER BY annual_salary DESC,last_name;
#查询工资不在8000到17000之间的员工姓名和工资,按工资降序,显示第21到40位置的数据
SELECT last_name,salary FROM employees WHERE salary NOT BETWEEN 8000 AND 17000 ORDER BY salary DESC LIMIT 20,20;
#查询邮箱中包含e的员工信息,并先按邮箱的字节数降序,再按部门号升序
SELECT * FROM employees WHERE email LIKE '%e%' ORDER BY LENGTH(email) DESC,department_id;#可见ODER BY 数值
#关联表(多表)查询 employees表关联departments表关联locations表
#查询员工'Abel'在哪个城市工作
SELECT A.last_name,C.city FROM employees A LEFT JOIN departments B ON A.department_id=B.department_id LEFT JOIN locations C ON B.location_id=C.location_id WHERE A.last_name='Abel';
#分开查
#查'Abel'的信息
SELECT * FROM employees WHERE last_name='Abel';#得到部门department_id是80
SELECT * FROM departments WHERE department_id=80;#location_id是2500
SELECT * FROM locations WHERE location_id=2500;#Oxford
SELECT * FROM locations WHERE location_id=(SELECT location_id FROM departments WHERE department_id=(SELECT department_id FROM employees WHERE last_name='Abel'));
#为什么要分表??为了去除冗余
#笛卡尔积现象 错误原因 缺少连接条件
SELECT employee_id,department_name FROM employees,departments;
SELECT employee_id,department_name FROM employees,departments WHERE employees.department_id=departments.department_id;#用的内连接 就是两张表都有的数据
SELECT employee_id,department_name,city FROM employees,departments,locations WHERE employees.department_id=departments.department_id AND departments.location_id=locations.location_id;#用的内连接 员工表中有一个员工部门id是null
#如果查询语句中出现了多个表中都存在的字段,则必须指明此字段所在的表 从SQL优化角度,建议多表查询时,每个字段前都指明其所在的表
SELECT employees.employee_id,departments.department_name,locations.city FROM employees,departments,locations WHERE employees.department_id=departments.department_id AND departments.location_id=locations.location_id;
#起别名方式 一旦给表起了别名SELECT或WHERE中使用表名的话,则必须使用表的别名,和SQL的执行顺序有关
SELECT a.employee_id,b.department_name,c.city FROM employees a,departments b,locations c WHERE a.department_id=b.department_id AND b.location_id=c.location_id;
#多表查询的分类
#等值连接和非等值连接(根据连接条件) 自连接和非自连接(自我引用,自关联) 内连接和外连接
#1.等值连接和非等值连接
#等值连接上面已经有了 演示非等值连接
SELECT A.last_name,A.salary,B.grade_level FROM employees A,job_grades B WHERE A.salary BETWEEN B.lowest_sal AND B.highest_sal;
#自连接和非自连接
#自连接 查员id,姓名和上级id,姓名
SELECT * FROM employees;
SELECT A.employee_id,A.last_name,B.employee_id,B.last_name FROM employees A,employees B WHERE A.manager_id=B.employee_id;
#查询所有员工的last_name,department_name
#这样内连接只能查出106条数据,因为员工表中有一个员工没有部门id,而现在要查所有
SELECT
E.employee_id,
D.department_name
FROM
employees E,
departments D
WHERE
E.department_id = D.department_id;
#SQL92语法和SQL99语法
#SQL92语法的左外连接 MYSQL不支持SQL92的外连接,因此下面的会报错,(+)代表从表
SELECT
E.employee_id,
D.department_name
FROM
employees E,
departments D
WHERE
E.department_id = D.department_id(+);
#SQL99的左外连接
SELECT
E.employee_id,
D.department_name
FROM
employees E
LEFT JOIN departments D ON E.department_id = D.department_id;
#SQL99内连接 INNER JOIN 或者 JOIN效果相同
SELECT
E.employee_id,
D.department_name
FROM
employees E
JOIN departments D ON E.department_id = D.department_id;
#MYSQL不支持满外连接
#UNION 要求,字段名称可以不同,以查询的第一张表的字段名称,查询的字段个数和字段类型必须相同 返回两个查询结果集的并集,去除重复记录
#UNION ALL 要求,字段名称可以不同,以查询的第一张表的字段名称,查询的字段个数和字段类型必须相同 返回两个查询的结果集的并集,不去重
SELECT employee_id,last_name FROM employees UNION ALL SELECT department_id,department_name FROM departments;
#SQL99新特性1 自然连接 NATURAL JOIN 不用再写ON了 等值连接 生效的条件是字段名称相同 不太灵活
SELECT
employee_id,
last_name,
department_name
FROM
employees e
JOIN departments d ON e.`department_id` = d.`department_id`
AND e.`manager_id` = d.`manager_id`;#注意连接条件可以有多个
SELECT
employee_id,
last_name,
department_name
FROM
employees e
NATURAL JOIN departments d;
#SQL99新特性2 USING 生效条件 是基于两张表中 字段名称相同 的列
-- 使用 ON 进行连接
SELECT employee_id, last_name, department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id;
-- 使用 USING 进行连接
SELECT employee_id, last_name, department_name
FROM employees e
JOIN departments d
USING (department_id);
#显示所有员工的姓名,部门号和部门名称
SELECT A.last_name,A.department_id,B.department_name FROM employees A LEFT JOIN departments B ON A.department_id=B.department_id;
#查询90号部门员工的job_id和90号部门的location_id
SELECT A.job_id,B.location_id FROM employees A JOIN departments B ON A.department_id=B.department_id WHERE A.department_id=90
#查询所有有奖金的员工的last_name,department_name,location_id,city 注意 LEFT JOIN的特性决定了以左表所有为主,即使在ON里添加条件例如ON A.department_id=B.department_id AND A.commission_pct IS NOT NULL这样也不行 注意注意注意 因此一定放在WHERE后面
SELECT A.last_name,B.department_name,B.location_id,C.city FROM employees A LEFT JOIN departments B ON A.department_id=B.department_id LEFT JOIN locations C ON B.location_id=C.location_id WHERE A.commission_pct IS NOT NULL;
#查询city在Toronto工作的员工的last_name,job_id,department_id,department_name
SELECT A.last_name,A.job_id,A.department_id,B.department_name,C.city FROM employees A LEFT JOIN departments B ON A.department_id=B.department_id LEFT JOIN locations C ON B.location_id=C.location_id WHERE C.city='Toronto';
#查询所在部门名称为'Executive'的员工的部门名称,部门地址,姓名,工作,工资
SELECT B.department_name,C.city,A.last_name,D.job_title,A.salary FROM employees A LEFT JOIN departments B ON A.department_id=B.department_id LEFT JOIN locations C ON B.location_id=C.location_id LEFT JOIN jobs D ON A.job_id=D.job_id WHERE B.department_name='Executive';
#查询哪些部门没有员工
SELECT B.department_id FROM employees A RIGHT JOIN departments B ON A.department_id=B.department_id WHERE A.department_id IS NULL;
#查询哪个城市没有部门
SELECT B.city FROM departments A RIGHT JOIN locations B ON A.location_id=B.location_id WHERE A.department_id IS NULL
#查询部门名为Sales或IT的员工信息
SELECT A.*,B.department_name FROM employees A LEFT JOIN departments B ON A.department_id=B.department_id WHERE B.department_name IN('Sales','IT');
/*
函数的分类:
从函数定义角度:分为内置函数和自定义函数
不同DBMS的内置函数差异还是很大的 就是说Mysql的内置函数在Oracle中不一定可以用 差异大
Mysql内置函数从实现功能角度分类
1.数值函数
2.字符串函数
3.日期和时间函数
4.流程控制函数
5.加密与解密函数
6.获取Mysql信息函数
-------以上都是单行函数------
7.聚合函数
将以上内置函数再次分类
1.单行函数(处理单条数据,输出单条结果)
2.聚合函数(分组函数,处理多条数据,返回单个结果)
*/
#1.数值函数
#挑几个觉得重要的
#四舍五入ROUND(ARG)一个参数表示小数点后面四舍五入,返回一个整数 ROUND(ARG1,ARG2)两个参数第二个参数表示保留几位小数,然后对后面的进行四舍五入
SELECT ROUND(123.556),ROUND(123.456,0),ROUND(123.456,1),ROUND(123.456,2),ROUND(123.456,-1),ROUND(123.456,-2) FROM DUAL;
#截断
SELECT TRUNCATE(123.456,0),TRUNCATE(123.996,1),TRUNCATE(129.45,-1) FROM DUAL;
#单行函数可以嵌套
SELECT TRUNCATE(ROUND(123.456,2),0) FROM DUAL;
#字符串函数
#LENGTH(ARG1) 返回字符串个数
SELECT LENGTH("A"),LENGTH("BB"),LENGTH("CC"),LENGTH("ASDF"),LENGTH("TREWQ")FROM DUAL;
#字符串连接函数CONCAT(ARG1,ARG2,...ARGN)将ARG1,ARG2...ARGN连接 注意有NULL参与就变成NULL
SELECT CONCAT("HELLO","WORLD"),CONCAT("1","WO","222"),CONCAT("H",NULL,"WORLD"),CONCAT("HELLO","WORLD","PPP")FROM DUAL;
#INSERT(str, pos, len, new_str)索引从1开始,将字符串中指定位置的内容替换为新字符串
SELECT INSERT("FENGHONGRUI",5,5,"NIHAO") FROM DUAL;
#REPLACE(str, from_str, to_str)将原字符串str,找到对应from_str,替换成to_str,如果from_str和str中的不匹配,则不做改动
SELECT REPLACE("HELLO","LL","WORLD"),REPLACE("HELLO","L","WORLD"),REPLACE("HELLO","LE","WORLD") FROM DUAL;
#UPPER(str)将字符串转换为大写 LOWER(str)将字符串转换为小写
SELECT UPPER("hhh"),LOWER("HHhH") FROM DUAL;
#LEFT(str,len)取字符串左边的len位 RIGHT(str,len)取字符串右边的len位
SELECT LEFT("QWERT",1),RIGHT("ASDDDD",3) FROM DUAL;
#字符串填充函数 LPAD(str, len, padstr)将str填充,len填充后的字符串总长度.如果len小于str的长度,则会截断字符串.填充从左开始.RPAD(str, len, padstr)填充从右边开始
SELECT LPAD(salary,3,"*"),LPAD(salary,10,"*"),RPAD(salary,10,"*") FROM employees
#TRIM(str)移除字符串两端空格,中间无法去除
SELECT TRIM(' Hello World ') FROM DUAL;
#REPEAT(str,n)返回str重复n次的结果 SPACE(5)提供5个空格
SELECT REPEAT('H',5),SPACE(5),LENGTH(SPACE(5)) FROM DUAL;
#SUBSTR(STR,INDEX,LEN)将str从5开始 截取三个
SELECT SUBSTR("QWERTYU",5,3) FROM DUAL;
#REVERSE(STR)字符串反转
SELECT REVERSE("DCBA") FROM DUAL;
#NULLIF(STR1,STR2)比较两字符串 如果相等 返回NULL 否则返回STR1
SELECT NULLIF("ASD","ASD"),NULLIF("ASD","ADD") FROM DUAL;
#日期和时间函数
#CURDATE()返回当前年月日
SELECT CURDATE();
INSERT INTO TEST VALUES(NULL,CURDATE());
#CURTIME()返回当前时分秒
SELECT CURTIME();
#NOW()/SYSDATE()返回当前系统时间 年月日时分秒
SELECT NOW();
SELECT SYSDATE();
#UTC_DATE() 返回UTC(世界标准时间) 年月日
SELECT UTC_DATE();
#UTC_TIME() 返回UTC(世界标准时间) 时分秒
SELECT UTC_TIME();
#DAYNAME(CREATE_TIME)返回周几Wednesday
SELECT DAYNAME(CREATE_TIME) FROM TEST
#流程控制函数
#IF(VALUE,VALUE1,VALUE2)如果VALUE的值是TRUE,返回结果VALUE1,否则返回VALUE2
SELECT last_name,IF(salary>=8000,"高工资","低工资") FROM employees;
#CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2...ELSE 结果N END 别名 ELSE可以不写,那么没有匹配就是NULL
#加解密函数信息函数
#PASSWORD()在mysql8.0中启用
SELECT MD5("123456"),MD5('123456'),SHA('123456'),SHA(MD5('admin'));#SHA(MD5('admin'))Bladex的加密
#ENCODE(str, pass_str)对str进行加密pass_str为加密密钥 DECODE(crypt_str, pass_str)对加密后的crypt_str解密用相同的pass_str
#mysql8.0中已经不能用了
SELECT ENCODE("12345",1);
SELECT DECODE("12345",1);
#Mysql信息函数
#查看当前Mysql版本
SELECT VERSION();
#CONNECTION_ID()当前会话的唯一标识符
SELECT CONNECTION_ID();
#DATABASE() 或 SCHEMA()当前会话中使用的数据库名称。
SELECT DATABASE();
-- 或者
SELECT SCHEMA();
#USER() / CURRENT_USER() / SYSTEM_USER() / SESSION_USER()回当前连接 MySQL 的用户名,包含主机信息,格式为:username@hostname
SELECT USER(), CURRENT_USER(), SYSTEM_USER(), SESSION_USER();
#CHARSET(value)返回指定字符串或变量的字符集名称
SELECT CHARSET('hello');
#COLLATION(value)返回指定字符串或变量的排序规则
SELECT COLLATION('hello');
#聚合函数 聚合删除会自动去掉null
#1.常见的集合聚合函数
#2.GROUP BY的使用
#3.HAVING的使用
#4.SQL底层执行原理
#常见的集合聚合函数
#AVG / SUM 针对于数字 可以是字符串的数字
SELECT AVG(salary),SUM(salary),AVG(salary)*12 FROM employees;
#无意义
SELECT SUM(last_name),AVG(last_name),SUM(hire_date) FROM employees;
#MAX / MIN
SELECT MIN(salary),MAX(salary) FROM employees;
SELECT MIN(last_name),MAX(last_name) FROM employees;
#COUNT 计算指定字段在查询结构中出现的个数
SELECT COUNT(employee_id),COUNT(salary),COUNT(commission_pct) FROM employees;#COUNT(commission_pct)不会计算NULL值
#如果计算表中有多少条数据
#方式1:COUNT(*):没问题
#方式2:COUNT(1):没问题
#方式3:COUNT(具体字段):不一定对(该字段可能值是NULL,聚合函数会自动排除NULL的字段)
SELECT COUNT(commission_pct) FROM employees GROUP BY commission_pct
SELECT AVG(salary),SUM(salary)/COUNT(salary),AVG(commission_pct),SUM(commission_pct)/COUNT(commission_pct),SUM(commission_pct)/107,SUM(commission_pct)/35 FROM employees;
#使用COUNT(*) COUNT(1) COUNT(具体非空字段,例如ID) 哪个效率高 如果使用的MyISAM引擎没有区别 如果使用InnoDB存储引擎 效率COUNT(*)=COUNT(1)>COUNT(具体非空字段,例如ID)
#GROUP BY
#查询各个部门平均工资
SELECT department_id, AVG(salary),SUM(salary)FROM employees GROUP BY department_id;
#查询各个JOB_ID的平均工资
SELECT job_id,AVG(salary) FROM employees GROUP BY job_id;
#查询各个department_id,job_id的平均工资
SELECT department_id,job_id,AVG(salary)FROM employees GROUP BY department_id,job_id;
#在Mysql中SELECT @@SQL_MODE;STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION 可以查看是否使用严格GROUP BY模式
#后来发现SELECT @@global.sql_mode;全局是生效的,但是会话SELECT @@SQL_MODE;没有
SELECT department_id,job_id,AVG(salary)FROM employees GROUP BY department_id;
SHOW VARIABLES LIKE 'DATADIR';#查看数据库目录
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY';#全局设置
SELECT @@global.sql_mode;#查看全局设置
SELECT @@SQL_MODE;#查看会话级别设置
#注意:SELECT中出现的非聚合函数字段,必须声明在GROUP BY中.而GROUP BY中声明的字段可以不出现在SELECT中
SELECT department_id,job_id,AVG(salary)FROM employees GROUP BY department_id;#其实这样是错误的
#GROUP BY中使用WITH ROLLUP关键字 会增加一行记录AVG(salary)的平均工资 使用ROLLUP时不能同时使用ORDER BY是互斥的
SELECT department_id,AVG(salary)FROM employees WHERE department_id>80 GROUP BY department_id WITH ROLLUP;
SELECT department_id,AVG(salary) avg_sal FROM employees WHERE department_id>80 GROUP BY department_id ORDER BY avg_sal
#HAVING的使用 (作用:过滤数据)
#查询各个部门最高工资比10000高的部门信息
SELECT department_id,MAX(salary) FROM employees GROUP BY department_id HAVING MAX(salary)>10000;
#如果过滤条件中使用了聚合函数,必须使用HAVING
#查询部门id为10,20,30,40这4个部门中最高工资比10000高的部门信息
SELECT department_id,MAX(salary) FROM employees WHERE department_id IN(10,20,30,40) GROUP BY department_id HAVING MAX(salary)>10000;
SELECT department_id,MAX(salary) FROM employees GROUP BY department_id HAVING MAX(salary)>10000 AND department_id IN(10,20,30,40);
#上面两句SQL效果一样,但是department_id IN(10,20,30,40)放在WHERE后面效果好,原因是执行时机,WHERE在GROUP BY之前就已经把有些数据过滤了
#子查询(嵌套查询):子查询指一个查询语句嵌套在另一个查询语句内部的查询
#查询谁的工资比Abel高
SELECT
E2.last_name,
E2.salary
FROM
employees E1,
employees E2
WHERE
E2.salary > E1.salary #连接条件可以是等值连接和非等值连接
AND E1.last_name = 'Abel';
SELECT * FROM employees WHERE salary>(SELECT salary FROM employees WHERE last_name='Abel');
SELECT
E2.last_name,
E2.salary
FROM
employees E1
JOIN employees E2 ON E2.salary > E1.salary #连接条件可以是等值连接和非等值连接
AND E1.last_name = 'Abel';
#查询工资大于149号员工工资的员工信息
SELECT * FROM employees WHERE salary>(SELECT salary FROM employees WHERE employee_id=149);
#查询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) AND salary>(SELECT salary FROM employees WHERE employee_id=143);
#查询公司工资最少的员工的last_name,job_id,salary
SELECT last_name,job_id,salary FROM employees WHERE salary=(SELECT MIN(salary)FROM employees);
#查询与141号员工的manager_id和department_id相同的其他员工的employee_id,manager_id,department_id
SELECT
employee_id,
manager_id,
department_id
FROM
employees
WHERE
manager_id =(
SELECT
manager_id
FROM
employees
WHERE
employee_id = 141
)
AND department_id =(
SELECT
department_id
FROM
employees
WHERE
employee_id = 141
)
AND employee_id <> 141
#查询最低工资大于110号部门最低工资的部门id和其最低工资
SELECT department_id,MIN(salary) FROM employees GROUP BY department_id HAVING MIN(salary)>(SELECT MIN(salary) FROM employees WHERE department_id=110)
#多行子查询 单行子查询返回一条数据 可以用等号连接 多行子查询返回多条数据 不能再用等号连接了
#多行子查询比较操作符
/*
单行比较操作符
=
>
>=
<
<=
<>
多行比较操作符
IN 等于列表中的任意一个
ANY 需要和单行比较操作符一起使用,和子查询返回的某一个值比较
ALL 需要和单行比较操作符一起使用,和子查询返回的所有值比较
SOME 实际上是ANY的别名,作用相同,一般常用ANY
*/
SELECT employee_id,last_name,salary,department_id FROM employees WHERE salary IN(SELECT MIN(salary) FROM employees GROUP BY department_id);
#ANY/ALL
#查询其他job_id中比job_id为IT_PROG任一工资低的员工工号,姓名,job_id以及salary
SELECT
employee_id,
last_name,
job_id,
salary
FROM
employees
WHERE
job_id <> 'it_PROG'
AND salary < ANY ( SELECT salary FROM employees WHERE job_id = 'IT_PROG' );
#查询其他job_id中比job_id为IT_PROG所有工资低的员工工号,姓名,job_id以及salary
SELECT
employee_id,
last_name,
job_id,
salary
FROM
employees
WHERE
job_id <> 'it_PROG'
AND salary < ALL ( SELECT salary FROM employees WHERE job_id = 'IT_PROG' );
#查询平均工资最低的部门id(注意MYSQL中聚合函数不能嵌套,Oracle中可以)
SELECT MIN(AVG(salary)) FROM employees GROUP BY department_id;#MYSQL中不可以,Oracle中可以
SELECT department_id,AVG(salary) avg_salary FROM employees GROUP BY department_id ORDER BY avg_salary;
SELECT
MIN( avg_sal )
FROM
(
SELECT
AVG( salary ) avg_sal
FROM
employees
GROUP BY
department_id) E#这个表必须有个别名
#感觉这样反而变得复杂
SELECT
department_id
FROM
employees
GROUP BY
department_id
HAVING
AVG( salary )=(
SELECT
MIN( avg_sal )
FROM
( SELECT AVG( salary ) avg_sal FROM employees GROUP BY department_id ) E) #这个表必须有个别名)
#EXISTS和NOT EXISTS 关键字
#查询公司管理者的信息
SELECT DISTINCT A.* FROM employees A,employees B WHERE A.employee_id=B.manager_id
#方式2子查询:
SELECT * FROM employees WHERE(employee_id IN(SELECT DISTINCT manager_id FROM employees));
#方式3EXISTS:
SELECT * FROM employees E1
WHERE EXISTS(
SELECT * FROM employees E2
WHERE E1.employee_id=E2.manager_id
)
#DDL数据库创建,修改与删除
CREATE DATABASE IF NOT EXISTS TEST4 CHARACTER SET UTF8MB4;
#CHARACTER SET UTF8MB4;写不写都一样MYSQL8默认UTF8MB4 默认排序规则utf8mb4_0900_ai_ci
CREATE DATABASE IF NOT EXISTS TEST5;
SHOW DATABASES;
SHOW CREATE DATABASE TEST5;
SHOW VARIABLES LIKE 'character_%';
SHOW VARIABLES LIKE 'DATADIR';
USE TEST5;
#查看当前使用的数据库
SELECT DATABASE();
#修改数据库
ALTER DATABASE TEST5 CHARACTER SET GBK;
#删除
DROP DATABASE TEST5;
DROP DATABASE IF EXISTS TEST5;
#创建表
CREATE TABLE IF NOT EXISTS emp (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50)
);
#查看表结构
DESC emp;
SHOW COLUMNS FROM emp;#作用一样
#查看创建表的语句结构
SHOW CREATE TABLE EMP;
#查看表数据
#基于现有的表
CREATE TABLE EMP2 AS SELECT * FROM EMP;#包含表里的数据
CREATE TABLE EMP3 AS SELECT ID FROM EMP;#包含表里的数据
#只复制表结构而不要数据
CREATE TABLE new_table AS
SELECT * FROM original_table#不用*可以选择要创建的字段 可以用关联查询
WHERE 1=0;
#创建表employees_copy,实现对employees表的复制,包括表数据
CREATE TABLE EMPLOYEES_COPY AS SELECT * FROM ATGUIGUDB.employees;
#可以指定字段和字段名
CREATE TABLE new_table AS
SELECT column1 AS new_column1, column2 AS new_column2, ...
FROM source_database.source_table;
#创建表employees_copy,实现对employees表的复制,只复制结构不包括表数据
CREATE TABLE EMPLOYEES_COPY2 AS SELECT * FROM ATGUIGUDB.employees WHERE 1=2;
#INSERT INTO ... SELECT
#往EMPLOYEES_COPY2插入数据
INSERT INTO EMPLOYEES_COPY2 SELECT * FROM EMPLOYEES_COPY
#列的名称不需要相同,只要字段类型相同
#INSERT INTO EMPLOYEES_COPY2(column2,column2) SELECT xxx,xxx FROM EMPLOYEES_COPY
#修改,重命名,删除,清空表
DESC emp;
#添加一个字段
ALTER TABLE emp ADD salary DOUBLE(10,2);#默认添加到表中最后一个字段
ALTER TABLE emp ADD phone varchar(15) FIRST;#添加到第一位
ALTER TABLE emp ADD email varchar(30) AFTER phone;#指定到某个字段后面
#修改一个字段 数据类型,长度,默认值等
ALTER TABLE emp MODIFY email VARCHAR(45);#修改字段类型长度
ALTER TABLE emp MODIFY email VARCHAR(45) default 'hrui@helljs.com';#默认值
#对字段重命名
ALTER TABLE emp CHANGE salary monthly_salary DOUBLE(10,2); #修改字段名,同时也可以修改字段类型
#删除一个字段
ALTER TABLE emp DROP COLUMN email;
#重命名表两种方式
RENAME TABLE EMP TO EMPEMP;
ALTER TABLE EMPEMP RENAME EMP;
#删除表(删除表结构和数据)
DROP table emp3;
DROP table IF EXISTS emp3;
#清空表(清空数据,保留结构)
TRUNCATE TABLE EMP;
DELETE FROM EMP;
#DCL(TCL)中 COMMIT和ROLLBACK
#COMMIT:提交数据,一旦COMMIT,不能回滚
#关闭自动提交(会话级别)
SET AUTOCOMMIT=FALSE;
DELETE FROM employees_copy;
ROLLBACK;
SELECT * FROM employees_copy;
SELECT @@AUTOCOMMIT;
#开启自动提交
SET AUTOCOMMIT=TRUE;
#----------------------------------------------------------------------------
-- 开启事务
START TRANSACTION;
DELETE FROM employees_copy;
-- ROLLBACK或者COMMIT之后,事务自动结束
ROLLBACK;
-- 查询数据
SELECT * FROM employees_copy;
#----------------------------------------------------------------------------
-- 开启事务
BEGIN;
DELETE FROM employees_copy;
-- ROLLBACK或者COMMIT之后,事务自动结束
ROLLBACK;
-- 查询数据
SELECT * FROM employees_copy;
#DELETE和TRUNCATE区别是DELETE可以回滚 但是TRUNCATE无法回滚
#DDL操作不受事务影响
#DML INSERT DELETE UPDATE
USE atguigudb;
CREATE TABLE IF NOT EXISTS emp1(id int,name varchar(15),hire_date date,salary double(10,2));
SELECT * FROM EMP1;
#没有指明添加的字段,要按申明的先后顺序全量添加
INSERT INTO EMP1 VALUES(1,'HRUI','2000-12-21',5555);
#前后字段位置一致
INSERT INTO EMP1(name,salary,id,hire_date)values('HANMEIMEI',5555,2,'2222-02-02');
#指定字段
INSERT INTO EMP1(name)values('lalala');
#多条插入
INSERT INTO EMP1(id,name,salary)VALUE(3,'zhang',6666),(4,'li',7777),(5,'wang',8888);
INSERT INTO EMP1 VALUES(6,'zh','2000-12-21',6666),(7,'liLI','2000-12-21',7777),(8,'wa','2000-12-21',8888);
#将查询结果插入到表中 从某张表里查出来的数据插入
#INSERT INTO EMP1.....SELECT * FROM XXX
CREATE TABLE EMP2(id int,name varchar(15),hire_date date,salary double(10,2));
INSERT INTO EMP2(id) SELECT id FROM EMP1;
CREATE TABLE EMP3(aid int,name varchar(15),hire_date date,salary double(10,2));
INSERT INTO EMP3(aid) SELECT id FROM EMP1;#只要类型相同 字段名称没关系
select * from emp3;
select * from emp2;
select * from emp1;
#UPDATE更新数据
#UPDATE TABLENAME SET COLUMN=XXX WHERE COLUMN=XXX
UPDATE EMP1 SET hire_date=CURDATE() WHERE id=5;
#同时修改一条数据的多个字段
UPDATE EMP1 SET hire_date=CURDATE(),salary=6000 WHERE id=5;
#批量修改
#将emp1表中,姓名中包含字符'a'的提薪20%
UPDATE emp1 set salary=salary*(1+0.2) where name like '%a%';
#修改数据时,可能存在不成功的情况(可能是由于约束的影响造成)
#删除操作DELETE FROM TABLENAME WHERE 条件
DELETE FROM EMP1 WHERE id=1;
#删除数据时,也有可能因为约束的影响导致删除失败
#MYSQL8新特性:计算列,某一列的值是通过其他列计算的来
USE atguigudb;
CREATE TABLE test1(
a int,
b int,
c int GENERATED ALWAYS AS(a+b) VIRTUAL);#C就是计算列
INSERT INTO test1(a,b)
VALUES(10,20);
select * from test1;
UPDATE test1 SET a=20;
#约束 对表中字段的限制
/*
从约束的字段个数说可以分为单列约束和多列约束
从约束的作用范围说可以分为列级约束和表级约束
在表中所有字段都声明完成,在所有字段的后面声明的约束-->表级约束
从约束作用(功能)上区分:
1.not null 非空约束
2.unique 唯一约束
3.primary key 主键约束
4.foreign key 外键约束
5.check 检查约束
6.default 默认值约束
如何添加约束?
1.CREATE TABLE时候添加约束
2.ALTER TABLE时去修改删除补充
约束 是一种规则,用来限制表中数据的合法性和一致性。
索引 是一种数据结构,用于提高查询性能。
有些约束会自动创建索引:例如主键约束会自动创建唯一索引 唯一约束也会自动创建唯一索引
*/
#如何查看表中的约束
SELECT * FROM information_schema.table_constraints WHERE table_name='employees';
CREATE TABLE my_table (
id INT PRIMARY KEY, -- id为主键
name VARCHAR(255) UNIQUE -- name字段设置唯一约束
);
INSERT INTO my_table value(1,null),(2,null);#唯一索引允许多个值为NULL
#非空约束 NOT NULL 默认所有的类型的值都可以是NULL 针对于列
CREATE DATABASE dbtest13;
USE dbtest13;
CREATE TABLE test1(
id int not null,
last_name varchar(15) not null,
email varchar(25) not null,
salary decimal(10,2)
);
#用ALTER修改 注意:如果修改时候表里该字段已经有数据是NULL,会报错
ALTER TABLE test1 MODIFY salary DECIMAL(10,2) NOT NULL;
desc test1;
#非空约束 基本约束 NOT NULL 这里无法查到
SELECT * FROM information_schema.table_constraints WHERE table_name='test1';
#当插入NULL时报错
INSERT INTO test1 VALUE(1,'douyu',NULL,'50');#Column 'email' cannot be null
CREATE TABLE test2 (
id INT NOT NULL,
name VARCHAR(50) NOT NULL DEFAULT 'Unknown'#不能插入NULL,如果插入时候未指定列则默认给值
);
INSERT INTO test2(id)VALUES(1)#但是不能INSERT INTO test2 VALUES(1,NULL);不能显示给值
#唯一约束 UNIQUE 不能重复,但是可以有多个NULL 可以是某列也可以设置多列
CREATE TABLE test3(
id int unique,
last_name varchar(30),
email varchar(30) unique,
salary decimal(10,2)
)
CREATE TABLE test3(
id int,
last_name varchar(30),
email varchar(30),
salary decimal(10,2),
CONSTRAINT uk_test2_email UNIQUE(id,email)#uk_test2_email是约束名称 删除约束时候要用到约束名,这样指的是id,email整体不能是唯一(复合唯一)
)
SELECT * FROM information_schema.table_constraints WHERE table_name='test3';
INSERT INTO test3 VALUES(1,'Tom','Tom@helljs.com',5000);
INSERT INTO test3 VALUES(NULL,'TomA',NULL,5000);
INSERT INTO test3 VALUES(NULL,'TomA',NULL,5000);
INSERT INTO test3 VALUES(2,'Tom','Tom@helljs.com',5000);
INSERT INTO test3 VALUES(3,'Tom','Tom@helljs.com',5000);
INSERT INTO test3 VALUES(3,'Tom','Tom@helljs.com',5000);
#删除约束
ALTER TABLE test3 DROP INDEX uk_test2_email;
#两个作用一样
DROP INDEX uk_test2_email ON test3
#添加
ALTER TABLE test3 ADD CONSTRAINT uk_test2_email UNIQUE (id, email);#id,email整体不能是唯一
ALTER TABLE test3 MODIFY email varchar(30) UNIQUE;
#查看test3表的索引
SHOW INDEX FROM test3;
#主键约束:用来唯一标识表中的一行记录 相当于唯一约束+非空约束 一个表中只能有一个主键约束 可以创建多列复合主键
#主键名总是PRIMARY 就算自己命名了主键约束名也没用 创建主键约束时候自动创建主键索引 如果删除主键约束,自动删除索引
CREATE TABLE test4(
id int primary key,
last_name varchar(20),
email varchar(20),
salary decimal(10,2)
)
CREATE TABLE test4(
id int,
last_name varchar(20),
email varchar(20),
salary decimal(10,2),
CONSTRAINT pk_test4_id PRIMARY KEY(id)#取名 但是不会用 还是会用primary, CONSTRAINT pk_test4_id可以省略
)
CREATE TABLE test4(
id int,
last_name varchar(20),
email varchar(20),
salary decimal(10,2),
primary key(id,last_name)#复合主键 无论哪一列都不能为NULL
)
INSERT INTO test4 VALUES(NULL,'HRUI','HRUI@hellojs.com',50000);#复合主键 无论哪一列都不能为NULL
SELECT * FROM information_schema.table_constraints WHERE table_name='test4';
#ALTER TABLE时候添加主键
ALTER TABLE test4 ADD PRIMARY KEY(id);#一张表只能有一个主键
#删除主键
ALTER TABLE test4 DROP PRIMARY KEY;
#自增列 AUTO_INCREMENT 一个表只能有一个自增长列 一般与主键使用 可以和UNIQUE使用 AUTO_INCREMENT UNIQUE 也可以单独使用 自增列数据类型必须是整形
CREATE TABLE test5(
id int AUTO_INCREMENT PRIMARY KEY,#AUTO_INCREMENT PRIMARY KEY或者PRIMARY KEY AUTO_INCREMENT都可以
last_name varchar(25)
)
INSERT INTO test5 VALUES(0,'TOM');
INSERT INTO test5 VALUES(0,'TOM2');#字段上添加0或者NULL 时 自动开始从1累加
#ALTER TABLE时添加主键自增 或者添加自增
ALTER TABLE test5 MODIFY id int AUTO_INCREMENT;
#删除自增
ALTER TABLE test MODIFY id int;
#引用完整性
#外键约束 指定某个表的某个字段的引用完整性 自己觉得应该是被别人引用之后 例如部门表的主键(或唯一约束的列)被做为EMPLOYEES表的外键
#例如员工表中更新或者新增数据时候,部门id必须是部门表里存在的部门
#删除部门数据时,会检查要删除的部门ID是否被员工表引用,如果被引用则不能删除,要先删除员工表引用该部门的数据,再删除部门表的该部门数据
#一个表可以有多个外键约束,创建外键约束时,会默认创建一个普通索引
#主键约束和唯一约束会自动创建唯一索引 删除主键约束或者唯一约束会自动删除索引 外键约束会自动创建普通索引(索引名是列名) #删除外键约束后需要手动删除对应索引 但是删除表之后外键约束自动创建的普通索引也会被删除
#做为外键的列在主表中需要是主键或者唯一约束的列
#FOREIGN KEY(外键约束) 主表和从表:主表的主键被另一张表引用
#创建主表
USE atguigudb;
CREATE TABLE dept1(
dept_id int AUTO_INCREMENT PRIMARY KEY,
dept_name VARCHAR(15)
)
#创建从表
CREATE TABLE emp1(
emp_id int AUTO_INCREMENT PRIMARY KEY,
emp_name varchar(30),
department_id int,
#表级外键约束
CONSTRAINT fk_emp1_dept_id FOREIGN KEY(department_id) REFERENCES dept1(dept_id)
)
DESC emp1;
SELECT * FROM information_schema.table_constraints WHERE table_name='emp1';
#外键约束等级
CREATE TABLE emp1(
emp_id int AUTO_INCREMENT PRIMARY KEY,
emp_name varchar(30),
department_id int,
#表级外键约束 ON UPDATE CASCADE ON DELETE SET NULL 意思是当主表更新主键的时候 从表的外键跟着更新 当主表删除主键时,从表外键设置为NULL
CONSTRAINT fk_emp1_dept_id FOREIGN KEY(department_id) REFERENCES dept1(dept_id) ON UPDATE CASCADE ON DELETE SET NULL
)
#删除外键约束
ALTER TABLE 表名 DROP FOREIGN KEY 外键约束名;
#查看表的索引名
SHOW INDEX FROM 表名;
#删除添加外键时自动创建的普通索引
ALTER TABLE 表名 DROP INDEX 索引名;
#CHECK 检查约束 检查某个字段是否符合要求,一般指的是值的范围 MYSQL5.7是不支持的 从 8.0.16 版本开始支持 CHECK 约束
CREATE TABLE emp2(
id int,
last_name varchar(15),
salary decimal(10,2) CHECK(salary>2000),
gender CHAR(1) CHECK (gender IN ('男', '女'))
)
#DEFAULT约束
CREATE TABLE emp3 (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
department VARCHAR(20) DEFAULT '未分配' -- 默认部门
);
#修改添加
ALTER TABLE 表名 MODIFY 列名 数据类型 DEFAULT 默认值;
#删除
ALTER TABLE 表名 MODIFY 列名 类型;
CREATE TABLE emp4 (
event_id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 默认当前时间
);
CREATE TABLE emp5 (
event_id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) AUTO_INCREMENT=100; -- 设置自增从 100 开始
相关文章:
Mysql笔记
windows安装记录Windows中Mysql安装-CSDN博客 用到的库 通过网盘分享的文件:atguigudb.sql 链接: https://pan.baidu.com/s/1YfC20c2vK9odn-XRJJwUJw 提取码: utk7 --来自百度网盘超级会员v5的分享 Mysql4中表关联关系 1.1对1,比较少用,因为完全可以一张表,当有…...
docker拉取rabbitmq镜像安装延迟队列插件
我这里使用的是rabbitmq:3.12.0-management版本作为示例 1.拉取rabbitmq镜像 docker pull rabbitmq:3.12.0-management 2.启动rabbitmq docker run -d --namerabbitmq --restartalways -p 5672:5672 -p 15672:15672 rabbitmq:3.12.0-management 在咱们拉取时如果出现连接超时可…...
创建一个谷歌插件项目dome上线流程+源码
创建一个简单的 Chrome 扩展程序,其主要功能是 JSON 格式化。用户可以通过点击扩展图标打开一个弹出窗口,在弹出窗口中输入或粘贴 JSON 数据,然后点击格式化按钮来格式化 JSON 数据 谷歌插件(即 Chrome 扩展程序)主要设…...
举例说明如何在linux下检测摄像头设备具备的功能
假设摄像头设备文件为/dev/video1 ,下面是一个专门用于检测 /dev/video1 设备能力的简化程序。这个程序将打印出设备的所有能力、格式和其他相关信息,以帮助你了解设备支持的功能。 检测 /dev/video1 设备能力的程序 #include <fcntl.h> #includ…...
win10配置子系统Ubuntu子系统(无需通过Windows应用市场)实际操作记录
win10配置子系统Ubuntu子系统(无需通过Windows应用市场)实际操作记录 参考教程 : win10配置子系统Ubuntu子系统(无需通过Windows应用市场) - 一佳一 - 博客园 开启虚拟机服务的 以管理员方式运行PowerShell运行命令。 …...
东北大学《2024年839自动控制原理真题》 (完整版)
本文内容,全部选自自动化考研联盟的:《东北大学839自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦~ 目录 2024年真题 Part1:2024年完整版真题 2024年真题...
5G中的ATG Band
Air to Ground Networks for NR是R18 NR引入的。ATG很多部分和NTN类似中的内容类似。比较明显不同的是,NTN的RF内容有TS 38.101-5单独去讲,而ATG则会和地面网络共用某些band,这部分在38.101-1中有描述。 所以会存在ATG与地面网络之间的相邻信…...
nginx负载均衡配置
目录 一、简介 二、nginx下载 二、nginx配置 四、注意点 (1)/api与/api/的区别 (2)http://gatewayserver与http://gatewayserver/的区别 一、简介 Nginx(发音为 "engine-x")是一个高性能的HTTP和反向代理服务器,也是一个IMA…...
【教学类-83-02】20241214立体书三角嘴2.0——青蛙(扁菱形嘴)
背景需求: 制作小鸡立体贺卡三角嘴,它的嘴是正菱形(四条边长度相等,类似正方形) 【教学类-83-01】20241215立体书三角嘴1.0——小鸡(正菱形嘴)-CSDN博客文章浏览阅读744次,点赞22次…...
vscode设置终端代理
转载请标明出处:小帆的帆的博客 设置终端代理 修改项目的.vscode/settings.json {"terminal.integrated.env.windows": {"http_proxy": "http://127.0.0.1:7890","https_proxy": "http://127.0.0.1:7890"}, }…...
【C++】函数计算题解论
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目描述💯思路解析3.1 函数的递归定义3.2 边界条件控制3.3 记忆化搜索 💯C实现代码💯添加解释💯小结 💯前言 在…...
Redis篇-21--运维篇3-集群(分片,水平扩展,高可用,集群配置案例,扩展哨兵案例)
1、概述 Redis集群(Cluster)通过分片(sharding)实现了水平扩展,允许数据分布在多个节点上,从而提升性能和存储容量。 在Redis集群中,数据被分割成16384个哈希槽(hash slots&#x…...
Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材
注明:网络素材,仅供学习使用! https://download.csdn.net/download/elineSea/90017291...
深入理解addEventListener中的第二个参数:listener
起因 首先,之前留给我们的一点东西,js的深入内容关键在addEventListener,这个函数中的参数,它们三个参数,分别为type、listener、options,当然在这里还有一些小的问题,比如mdn文档中它介绍到了另…...
数据库镜像(Database Mirroring):高可用性与灾难恢复技术
一、引言 在现代信息系统中,数据的可用性和完整性至关重要,尤其是对金融、电商、医疗等高并发和高可靠性要求的行业。数据库镜像(Database Mirroring) 作为一种高可用性与灾难恢复技术,通过将主数据库的数据实时复制到…...
【Qt】按钮类控件:QPushButton、QRadioButton、QCheckBox、ToolButton
目录 QPushButton 例子: QRadioButton 例子: 按钮的常见信号函数 单选按钮分组 例子: QCheckButton 例子: QToolButton QWidget的常见属性及其功能对于它的派生类控件都是有效的(也就是Qt中的各种控件),包括…...
day-21 内核链表以及栈
1.昨日作业 1.删除指定节点 找到删除就完事了,双向可以停在删除处。 /***************************** 功能:删除指定结点(通过姓名)* 参数:phead;oldname; * 返回:成功0,失-1&…...
深度与视差的关系及其转换
深度与视差的关系及其转换 在计算机视觉和立体视觉中,深度和视差是两个重要的概念。理解这两者之间的关系对于实现立体图像处理、三维重建以及深度估计至关重要。在这篇博客中,我们将深入探讨深度和视差的概念,并介绍它们之间的转换关系。 …...
Unity全局光照详解
之前就学过但是太久没用又忘了,因此用最简洁易懂的语言做个记录。 全局光照分为两个系统,分别是实时光照和混合光照。(点击window/Rendering/Lighing打开此面板) 其中全局光照对于我来说都是新技术了,上一次学…...
外观模式的理解和实践
外观模式(Facade Pattern)是一种常用的软件设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。该模式定义了一个高层的接口,使得子系统更容易使用。简单来说,外观模式就是通过引入一个外观角色…...
【前端知识】Javascript进阶-类和继承
文章目录 概述一、类(Class)二、继承(Inheritance) 三、继承的实现方式作用一、类和作用二、继承和作用 概述 当然可以,以下是对JavaScript中类和继承的详细介绍: 一、类(Class) 定…...
Kylin麒麟操作系统 | Nginx服务部署
目录 一、理论储备1. Nginx概述2. Nginx与Apache的区别3. Nginx的服务配置 二、任务实施任务1 Nginx的编译安装1. Server配置2. 客户端测试 任务2 Nginx反向代理1. Server1配置2. Server2配置3. 客户端测试 一、理论储备 1. Nginx概述 Nginx是一个轻量级的web服务器ÿ…...
51单片机--- 串口控制仿真
51单片机--- 串口控制仿真 实验目标:51单片机接收串口数据,根据数据点亮LED。 实验步骤: 在Proteus里画出原理图 在Keil里用C语言编写程序 在Proteus中导入HEX文件,启动仿真 实验协议: 波特率115200 数据位:8位,停止位:1位,校验位:无。 命令格式: 一条命令为…...
<数据集>输电线塔杂物识别数据集<目标检测>
数据集下载链接 <数据集>输电线塔杂物识别数据集<目标检测>https://download.csdn.net/download/qq_53332949/90141102数据集格式:VOCYOLO格式 图片数量:1099张 标注数量(xml文件个数):1099 …...
HarmonyOS学习 --- Mac电脑获取手机UDID
一,手机打开开发者选项 1,打开“设置 > 关于本机”,连续点击7次版本号,打开开发者选项。 2,打开“USB调试”。 二,配置环境变量 获取OpenHarmony SDK 安装路径 /Users/admin/Library/OpenHarmony/Sdk/10…...
OpenIPC开源FPV之Adaptive-Link地面站代码解析
OpenIPC开源FPV之Adaptive-Link地面站代码解析 1. 源由2. 框架代码3. 软件配置3.1 默认配置3.2 加载配置3.3 更新配置 4. 通信例程4.1 TCP报文解析4.2 UDP报文发送 5. 特殊指令5.1 request_keyframe5.2 drop_gop5.3 resume_adaptive5.4 pause_adaptive 6. 总结7. 参考资料 1. 源…...
Linux Docker环境中解决中文字体乱码问题完整指南
问题背景 在Linux Docker环境中运行涉及中文显示的应用时(如Selenium网页截图、PDF生成等),经常会遇到中文显示为方块或乱码的问题。这是因为Linux系统默认没有安装中文字体所导致的。 解决方案 我们可以从Windows系统复制常用中文字体到D…...
[数据结构#1] 并查集 | FindRoot | Union | 优化 | 应用
目录 1. 并查集原理 问题背景 名称与编号映射 数据结构设计 2. 并查集基本操作 (1) 初始化 (2) 查询根节点 (FindRoot) (3) 合并集合 (Union) (4) 集合操作总结 并查集优化 (1) 路径压缩 (2) 按秩合并 3. 并查集的应用 (1) 统计省份数量 (2) 判断等式方程是否成…...
用于卫星影像间接RPC模型精化的通用光束法平差方法
引言 介绍了通用RPC模型的表达式,which has been down to death 描述了RPC模型产生误差的原因——主要与定义传感器方位的姿态角有关。 每个影像都会对应一个三维点云,但是对同一地物拍摄的不同影像对应出来的三维点云是不一样的,所以才需…...
关于Redis主从复制实验操作
需要搭建帮助的可以去taobao搜索Easy Company技术服务,谢谢!!! 需要搭建帮助的可以去taobao搜索Easy Company技术服务,谢谢!!! Redis主从复制需要一主二从(共三个Redis…...
【HarmonyOS】鸿蒙获取appIdentifier,Identifier
【HarmonyOS】鸿蒙获取appIdentifier,Identifier 一、前言 三方后台需要填写的所谓appIdentifier,Identifier信息,其实对应鸿蒙应用的appID。 二、解决方案: 注意,模拟器获取data.signatureInfo.appIndentifer为空…...
matplotlib(二)
目录 1、折线图(plot)与基础绘制图功能 1.1、设置图形风格 2、多坐标系显示图像 3、折线图的应用场景 1、折线图(plot)与基础绘制图功能 # import matplotlib.pyplot as plt # import random # #1.创建画布 # plt.figure(figs…...
Jenkins容器使用宿主机Docker(五)
DevOps之安装和配置 Jenkins (一) DevOps 之 CI/CD入门操作 (二) Sonar Qube介绍和安装(三) Harbor镜像仓库介绍&安装 (四) Jenkins容器使用宿主机Docker(五) Jenkins流水线初体验(六&#…...
基于前后端分离的食堂采购系统源码:从设计到开发的全流程详解
本篇文章,笔者将从系统设计到开发的全过程进行详解,帮助开发者和企业了解如何高效构建一套完善的食堂采购系统。 一、系统需求分析 在开发一套基于前后端分离的食堂采购系统前,必须对业务需求和功能模块进行详细分析,确保系统设…...
git使用教程(超详细)-透彻理解git
一.核心基础 核心概念有六个 首先请把与svn有关的一切概念暂时从你的脑海中移除掉,我们要重新认识本文所讲述的所有概念。 1.worktree worktree是一个目录,你在这里对文件进行增加、删除、修改。也就是我们常说的工作区。在git中worktree必须要与一个…...
Bugku---misc---隐写2
题目出处:首页 - Bugku CTF平台 ✨打开发现是一张图片,于是查看属性,放在010查看,这都是基本步骤了,发现里面有一个flag.rar!!!拿binwalk分析也确实存在 ✨于是按照压缩包的起始位置…...
数据仓库工具箱—读书笔记01(数据仓库、商业智能及维度建模初步)
数据仓库、商业智能及维度建模初步 记录一下读《数据仓库工具箱》时的思考,摘录一些书中关于维度建模比较重要的思想与大家分享🤣🤣🤣 博主在这里先把这本书"变薄"~有时间的小伙伴可以亲自再读一读,感受一下…...
将 Ubuntu 22.04 LTS 升级到 24.04 LTS
Ubuntu 24.04 LTS 将支持 Ubuntu 桌面、Ubuntu 服务器和 Ubuntu Core 5 年,直到 2029 年 4 月。 本文将介绍如何将当前 Ubuntu 22.04 系统升级到最新 Ubuntu 24.04 LTS版本。 备份个人数据 以防万一,把系统中的重要数据自己备份一下~ 安装配置SSH访问…...
Springboot3.x配置类(Configuration)和单元测试
配置类在Spring Boot框架中扮演着关键角色,它使开发者能够利用Java代码定义Bean、设定属性及调整其他Spring相关设置,取代了早期版本中依赖的XML配置文件。 集中化管理:借助Configuration注解,Spring Boot让用户能在一个或几个配…...
Python:类方法、实例方法与静态方法深度解析(补)
目录 一.实例变量 二.类变量 三.实例方法 四.类方法 五.静态方法 六.小结 总结 今天看程序时,发现自己好像忘了这三者的区别,所以重新写了一篇深度解析,希望之前看博客没看懂的小伙伴可以通过这个博客分清楚这三个方法。跟的是麦叔的课…...
Certimate:简化 SSL 证书管理的开源工具
引言 SSL(Secure Sockets Layer)证书对于保护网站和用户数据至关重要。然而,管理多个 SSL 证书可能变得繁琐和复杂。为了解决这个问题,Certimate 应运而生。Certimate 是一款开源的 SSL 证书管理工具,旨在简化 SSL 证书的申请、部署和续期流程。它特别适合需要管理多个域…...
rabbitMq举例
新来个技术总监,把 RabbitMQ 讲的那叫一个透彻,佩服! 生产者 代码举例 public String sendMsg(final String exchangeName,final String routingKey,final String msg) {} /*** 发送消息* param exchangeName exchangeName* param routin…...
人工智能增强的音频和聊天协作服务
论文标题:AI-enabled Audio and Chat Collaboration Services 中文标题:人工智能增强的音频和聊天协作服务 作者信息: Emil P. Andersen, Norwegian Defence Research Establishment (FFI), Kjeller, NorwayJesper R. Goksr, Sindre E. Ha…...
ctr: content digest XXX not found
1、问题描述 ctr 推送镜像到本地仓库报错 ctr: content digest sha256:b96e30ccb0a1e225493e53d4f81cb2c27183406e5f902ed43c4bf15dc6f21c9c: not found 2、问题原因 本人的平台是M1,正常情况下载镜像会自动按平台寻找版本,但是由于我下载的镜像版本没…...
java内存模型
文章目录 1.java内存模型2.重排序3.内存屏障3.1四类内存屏障指令 4.happens-before4.1 规则5.volatile5.1特性5.2规则5.3 内存语义5.4 内存屏障插入策略 1.java内存模型 java内存模型(JMM)定义了线程和主内存之间的抽象关系:线程之间的共享变…...
Java Object类与Objects类
1. Object 类 (1) Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法(public class Object)。 . (2) Object类常见方法 方法说明public String toString()返回对象的字符串形式public boolean eq…...
【目标检查】YOLO系列之:Triton 推理服务器Ultralytics YOLO11
Triton 推理服务器 1、引言2、Triton服务器2.1 什么是Triton Inference Server2.2 将YOLO11 导出为ONNX 格式2.3 设置Triton 模型库2.3.1 创建目录结构2.3.2 将导出的ONNX 模型移至Triton 资源库 2.4 运行Triton 推断服务器2.4.1 使用 Docker 运行Triton Inference Server2.4.2…...
力扣69. x 的平方根
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。 示例 1:…...
关于目标检测YOLO 各版本区别v1-v11/vX/vR
概述 YOLO(You Only Look Once,你只看一次)是一系列开创性的实时目标检测模型,它们彻底改变了计算机视觉领域。由Joseph Redmon开发,后续版本由不同研究人员迭代,YOLO模型以其在图像中检测对象的高速度和准…...
求成绩的平均值,统计低于平均分的人数
【问题描述】编写函数double average(double score[ ], int n,int *m)对存放在实型数组中考试成绩进行求平均分和低于平均分的人数,要求在主函数里面进行班级人数和成绩的输入,调用average函数进行计算成绩平均值和低于平均分的人数后,返回主…...