mysql -u用户名 -p密码
查看数据库 注意以分号结尾
show databases;
#显示所有数据库,(#是mysql注释的符号)
_____________________________________________________________________________________
SQL(Structural query language) 结构化查询语言,用于操作数据库
SQL学习的三条主线
#SQL的学习分为如下的三部分:
#DML :数据操纵语言 ---> INSERT / DELETE / UPDATE / SELECT ----增删改查
#DDL :数据定义语言 ---> CRAETE(加一个列) / ALTER (修改)/ DROP(删除) / TRUNCATE (清空)/ RENAME(重命名)
#DCL :数据控制语言 ---> COMMIT 提交数据) / ROLLBACK(回滚操作) / GRANT / REVOKE
#说到数据库,习惯上提到增删改查,数据库的增删改比较简单,查询比较难一些
#数据量大可以用limit分页显示,比如:查询五百条数据,十条十条显示
_____________________________________________________________________________________
基本的SELECT语句;
elect 查询的列 from 查询的表`
show databases;
use test1
#有些字段为 null 和java的null是一个意思就是没有赋值的意思,NULL和0是两个概念
select name myname , age as myage
from myname
#为查询后表的字段指定别名 可用 字段名 别名 的形式
#或者 字段名 as 别名 的形式
#注意所有"," 全都是半角的
#如果列的别名中想要包含空格 则用"别 名"或’别 名’引起来
#规范里要求用双引号,mysql里不严格 oracle数据库里必须是双引号
SELECT hid H_ID,gname AS "GAME NAME"
FROM girl;
#查询所有的数据库
SHOW DATABASES;
#使用指定的数据库
USE test1;
#基本的查询操作,查哪个列,哪些列
SELECT hid,gname #要查询字段
FROM girl; #要查询的表
查询的快捷键是F9
查询此表中的全部的列
SELECT *
FROM girl;
#列的别名
#可以使用一对""包裹别名
SELECT hid 'H ID',gname AS "游戏 昵称"
FROM girl;
#三类常见的数据类型:
#1数值型,java的整型浮点型
#2字符型/字符串型,姓名,街道,省份 没有严格要求说字符就是一个,字符串就是多个
#3日期型
#除此以外还有很多
#日期型和字符型变量。要使用一对 单引号来引用,只能在单引号中出现
#双引号是给列起别名是使用
#显示表结构
#对应改变表
#显示字段名 数据类型 是否为空 key default extra字段属性
#图形化界面相当于选中表以后,右键,改变表
DESC girl;
#命令行显示表结构
#或者使用命令全称
DESCRIBE girl;
比较运算
操作符 含义
= 等于(不是==)
> 大于
>= 大于、等于
< 小于
<= 小于、等于
<> 不等于(也可以是!=)
重点 : 赋值使用 :=符号
#其他比较运算符
操作符 含义
BETWEEN 在两个值之间(包含边界)
... AND ...
IN(set) 等于值列表中的一个
LIKE 模糊查询
IS NULL 空值
在sqlyog中将光标定位在某个查询语句上,就可以执行当前的查询
sql 中的字符理解成字符串
逻辑运算
操作符 含义
AND 逻辑并 (且)
OR 逻辑或 (或)
NOT 逻辑否 (非)
#mysql 刚安装完初始化的数据库有4个
#比较关键的是mysql 这里放的是系统相关的表
#用户名,密码都在这里,密码是加密过的
_____________________________________________________________________________________
#1 过滤 2 排序
#查询 test1 数据库中表 goods 中所有cat_id 是8的信息,并返回
SELECT *
FROM goods
#过滤数据
WHERE cat_id=8;
#查询shop_price > 60的货物
SELECT goods_name,cat_id,shop_price
FROM goods
#WHERE (shop_price > 3000 or shop_price < 2000) ;
WHERE shop_price != 1000;
#between …and … (在两个值之间,包含边界)
SELECT *
FROM goods
#where shop_price between 2000 and 3000;
WHERE shop_price BETWEEN 3000 AND 2000;
#包含边界时用between and 比较方便,不包含时还是使用 >=之类的操作符比较简单
#in (set ) :取值为()中的任一个
SELECT *
FROM goods
#where shop_price=2000 or shop_price=2500 or shop_price=3000;
WHERE shop_price IN( 2000,2500,3000 );
#like :模糊查询 查询goods表 goods_name 包含a的数据
SELECT *
FROM goods
#where goods_name like '%p%e%' or goods_name LIKE '%e%p%';
#此处谁like 要写全 写具体
#%号代表0个或多个字符
#oracle 在单引号引的里边是区分大小写的
#WHERE goods_name LIKE ‘%p%’ and goods_name LIKE ‘%e%’;
#查询goods_name 第二个字符是a的数据
WHERE goods_name LIKE ‘_d%’; #mysql 中 _是占位符,一个下划线代表一个字符’___d%'第四个字符是d
#什么字符都可以,任意一个字符
#查询第二个字符是,且第三个字符是a的数据
#转义字符 \
SELECT *
FROM girl
#where gname like '%\_%女';
WHERE gname LIKE '%_%女' ESCAPE '_';
#ESCAPE '_' 是指定转义字符的意思,所以转义有两种方法
#is null :空值
#is not null :非空值
SELECT *
FROM girl
WHERE gname IS NOT NULL;
SELECT goods_name, goods_id,market_price,goods_number , (market_price * goods_number) AS '可得销售总额'
#指定一个新列,字段为总额,内容是乘积
#凡是null值参与运算,结果都是null,应该明白,null就是null 不等同于0,如果想把null 当成0 可以用函数来实现
FROM goods;
#排序 分组 order by
SELECT *
FROM goods
#Order By market_price;
#Order by 默认按升序排序
#也可以自己指定排序方式
#ASC : 升序 (ascend) 也可以省略不写
#Desc : 降序 (descend)
ORDER BY market_price DESC;
#如果想在排序的同时做一些过滤操作,那么 where 不能乱放,不能放在order by 的后边
#where通常和from 挨着,
#from后边紧跟着where,order by 写的时候通常写在查询语句的最后
#查询 goods_number >10 的 market_price 降序之后的数据
SELECT *
FROM goods
WHERE goods_number>10
ORDER BY market_price DESC;
#二级排序
SELECT *
FROM goods
WHERE goods_number>10
ORDER BY market_price DESC,click_count;
#如果一级排序结果比较多,那么就可以指定二级,三级,n级排序
#就在原先的排序条件后加 ,条件即可
#可以使用别名排序
SELECT goods_name AS GOODSNAME #指定别名
FROM goods
WHERE goods_number>10
ORDER BY GOODSNAME; #按别名排序
_____________________________________________________________________________________
#实现多个表之间的查询
#涉及到多个表连接
#多表连接,多表查询
#为什么不把所有信息都放一张表里,乱,杂,管理起来不方便,如同java中类
#create database 学生信息;
USE 学生信息;
SELECT 姓名,对应地址
FROM 基本信息,区域表;#30行 6*5=30
#以上查询是错误的,称这种错误为:笛卡尔集错误。
#没有写两个表的连接条件,或写条件了,但失效了
#如果多表连接中,没有声明多表连接条件或连接条件失效。
#直角坐标系,又叫笛卡尔坐标系
SELECT 30/6
FROM DUAL;
#dual是虚拟表
#正确的,多表连接,一定会有连接条件
USE 学生信息;
SELECT 姓名,对应地址
FROM 基本信息,区域表
#连接条件
WHERE 基本信息.`区域编号`= 区域表.`区域编号`;
#关联的语法是 表1.字段名=表2.字段名,如果两个字段名相同,则关联成功
#满足连接条件的显示出来了,
#错误示范
USE 学生信息;
SELECT 姓名,对应地址,区域编号#此时这个区域编号是基本信息表里的呢,还是区域表里的呢
#产生了二义性,所以报错ambiguous,此时的解决办法是指定具体的表
#用表.区域编号来表示
#select 后边的两个字段 姓名和对应地址都唯一的存在对应的两个表中,很好查找
#如果查询的列在多个表中都出现
#则一定要指明此列所属的表
#最好是查询时每一列都指明表,
#从SQL优化的角度说,指定所属表的字段效率比较高
#mysql高级课中有优化等其他操作
FROM 基本信息,区域表
WHERE 基本信息.`区域编号`= 区域表.`区域编号`;
#ambiguous 不确定的模糊的
#表的别名
USE 学生信息;
SELECT e.姓名 , d.对应地址
FROM 基本信息 AS e ,区域表 d
#连接条件
WHERE e.`区域编号`= d.`区域编号`;
#如果指定别名则用别名操作,不能用原有名称操作,指定别名也可用AS
#列的别名只能使用在 order by,其他地方不好使
#所以说列的别名只能用来排序,不能用来过滤
#查询具体地址操作三个表
SELECT e.姓名 , d.`区域编号` ,f.具体地址
FROM 基本信息 AS e , 区域表 AS d , 地址表 AS f
WHERE e.`区域编号`=d.`区域编号`
AND d.`地址编号`=f.`地址编号`;
#三个表写两个连接条件
#等值连接,两个表必须有共同字段
#总结1:如果有N个表做查询操作,那么连接条件至少有N-1个
#总结2:表的连接分类
#等值连接 VS 非等值连接
#自连接(自己连接自己) VS 非自连接(自己连接别人)
#内连接 VS 外连接
#非等值连接基本信息
SELECT 基本信息.`姓名`,基本信息.`年龄`,工资等级.`等级`
FROM 基本信息,工资等级
#where 基本信息.`工资`>=工资等级.`从` and 基本信息.工资<=工资等级.到;
#协程between and 比较清晰
WHERE 基本信息.工资 BETWEEN 工资等级.从 AND 工资等级.`到`
#查询完对结果工资等级进行降序排序
ORDER BY 工资等级.`等级` DESC;
#以上写的都是非自连接
#自连接(自己连接自己)
#查询 每个员工及其管理者的信息
SELECT emp.工号 ,emp.`姓名` , mgr.`工号`,mgr.`姓名`
FROM 基本信息 emp , 基本信息 mgr
#操作两个表,实质是一个表
WHERE emp.`上司工号`=mgr.`工号`;
#查询完输出顺序发生了改变
#这是个没用的例子
SELECT 基本信息.`工号`,基本信息.`上司工号`
FROM 基本信息;
#内连接:内连接: 合并具有同一列的两个以上的表的行
#结果集中不包含一个表与另一个表不匹配的行
#内连接:只查询连接条件能匹配的行的信息,
#结果集中不包含不匹配的行
USE 学生信息;
SELECT e.姓名 , d.`地址编号`
FROM 基本信息 AS e ,区域表 d
#连接条件
WHERE e.`区域编号`= d.`区域编号`;
#此表中 贝贝的区域编号为空,所以被过滤掉了
#外连接: 两个表在连接过程中除了返回满足连接条件的行
#以外还返回左(或右)表中不满足条件的行 ,
#这种连接称为左(或右) 外连接。没有匹配的行时,
#结果表中相应的列为空(NULL).
#外连接
#左外连接 :除了能查询到满足连接条件能匹配的信息行之外,还能查到左表中不满足条件的信息
#右外连接 :除了能查询到满足连接条件能匹配的信息行之外,还能查到右表中不满足条件的信息
#外连接查询到数据的数量要大于等于内连接查询到的数据的数量
#USE 学生信息;
#SELECT e.姓名 , d.`地址编号`
#FROM 基本信息 AS e ,区域表 d
#连接条件
#WHERE e.`区域编号`= d.`区域编号`(+); #使左右表长度一样
#oracle比较简单,加个+就表示左外连接,而mysql不能实现
#查询所有员工的姓名,地址编号(有人地址编号为空)
#mysql 外连接只能借助join on,其他连接,join on 和 where都可以
#sql 99的语法,规定了另一种方式,实现多表的连接
#内连接
SELECT e.姓名 , d.`地址编号`
FROM 基本信息 e JOIN 区域表 d
#连接条件
ON e.`区域编号`=d.`区域编号`;
SELECT 工号`区域表`,姓名,地址编号
FROM 基本信息 j JOIN 区域表 q #加入一个表
ON j.`区域编号` = q.`区域编号`; #连接条件
#where....如果还有过滤条件加where
#三个表的内连接
SELECT 工号`区域表`,姓名,q.地址编号
FROM 基本信息 j JOIN 区域表 q #加入一个表
ON j.`区域编号` = q.`区域编号` #连接条件
JOIN 地址表 AS l
ON q.`地址编号`=l.`地址编号`;
#join
#on 多个表就 一直join on 下去
#加入INNER 关键字,同样表示内连接
SELECT 工号`区域表`,姓名,q.地址编号
FROM 基本信息 j INNER JOIN 区域表 q
ON j.`区域编号` = q.`区域编号` #连接条件
JOIN 地址表 AS l
ON q.`地址编号`=l.`地址编号`;
#使用sql 99语法实现外连接
#在 JOIN 的左侧加入 LEFT OUTER 叫左外连接
SELECT 工号`区域表`,姓名,地址编号,q.`区域特色`
FROM 基本信息 j LEFT OUTER JOIN 区域表 q #加入一个表
ON j.`区域编号` = q.`区域编号`; #连接条件
#where....如果还有过滤条件加where
#列出左表的全部信息
#右外连接
SELECT 工号`区域表`,姓名,地`区域表`址编号,q.`区域特色`
FROM 基本信息 j RIGHT OUTER JOIN 区域表 q #加入一个表
ON j.`区域编号` = q.`区域编号`; #连接条件
#where....如果还有过滤条件加where
#把两个表匹配的信息列出来后,把右表中不满足条件的也列出来
#相当于列出右侧表的全部信息
#即包含左表不满足的,又包含右表不满足的
#满外连接:除了查询到满足连接条件能匹配的行的信息之外,
#还能查询到左表和右表中不满足条件的信息。
#oracle支持满外连接。使用full关键字实现,mysql不支持
#mysql 如果想实现同样的功能,只能多个表去求unio,并
#SELECT 工号`区域表`,姓名,地`区域表`址编号,q.`区域特色`
#FROM 基本信息 j full OUTER JOIN 区域表 q #加入一个表
#ON j.`区域编号` = q.`区域编号`; #连接条件
SELECT 工号`区域表`,姓名,地`区域表`址编号,q.`区域特色`
FROM 基本信息 j RIGHT OUTER JOIN 区域表 q #加入一个表
ON j.`区域编号` = q.`区域编号`; #连接条件
_____________________________________________________________________________________
#单行函数
#sql 类似于java 中的方法
#y=f(x1,x2…n)
#单行函数:一个输入一个输出的函数叫单行函数
#多行函数:多个输入一个输出的函数叫多行函数
#行 : 表中的一行数据
#进去一行出来一行,就是单行函数
#进去多行,出来一行,就是多行函数 进去多个工资,出来一个最高的
#单行函数 操作数据对象
#单行函数
#数据库对象:表(table) 视图(view)索引(index)
#序列(sequence) 函数(FUNCTION) 存储过程(PROCEDURE) 触发器(trigger)
#像java 类一样
#视图:不同于表,视图修改对应数据,会更新源数据
#索引:为了快速查找,表中数据达到几十万条,快速找到想要的,可以为表创建索引
#序列:添加数据时,让序列自动添加,每次隔着几个数,比如 1 3 5 7
#函数,类似于java无返回值的方法
#存储过程,类似于java有返回值的方法
#触发器:做如下类似的操作,删除数据时每删除一条触发一条,可以用作复制,备份
#工作中 不是做DBA 所以不用深究函数这三个结构
#字符函数
SELECT 'hello','heLLo',LOWER('heLLo'),UPPER('hello')
FROM DUAL; #没有存在任何表中就写一个DUAL
USE 基本信息;
SELECT *
FROM 基本信息
WHERE LOWER(姓名) = LOWER('KING');#假如数据库是时小写的
#sql 标准严格字符区分大小写 mysql 并没有这么严格,忽略了大小写
SELECT CONCAT('AAA','bbb','ccc')
FROM DUAL;
#xxx worked for xxx
SELECT CONCAT(emp.`姓名` ,' worked for ' , mgr.`姓名`) AS '工作信息'
FROM 基本信息 emp , 基本信息 mgr
#操作两个表,实质是一个表
WHERE emp.`上司工号`=mgr.`工号`;
#该方法特点是 从第二个参数开始,取第三个参数长度的子串
SELECT SUBSTR('HelloWorld',2,5)#mysql 索引位置是从1 开始的
#java JDBC操作数据库,一些api中的数据库索引也是从1开始
FROM DUAL;
#LENGTH() 长度
#INSTR() 字符在串中首次出现的位置,没有出现则输出0
#LPAD()
SELECT INSTR('helloworld','l')
FROM DUAL;#3
#LPAD("he",10,' ') 右对齐 十位,不足补' '
#RPAD('he',10,' ')左对齐
#TRIM('h' FROM 'helloh' ) 取什么都可以,这里去了收尾的h
FROM DUAL;
SELECT TRIM(' ' FROM 'helloh')
FROM DUAL;
#REPLACE('abcd','b','m') 替换了,全部被替换
#数学函数
SELECT ROUND(12.345,0),ROUND(12.345,2),ROUND(12.34,-1)
FROM DUAL;
#ROUND 四舍五入 第三个参数是-1时,结果是10 2被四舍五入了
#第三个参数如果是0可以去掉,是默认行为
SELECT TRUNCATE(12.345,0),TRUNCATE(12.345,2),TRUNCATE(12.34,-1)
FROM DUAL;
#truncate()是截断 以上结果分别为 12 12.34 10
#MOD(12,5) 求余可以有正负情况
SELECT MOD(12,7),MOD(-12,7),MOD(12,-7),MOD(-12,-7),MOD(12.3,3)
FROM DUAL;
#以上结果 5 -5 5 -5 0.3
#日期函数
#函数now() 返回:日期,时间
SELECT NOW() , DATE(NOW()),
TIME(NOW()),SECOND(NOW()),MINUTE(NOW()),HOUR(NOW()),
DAY(NOW()),MONTH(NOW()) , YEAR(NOW())
FROM DUAL;
#通用函数
SELECT (goods_price*IFNULL(goods_number,0))
#ifNULL(expr1,expr2) 如果第一个参数是0,那么就拿第二个参数替换第一个参数
FROM DUAL;
#oracle 使用的是nvl替换
#条件表达式
#case WHEN then then then else end
#查询所有员工信息,
#若其年龄 打印其工资的10倍
#若其年龄 打印其工资的20倍
#若其年 打印其工资的30倍
#若是其他年龄 打印其工资
#格式如下:
SELECT 工号,工资,CASE 年龄 WHEN 10 THEN 工资*10
WHEN 20 THEN 工资*20
WHEN 30 THEN 工资*30
ELSE 工资 END AS '新工资'
FROM 基本信息; #可以没有ELSE
#where 。。。 可以指定where过滤
#case when then 之间没有任何标点
#多行函数(分组函数)
#比如查询工资最大值
#常用分组函数:avg() sum() max() min() count()
#avg() sum() 只针对数值型变量操作,其他类型不可以
#不可以操作字符型,日期型变量
#求工资平均值,和
SELECT AVG(工资) ,SUM(工资)
FROM 基本信息;
#mysql 对某些无意义操纵不报错,这一点oracle做的比较好
#max() , min() 针对数值型,字符型,日期型操作
SELECT MAX(工资),MIN(工资),MAX(姓名) , MIN(姓名)
FROM 基本信息;
#count() 计算指定列数据中非空数据的个数
SELECT COUNT(姓名) ,COUNT(NULL),COUNT(1),COUNT(*)#1取出一条数据看看是不是NULL,
FROM 基本信息;
#avg=sum/count 他们求的都是非空数据不考虑控制
SELECT AVG(工资) , SUM(工资), SUM(工资)/COUNT(工资)
FROM 基本信息;
#sum(工资)/count(*) ,AVG(IFNULL(工资,0))
#group by 实现对各个部门进行分组计算各个组的平均工资
SELECT department_id,AVG(salary)
FROM employees
GROUP BY department_id;#按组id进行分组求平均
#比如国家计算我国各个行业的平均工资是多少
#学校计算每个院系收的总学费是多少
#group by 指定要分组的列即可
SELECT COUNT(姓名),区域编号#求各个区域的人数
FROM 基本信息
GROUP BY 区域编号;
#不同部门,不同工种的平均工资
SELECT department_id,AVG(salary)
FROM employees
GROUP BY department_id,job_id;
SELECT department_id,AVG(salary)
FROM employees
###这种写法即使能出来数据,但不是正确的
###没有什么意义 mysql这么写不报错,oracle 会报错
#凡是在select 中,有组函数 也有非组函数
#要求,非组函数一定要出现在我们的group by当中
#错误的
SELECT department_id,AVG(salary)
FROM employees
GROUP BY department_id;
#正确的:反之,出现在group by中的列可以不声明在select中。
SELECT department_id,AVG(salary)
FROM employees
GROUP BY department_id,job_id;
#在select 中有组函数和非组函数的列,那么非组函数的列一定要在group by 中声明
#进行这组操作
#having
#非法使用组函数
#部门最高工资比10000高的部门
SELECT department_id,MAX(salary)
FROM employees
#where max(salary)>10000
#出错了,凡是在过滤条件中,使用组函数的话,那么需要使用
#having 替换掉where
GROUP BY department_id;
#orcale这样写可以,但是mysql不行
SELECT department_id,MAX(salary)
FROM employees
HAVING MAX(salary) >10000
GROUP BY department_id;
#mysql要求把having声明在group by的 后边,oracle没有此要求
SELECT department_id,MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary) >10000;
#查询 10 20 30 40 50部门中,哪些部门的最高工资比10000高
#效率低
SELECT department_id,MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary) >10000 AND department_id IN (10 ,20 , 30 , 40 ,50);
#这种写法不会报错,但是不建议这么写
#如果有多个过滤条件,必须将分组函数的过滤条件写在having中。
#另外,不包含组函数的过滤条件建议写在where中。因为写在where中效率更高
#sql优化,效率高
SELECT department_id,MAX(salary)
FROM employees
WHERE department_id IN (10 ,20 , 30 , 40 ,50)
#where在全表检索的时候就已经开始过滤
#having 全表检索完以后才开始过滤,效率低。
GROUP BY department_id
HAVING MAX(salary) >10000 ;
#总结:
#至此,关于关键字的使用在select中就已经结束了
#select 。。。。。,。。。。。,。。。。。别名
#from 。。。,。。。,。。。。 join 。。。。。
#on 。。。。。。。。。。。。。
#join 。。。。。。。。。。。。
#where 多表的连接条件
#and 非组函数的过滤条件
#group by 。。。。。。。。。
#having 。。。。。。。。。。
#order 。。。。。。。。。。。
#limit 。。。。。。。。。。。 分页
_____________________________________________________________________________________
#子查询,就是嵌套select ,嵌套多层,有时可以优化
#谁的工资比 张三高
#方式一:
#多次查询
USE 学生信息;
SELECT 姓名,工资
FROM 基本信息
WHERE 姓名='张三';
SELECT 姓名,工资
FROM 基本信息
WHERE 工资 > 1034;
#方式二:
#自连接
#并不是所有问题都是自连接都能解决的
SELECT j2.`姓名`,j2.`工资`
FROM 基本信息 AS j1, 基本信息 AS j2
WHERE j1.`姓名`='张三'
AND j1.工资
#方式三
#子查询
#在java jdbc 调用服务器后台数据库时,力求
#简洁,能一次做完的事情,绝不分成两次做完。
SELECT 姓名,工资
FROM 基本信息
WHERE 工资 > (
SELECT 工资 #不能写多余的信息
FROM 基本信息
WHERE 姓名='张三'
);
#两个以上嵌套的查询都叫子查询
SELECT 姓名,工资
FROM 基本信息
WHERE (
SELECT 工资 #不能写多余的信息
FROM 基本信息
WHERE 姓名='张三'
)<工资;
#也可以这么写,但是看着很别扭
#一般都是把轻量级的变量放在where 位置
#子查询分类
#单行子查询:返回一行查询记录
SELECT 姓名,工资
FROM 基本信息
WHERE (
SELECT 工资 #不能写多余的信息
FROM 基本信息
WHERE 姓名='张三'
)<工资;
#由内向外
#多行子查询:返回多行查询记录
#返回 基本信息表中区域编号和斯蒂文相同,
#工资比小倩多的员工的姓名,工号,和工资
#解决方式,1 从外往里写, 2 从里往外写
SELECT 姓名,工号,工资
FROM 基本信息
WHERE 区域编号=(
SELECT 区域编号
FROM 基本信息
WHERE 姓名='斯蒂文'
)
AND
工资>(
SELECT 工资
FROM 基本信息
WHERE 姓名='小倩'
);
#一般来讲 从里往外写 比较简单一些
#从外往里写,不可以测试
#返回公司工资最少的员工的姓名,工号,工资
SELECT 姓名,工号,工资
FROM 基本信息
WHERE 工资=
(
SELECT MIN(工资)
FROM 基本信息
);
#返回公司工资第二少的员工的姓名,工号,工资
SELECT 姓名,工号,工资
FROM 基本信息
WHERE 工资=(
SELECT MIN(工资)
FROM 基本信息
WHERE 工资>(
SELECT MIN(工资)
FROM 基本信息
)
);
#自查询中带有having
#查询最低工资大于60号部门最低工资的部门id和其最低工资
SELECT department_id ,MIN(salary)
FROM empoyees
GROUP BY department_id
HAVING MIN(salary)>(
SELECT MIN(salary)
FROM employees
WHERE department_id=60
)
AND department_id IS NOT NULL;
#看的时候也由内往外看,说的时候从外往里说
#要学会英汉互译
#非法使用子查询
#…
SELECT employee_id, last_name
FROM employees
WHERE salary = #这里应该用In
(SELECT MIN(salary)
FROM employees
GROUP BY department_id);
**#子查询中的查询结果空值问题**
SELECT last_name, job_id
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE last_name = 'Haas');
#公司没有这个工种以及这个人,查无此人
#多行子查询,可以使用的操作符为:in any all
SELECT employee_id, last_name
FROM employees
WHERE salary IN
(SELECT MIN(salary)
FROM employees
GROUP BY department_id);
#any
#题目:返回其它部门中比job_id为‘IT_PROG’部门任一工资低的员工的员
#工号、姓名、job_id 以及salary
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary < ANY # any
(SELECT DISTINCT salary
FROM employees
WHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';
###############
##DISTINCT去重#
###############
#题目:返回其它部门中比job_id为‘IT_PROG’部门任意工资低的员工的员
#工号、姓名、job_id 以及salary
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary < ALL # any
(SELECT DISTINCT salary
FROM employees
WHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';
#最困难的就是子查询
#查询工资比公司平均工资高的员工的员工号,姓名和工资。
SELECT employee_id,last_name,salary
FROM employees
WHERE salary>(
SELECT AVG(salary)
FROM employees
);
#*.查询各部门中工资比本部门平均
#工资高的员工的员工号, 姓名和工资
#相关查询
#方式一:
SELECT employee_id,last_name,salary
FROM employees e1
WHERE salary>(
#查询送进来的员工所在部门的平均值
SELECT AVG(salary)
FROM employees e2
WHERE e1.`department_id`=e2.`department_id`
);
#外边先送进来一条数据
#里边判断,和送进来的比较一下然后再送出去
#方式二:子查询不止可以出现在where过滤条件中
SELECT employee_id,last_name,salary #下边相当于新制作了一张表
FROM employees e1,(SELECT department_id,AVG(salary) dept_avg_sal FROM
employees GROUP BY department_id) d)
WHERE e1.`department_id`=d.dept_avg_sal;
#子查询不仅可以写在where 里,能写的地方比较多
#group by 这块不能写其他地方都可以写
#排序这块也可以写
#可以在order by 中也使用子查询
#查询员工的姓名,部门id,要求按照部门名排序
SELECT last_name,department_id
FROM employees e
ORDER BY (
SELECT department_name
FROM departments d
WHERE e.`department_id`=d.`department_id`
);
#查询管理者是King 的员工的姓名和工资
SELECT last_name,salary
FROM employees
WHERE manage_id IN(
SELECT employee_id
FROM employees
WHERE last_name='King'
);
#查询平均工资最低的部门信息
#单行函数可以嵌套,多行行数,分组函数不可以嵌套
#oracle可以嵌套
SELECT MIN(AVG(salarg))
FROM employees
GROUP BY department_id
#mysql 写法
SELECT *
FROM departments
WHERE department_id=(
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 ) dept_avg_sal
)
);
#查询平均工资最低的部门的信息和该部门的平均工资
SELECT d.*,(SELECT AVG(salary) FROM emeployees e WHERE e.department_id=d.`department_id`) "部门平均工资"
FROM departments d
WHERE department_id=(
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 ) dept_avg_sal
)
);
#各个部门中 最高工资中最低的那个部门的 最低工资是多少?
#加入有三个部门 最高工资分别是 8000 9000 10000, 那么本题求的是8000那个部门的最低工资
SELECT MIN(salary)
FROM employees
WHERE department_id=(
SELECT department_id
FROM employees
GROUP BY department_id
HAVING MAX(salary)=(
SELECT MIN(max_sal)
FROM (
SELECT MAX(salary) max_sal
FROM employees
GROUP BY department_id
) dept_max_sal
)
)
#分号问题,如果把下边的全部选中,那么会逐个执行插入操作
#分号表示单独一条的执行语句,单独一行的代码写不写分号都无所谓
INSERT INTO ....;
INSERT INTO ....;
INSERT INTO ....;
INSERT INTO ....;
_____________________________________________________________________________________
#写查询时最好一次性都做完,一次性搞定
#查询不可不免的使用子查询
#sql三条主线
#DML :inset、update ,delete,select
#DDL : create、alter、drop、truncate、rename
#dcl :commit、rollback
#主要学ddl
#显示所有的数据库
SHOW DATABASES;
#使用指定的数据库
USE 学生信息;
#显示所有的表
SHOW TABLES;
#创建表 (create table)
#方式一:"白手起家的方式",自己一点点搭建起来
#HOW TO CREATE TABLE ?
#CREATE TABLE
CREATE DATABASE AAA;
USE AAA;
#设计每个字段
#列,即字段,要指定字段的数据类型
#数据类型 等比java严格
#设置长度10位 最大9999999999
#字符型
#工资,总长度是10,其中2位是小数
#入职时间,日期型
#开发中创建表的方式
CREATE TABLE myemp1(
emp_id INT(10) AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(15),
salary DOUBLE(10,2),
hire_date DATE
);
SELECT * FROM myemp1 ;
DESC myemp1;
##################
#AUTO_INCREMENT # 自增长,创建一个自己增加
##################
#PRIMARY KEY # 设置主键 保证自动添加的数是唯一的
##################
#平时创建表的时候,用到约束,
#方式二: “基于现有的表,创建新的表”,创二代,富二代
CREATE TABLE myemp2
AS #列的别名充当新创建键的表的列名
SELECT employee_id emp_id ,last_name,salary #emp_id是列的别名,创建别名后新表中使用这个别名作为字段
FROM employees;
#从原有的表中复制出来三个字段供myemp使用
#原表的类型和存储范围也同步的复制过来了
#并不是所有内容都会被赋值过来
#约束并不是能被复制过来的
#此种方式创建表的同时,还可以将原有表的数据赋值过来
SELECT *
form myemp2;
#不能覆盖,所以要写个别的名
CREATE TABLE myemp3
AS
SELECT employee_id emp_id ,last_name,salary
FROM employees;
WHERE department_id IN (50 , 60 , 70,80)
AND salary > 5000;
#可以根据自己的想法,创造很多的新表
CREATE TABLE myemp4
AS
SELECT department_id ,AVG(salary)
FROM employees
GROUP BY department_id;
#####基于多表创建新表
CREATE TABLE myemp5
AS
SELECT department_name ,AVG(salary)
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY department_name;
#复制 employees
CREATE TABLE employee_copy
AS
SELECT *
FROM employees; ##约束有一些问题
#复制 employees ,但是数据为空
CREATE TABLE employee_blank
AS
SELECT *
FROM employees; ##约束有一些问题
WHERE 1=2; #写个不成立的条件
#创建表涉及到一些常用的数据类型
#varchar()
#不写长度会报错 通常用这种可变长度的
#视频,图片都是以blog形式存储的
#有多种不同的blog
#改变表
USE aaa;
CREATE TABLE myemp1(
emp_id INT(10) AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(15),
salary DOUBLE(10,2),
hire_date DATE
);
#修改表 (alter table)
#1添加一个列
ALTER TABLE myemp1
ADD email VARCHAR(25);
DESC myemp1;
#ora varchar2 mysql varchar
#修改现有的列
ALTER TABLE myemp1
MODIFY salary DOUBLE(15,2) DEFAULT 2000; #default 用于设置默认值
#modify用于修改表字段
#删除现有列
ALTER TABLE myemp1
#不能用delete,delete用于删数据
#这里用drop 删除结构
DROP COLUMN email; #colum叫列
#重命名列
#可以同时改变列数据类型
#和ora 不一样
#change
USE aaa;
ALTER TABLE myemp1
CHANGE salary my_sal DOUBLE(10,2);
#oracle 的写法 :
#alter table myemp1 rename salary to mysal;
#修改四个事情 完毕
#删除表
DROP TABLE myemp1;
#重命名表
ALTER TABLE emp3
RENAME TO myemp1;
#oracle : rename myemp3 to emp3;
SELECT * FROM myemp3;
SELECT * FROM emp3;
#最后一个操作
#清空表
#清空表:将表中所有的数据清空,表结构仍然保留
#truncate table
一旦将数据删除,数据不可回滚
#delete from
: 删除操作支持回滚 增删改的删
COMMIT; #提交数据
#前边做的任何修改都提交,
#之前做的修改都保存下来
##DCL
#将数据设置为不能自动提交
USE 学生信息;
SET autocommit=FALSE;#不让数据提交
DELETE FROM 地址表;
SELECT * FROM 地址表;
ROLLBACK ; #回滚数据
ROLLBACK ;#只会回滚到最近的一次commit之后,他俩是成对出现的
#############
COMMIT;
SET autocommit=FALSE;
TRUNCATE TABLE test1.`result`; ##不可回滚数据,也可以理解为自动提交数据
#一旦执行不可找回
ROLLBACK;
SELECT * FROM test1.`result`;
回滚这里有坑
#有时无法回滚
#解决办法
https://blog.csdn.net/noaman_wgs/article/details/52121991
_____________________________________________________________________________________
#pl/sql专门的数据库操作语言,
#增删改查中查询最复杂也最重要
#和数据库交互时,力求查询命令写的干净利落,一次能完成的事情,绝不两次做完
#相关子查询是里边和外边有相关性,外边传进去,里边再传出来,用到子查询
#创建管理表要简单一些,创建表有两种方式,白手起家,和拷贝
#修改表有四个指令,添加列,修改列,删除列等,修改列名操作比较少,一般情况下数据库表字段都是一次成型,改列名的操作很少去做
#存储范围从小改大不会对原数据造成影响,由大改小会造成数据丢失,报错
#数据类型也可以修改,本身已经有数据,由double改data 那么不匹配,在oracle报错,表中没数据可以改,在mysql中不报错
#如果里边有数据,也会改成功,会清空数据。这一列数就全没有了。
#清空表turnccate table,不可回滚
#表非常确定,想要删除,用trunccate table
#delete from 中间环节是删一删,修改一下,不确定。
#增删改都可回滚。及时commit 提交数据 省着回滚的特别远,造成数据损失
#函数 格式很重要
#sql 不难,需要多写
#没有很长的代码,撑死几十行
#投入了会心疼,会努力
#group by 后不要写子查询
#数据处理 之 增删改
#增 (添加) -----INSERT INTO
DROP TABLE aaa.`myemp1`;
USE aaa;
CREATE TABLE myemp(
id INT,
nam VARCHAR(10),#可变必须指定长度
salary DOUBLE(10,2),
hire_date DATE
);
SELECT * FROM aaa.myemp;
#增
#方式一,一条一条添加数据
#默认情况下,需要按照表中的列的顺序依次赋值
INSERT INTO myemp
VALUES(1,'tom1',3400,NOW());
#默认循序按列的排列顺序来的
INSERT INTO myemp
VALUES(1,'tom1',NOW(),3400);
#这样写测试通过,不过没意义
#开发中常见情况
#有时候,不太清楚先哪个列后哪个列
#就可以在表后指定顺序,这种方法在程序开发里用的比较多
INSERT INTO myemp(id,nam,hire_date,salary)
#显示的列出表中的列,一般都这样做
VALUES(1,'tom1',NOW(),3600);
#假如员工工资还没定下来,所以可以填null
INSERT INTO myemp(id,nam,hire_date,salary)
VALUES(1,'tom1',NOW(),NULL);
#表有四个列,参数表中只写了三个,
#则下边的具体参数也要写三个
#这种情况用的也比较多,剩余列自动填null
INSERT INTO myemp(id,nam,hire_date)
VALUES(1,'tom1',NOW());
#用户信息,填表可能不完整,在保存时没写的自动填NULL
#没有声明添加数据的列,数据默认为nulll,在开发中很常见
#有时会执行不成功,涉及到约束问题
#salary添加过非空约束的话,那么执行时就会报错
#有些非空的列,必须要赋值,
#以上是一条一条添加
#方式二,导入数据,基于现有的表
#导入时要注意列的类型和范围是否一样
DESC myemp;#导表示先看结构
DESC emp;
CREATE TABLE hehehe
AS
SELECT * FROM myemp;
INSERT INTO hehehe(id,nam,salary)
SELECT id,nam,salary
FROM myemp;
#where.....
#删除数据 : delete from
DELETE FROM myemp
WHERE salary IS NULL;#删除空行
#写的时候通常有过滤条件,否则全删除了
#delete from 是天然的批量操作
#删除,有时会删除失败(报错)
#表不存在
#约束,主要对列加约束
#外键约束
#A表有一个地区编号,B表也有一个地区编号
#AB表关联以后,如果再向A表的地区编号写一个
#另外的值,这个值在b表的地区编号中不存在
#那么会报错,违反外键约束
#外键约束的值不能删
#删父表的数据,先去子表查一下看有没有相关关联
#因为有外键约束,且在employees 找到了对应的90号部门相关的员工数据,所以删除失败
DELETE FROM departments
WHERE department_id=90;
#修改数据 update … set …where…
UPDATE myemp
SET salary=12000
WHERE id=1;
#此操作也是批量操作,如果不指定where条件,则全部更新
UPDATE myemp
SET salary=12000,id=222,hire_date='1999-09-09'
WHERE id=2;
#有外键约束的时候也要谨慎删除
#删除的特点
#级联删除,级联置空 (看课件)
#多表同步的意思
#在设置外键约束时,在后边加上一些条件。。。。
#数据库事务 一条或多条的DML的操作综合在一起
#叫数据库事务
#数据库事务:一条或多条DML操作组合在一起,构成数据库事务
#AA 转账 给BB
#转账的一个同步性,我转你收,你收不到,就回滚
#update emp set salary=salary-100 where name='AA'
#update emp set salary=salary+100 where name='BB'
#处理事务的原则:要么一个事务中的多个DML操作都执行成功,此时提交数据
#将修改了的数据保存下来
#要么都执行不成功,则已经执行了的操作也要回滚回去。
#CC向DD转账100
#又构成一个事务,整体出现,要么都出现,要么都不出现
#DML操作,支持数据的回滚操作。
#DDL操作,不支持数据的回滚,删除一个表,修改一个表,都不可以回滚
SET autocommit=FALSE;#设置为不自动提交操作
#开发中,先让autocommit变量为false
#try{
#update emp set salary=salary-100 where name='AA'
#update emp set salary=salary+100 where name='BB'
#commit;
#} catch(){
#rollback;
#}
#java 中类似这么表示
#commit;
commit;
SET autocommit=FALSE;
SELECT * FROM goods;
DELETE FROM goods;
ROLLBACK;
_____________________________________________________________________________________
#约束(constraint) 关键字
#为了保证数据一致性和完整性,SQL规范以约束的方式对表数据尽心额外的条件限制
#常见的约束:费控约束(not null) 唯一性约束(unique) 主键约束(primaary key) 外键约束(foreign key)
#检查性约束(check) 默认值约束(default)
#如何给表添加约束:1创建的同时添加约束,2通过修改表的方式,添加,删除约束,约束不能说是修改(先删 再加)
#在一开始考虑到,造表的时候考虑清楚,否则后期可能出现约束添加不上,删除不了的情况
#添加方式的体现:1 列级约束 2 表级约束(写在表的后边而已)
#约束实际上是对表的列的限制,对表中数据额外加的限制
#通俗来说就是对表中列在进行DML操作时的限制
#1.非空约束(not null)
#只能使用列级约束
USE aaa;
CREATE TABLE myem1(
id INT NOT NULL ,
NAME VARCHAR(15) NOT NULL,
salary DOUBLE (10,2)
);
DESC myem1;
INSERT INTO myem1(id,NAME,salary)
VALUES(1,'tom',200);
#报错 Field ‘id’ doesn’t have a default value
#添加失败
INSERT INTO myem1(NAME,salary)
VALUES('t1',200);
INSERT INTO myem1(NAME,salary)
VALUES(200);
#最后一个字段可以为空,因为没有非空限制
INSERT INTO myem1(id,NAME,salary)
VALUES(1,'tom',NULL);
#删除非空约束
ALTER TABLE myem1
MODIFY NAME VARCHAR(15) NULL;
DESC myem1;
#添加非空约束
#有可能执行不成功,(原因:如果现有的salary中已有null值,则添加约束失败)
ALTER TABLE myem1
MODIFY salary DOUBLE(10,2) NOT NULL;
#2.唯一性约束 (unique)
#列值是唯一的
USE aaa;
CREATE TABLE myem2(
id INT UNIQUE, #列级约束,这默认起约束名
NAME VARCHAR(15),
email VARCHAR(20),
hire_date DATE,
#表级约束 约束名
CONSTRAINT emp2_id_uk UNIQUE(email),
CONSTRAINT emp2_hire_date_uk UNIQUE(hire_date)
);
#NULL可以出现多次,不认为是一样的数据
#可以向声明为unique的列上多次添加null
INSERT INTO myem2(id,NAME,hire_date)
VALUES(3,'tom','2019-09-10');
#重复添加会添加失败
INSERT INTO myem2(id,NAME,hire_date,email)
VALUES(31,'t11om','2019-1-10','178@qq,com');
#删除唯一性约束
#系统会自动向声明为唯一性约束的列上添加索引
ALTER TABLE myem2
DROP INDEX emp2_hire_date_uk;
#删掉索引,对应的唯一性约束也就删掉了。
#添加唯一性约束
#…
#3.主键约束(primary key)
#主键的约束作用的列要求:非空且唯一
#一个表中,只能声明一个主键约束
#使用作用有主键约束的列作为查询条件,可以定位表中的唯一的一条记录
#唯一约束有null值的情况
CREATE TABLE my3(
id INT PRIMARY KEY,
NAME VARCHAR(15)
CONSTRAINT my3_id_pk PRIMARY KEY(id)
);
CREATE TABLE my3(
id INT AUTO_INCREMENT,#通常使用自增长,自动维护
NAME VARCHAR(15),
CONSTRAINT my3_id_pk PRIMARY KEY(id)
);
INSERT INTO my3(NAME)#因为设置了主键自增长,所以这里可以只写一个name
VALUES('张三');
INSERT INTO my3(NAME)#因为设置了主键自增长,所以这里可以只写一个name
VALUES('李四');
SELECT * FROM my3;
#4.外键约束:同样作用在列上
CREATE TABLE m1(
dept_id INT,
dept_name VARCHAR(10)
);
INSERT INTO m1(dept_id,dept_name)
VALUES(10,'it');
INSERT INTO m1(dept_id,dept_name)
VALUES(20,'Account');
#需要先为mi添加主键或唯一约束
ALTER TABLE m1
ADD CONSTRAINT dept_id_pk PRIMARY KEY(dept_id);
DELETE FROM m2;
ROLLBACK;
CREATE TABLE m2(
id INT,
NAME VARCHAR(15),
dept_id INT,
#外键约束(关联到的mydept的dept_id需要有唯一性的约束或主键约束)
CONSTRAINT m2_dept_id_fk FOREIGN KEY(dept_id)
REFERENCES m1(dept_id)#在这个地方添加级联删除,级联置空的约束
#意思。。
);
#要求向m2 表中dept_id添加值时,要求值必须是m1表中dept_id出现过的值
#正确的
INSERT INTO m2(id,NAME,dept_id)
VALUES(2,'TOM',10);
#错误的
INSERT INTO m2(id,NAME,dept_id)
VALUES(1,'TOM',40);
#5.检查约束 check 对oracle有效,对mysql失效了
#sql语言里有这个规范,mysql里写和没写一样
CREATE TABLE m3(
id INT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(10),
salary DOUBLE(10,2) CHECK(salary>3000)
);
#mysql执行仍然成功,oracle报错
INSERT INTO m3(NAME,salary)
VALUES('tom',100);#加入check无意义,照样执行
#6.默认值约束(default)
CREATE TABLE m4(
id INT,
NAME VARCHAR(15),
salary DOUBLE(10,2) DEFAULT 3000
);
INSERT INTO m4(id,NAME)
VALUE(1,'tom');
SELECT * FROM m4;
#分页
#要查的数据比较多
SELECT *
FROM goods
LIMIT 0,10;#查询前十条数据
#查询goods_number 前十的信息
SELECT *
FROM goods
ORDER BY goods_number DESC
#LIMIT 0,10;#查询前十条数据
#第一个参数表示从多少条开始,第二个参数表示显示多少条
#在查询中limit写在order by的后边
LIMIT 20,3; #查询20-23的数据
#写成公式,显示第pagenumber页的pagesize条数据
#limit (pagenumber-1)*pagesize,pagesize
#约束比较多 主要掌握,主键约束,造表是主键都会加上
(本笔记整理自网络资源,侵删)