数据库:
查看当前数据库
show databases;
创建数据库
create database abc;
删除数据库
drop database abc;
进入某个数据库——要操作某个数据库内的东西,一定要先进入该数据库。
use 数据库名;
查看某个数据库内所有表
show tables;
数据表 - 是数据库内存放数据的基本单元。
就类似于现实中一个表格,
在这个表格中,每行代表一条记录。
每列代表一个Field。
查看某个表的结构:
—— 可以看到该表包含哪些数据列,每个数据列的数据类型。
desc 表名
查看某个表里数据:
select * from 表名;
现实生活中的表格、包括Excel表格,它们都是给人看的。
而数据库的表,通常都是通过程序来访问的。
但对于数据库的数据表,通常会通过程序来读写,因此呢,
使用SQL(Structured Query Language)结构化查询语言来操作数据库。
SQL分类:
DDL 数据定义语言,它主要负责增、删、改数据库对象。
它主要create、drop、alter关键字组成。
DCL 数据控制语言,GRANT 、INVOKE 收回权限。
查询语句 select
DML 数据操作语言,它主要由INSERT、update、DELETE关键字组成。
它主要负责增、删、改数据。
事务控制语句: commit、rollback savepoint组成。
====DDL====
create/drop/alter
主要用于对数据库对象进行增、删、修改操作。
——这三个关键字往往还要与其他关键字结合使用,用于操作指定类型的数据库对象。
对表的操作:
1. 建表
create table 表名
(
#多个列定义 , 多个列定义之间用逗号隔开
列名 类型 default 默认值。
) [W1]
2. 删除表
drop table 表名
3. 修改表
a。 增加列 alter table 表名
add 列定义
alter table news_inf
add post_time datetime;
-- 默认增加的列,用于在最后。
#将新增的列放在指定位置。
alter table news_inf
add post_ip varchar(255) after news_content;
#将新增的列放在最前面
alter table news_inf
add new_news_id varchar(255) first;
b。 删除列
alter table 表名
drop 列名
alter table news_inf
drop new_news_id;
c。修改列:
alter table 表名
modify 已有列名 新的列定义
alter table news_inf
modify post_time date default '2001-12-12';
如果要改列名,用change
alter table 表名
change 已有列名 新列名 新的列定义
alter table news_inf
change post_time post_date date default '2001-12-12';
对表的操作:
建表:create table 表名。创建了一个表结构,表里面依然没有数据。
删除表:drop table 表名。
修改表:alter table 表名 modify|change|add|drop
truncate 表名 [W2]
截断操作——对于大部分数据库来说,它是DDL。
因为MySQL早先它甚至只是toy数据库,所以MySQL对truncate实现并不好。
按标准,Truncate应该是一个DDL,它总是“截断”表中的全部数据,
因此它的速度比delete语句(删除数据)的速度要快得多。
---约束(constraint)---
它用于对数据库中数据的完整性进行约束:
约束分为5类:
-非空
-唯一
-主键
-外键
-check
===非空约束===
指定某个数据列不允许为null。
非空约束,总是列级约束,总是对单列起作用。
可以在建表时指定。也可以通过修改表来增加或删除。
非空约束:not null
create table category_inf
(
category_id int,
category_name varchar(255) not null,
category_desc varchar(255)
);
#修改表时增加非空约束
alter table news_inf
modify news_title varchar(255) not null;
#修改表时删除非空约束
alter table news_inf
modify news_title varchar(255) null;
当你向表中插入数据、或修改数据时,
如果你的数据与约束冲突,数据无法插入、数据也无法修改。
===唯一约束===
指定某个数据列或列组合的值不允许重复。
唯一约束既可用列级约束语法,也可用表级约束语法。
它既可对单列起作用,也可对多列组合起作用。
唯一约束:unique
create table item_inf
(
item_id int,
item_barcode varchar(255) unique,
item_name varchar(255),
item_price decimal
);
insert into item_inf
values(1 , '123a' , '键盘' , 12);
insert into item_inf
values(2 , '123a' , '鼠标' , 15);
列级约束:指的是建表时直接把约束紧跟在列定义之后。
表级约束:指的是建表时使用单独的约束定义来定义约束。
[constraint 约束名] 约束关键(列或列组合)
create table cat_inf
(
cat_id int,
cat_name varchar(255),
cat_age int, nique unique(cat_name)
);
# 列组合不能重复!
# 对于列组合不能重复的情况,只能用表级约束语法。
create table sys_users
(
user_id int,
user_name varchar(255),
user_pass varchar(255),
unique(user_name , user_pass)
);
1 a b
2 a c
3 d b
constraint cat_name_u
#两列都不能重复。
create table sys_users
(
user_id int,
user_name varchar(255) unique,
user_pass varchar(255) unique
);
1 a b
2 a c
3 d b
修改表时增加唯一约束:
alter table 表名
add 约束定义。
alter table user_inf
add constraint user_name_unique unique(user_name[X3] );
删除唯一约束
alter table 表名
drop index 约束名 [W4]
alter table user_inf
drop index user_name_unique;
insert into user_inf
values
(1, 'a' , 'b' , '123' , 'ss' , 'xx' , now() , 23);
insert into user_inf
values
(1, 'a' , 'c' , '123' , 'ss' , 'xx' , now() , 23);
!!!!!!!!!当你想对数据表进行修改时,而且表中已有数据情况下,对表的修改很容易失败!
如果你要做的修改与表中数据冲突,那么修改就会失败了!
----主键约束---- primary key
每条记录时,总会有一列或列组合,系统找到这列或这些列组合的值,
就可以根据该值来唯一地、确定一条记录。
主键默认的有唯一、非null。
在一个数据表中,只要确定了主键值,就可以唯一地找到对应的记录。
一个表中,最多只能有一个主键。但主键可由多个列的列组合来确定。
对于现代的数据库建模理论,通常建议:
不要采用具有实际物理意义的列作为主键,
应该额外地为数据表增加一列,这列没有实际意义,只是一个逻辑编号,
通常建议采用这列作为主键。
通常建议让系统为这列来分配值,而不是让程序员指定!
MySQL、SQL Server为这种逻辑主键列提供了identity支持。
auto_increment 有两个要求:
1. 这列必须是主键。
2. 这列的数据类型必须是整型。
create table item_inf
(
item_id int primary key auto_increment,
item_barcode varchar(255) unique,
item_name varchar(255),
item_price decimal
);
insert into item_inf
values(null , 'a1230' , '鼠标' , '12'),
(null , 'a2345' , '键盘' , '15');
主键也可以用表级约束语法来建,
尤其是当你要为多列的组合建约束时,更只能用表级约束语法。
create table sys_users
(
user_name varchar(255),
user_pass varchar(255),
constraint aa primary key(user_name , user_pass)
);
删除主键
alter table 表名
drop primary key;
alter table sys_users
drop primary key;
数据字典——看上去也像表,但通常是视图,数据字典通常只能查看。
数据字典里记录了数据库中所有的数据库对象的信息。
MySQL来说,使用information_schema保存数据字典信息。
SQL Server来说,使用master数据保存数据字典信息。
----外键---- foreign key
现实世界中,实体与实体之间存在如下关联关系:
1-1
1-N
N-N
一个人 -- 多匹马
典型的 1 - N关联关系。
create table wrangler_inf
(
wrangler_id int primary key auto_increment,
wrangler_name varchar(255)
);
create table horse_inf
(
horse_id int primary key auto_increment,
horse_name varchar(255),
horse_weight double
);
insert into wrangler_inf
values
(null , '张三'),
(null , '李四'),
(null , '王五');
insert into horse_inf
values
(null , '张新' , 200.0),
(null , '追风' , 210.0),
(null , '宝马' , 120),
(null , '骐骥' , 145);
外键列的值就是为了让系统知道,这条记录和哪条记录有关联关系。
1 - N
1是主,保存主记录的那个表称主表! 父表。
N是从,保存从记录的那个表称从表! 子表。
这就是典型的主从关系。
总是在从表上增加外键列。
drop table horse_inf;
create table horse_inf
(
horse_id int primary key auto_increment,
horse_name varchar(255),
horse_weight double,
wrangler_id int,
foreign key(wrangler_id) references wrangler_inf(wrangler_id)
);
insert into horse_inf
values
(null , '张新' , 200.0 , 1),
(null , '追风' , 210.0 , 1),
(null , '宝马' , 120 , 2),
(null , '骐骥' , 145 , 2);
外键列的值必须是主表里被参照列中已有的值。
insert into horse_inf
values
(null , '月牙' , 200.0 , 5);
删除外键约束:
alter table 表名
drop foreign key 外键约束名
自关联:参照自身主键,主表和从表是同一个。
create table emp_inf
(
emp_id int primary key auto_increment,
emp_name varchar(255),
emp_age int,
#记录自己的经理
manager_id int,
foreign key(manager_id) references emp_inf(emp_id)
);
insert into emp_inf
values
(null , '张三' , 25 , null),
(null , '李四' , 23 , 1),
(null , '王五' , 22 , 1);
多重关联:
商品表
用户表
商品可以属于某个人(卖家)
商品可以被谁购买(买家)
create table shop_users
(
user_id int auto_increment primary key,
user_name varchar(255)
);
create table goods_table
(
goods_id int auto_increment primary key,
goods_name varchar(255),
seller_id int,
buyer_id int,
# 记录卖家信息
foreign key(seller_id) references shop_users(user_id),
# 记录买家信息
foreign key(buyer_id) references shop_users(user_id)
);
insert into shop_users
values(null , 'aa'),
(null , 'bb'),
(null , 'cc');
insert into goods_table
values
(null , '键盘' , 2 , 1);
---约束--- 外键约束代码.txt
对数据增加一些限制条件,用于保证数据库里数据完整性。
5类约束:
not null 列级约束、只能对单列起作用。
unique 列级约束,也可以是表级约束。既可要求单列的值不允许重复,也可要求多列组合的值不允许重复。
primary key 每个数据表都应该有PK,而且我们建议没有物理的逻辑主键。
这个逻辑主键应该让系统自动编号,为主键列提供identity支持。auto_increment
foreign key 为了记录两个表里记录之间的关联关系。
1-N 主从表。
现实世界上,实体与实体之间存在
1-1 :两个表的关系是平等,因此可以在任何一方增加外键。
一旦增加外键,那么增加外键的一方就是从表。
boy和girl之间存在1-1的关联:
所以可以在任何一方增加外键,在那边增加外键,那么它就是从表
create table girl_inf
(
girl_id int primary key auto_increment,
girl_name varchar(255),
girl_weight double
);
create table boy_inf
(
boy_id int primary key auto_increment,
boy_name varchar(255),
girlfriend int unique,
foreign key(girlfriend) references girl_inf(girl_id)
);
■■■■可以在任意一方增加外键列,而且外键列上定义unique约束■■■■
insert into girl_inf
values
(null, '凤姐' , 60);
insert into boy_inf
values
(null , '张三' , 1),
(null , '李四' , 1);
1-N
N-N 两个表的关系也是平等。
N-N的关联关系要使用连接表来记录
两个表都是主表,连接表是从表。
customer和seller之间存在N-N的关联:
create table customer_inf
(
customer_id int primary key auto_increment,
customer_name varchar(255),
customer_address varchar(255)
);
create table seller_inf
(
seller_id int primary key auto_increment,
seller_name varchar(255),
seller_dept varchar(255)
);
#使用连接表来记录两个实体之间的关联关系
create table customer_seller
(
customer_id int,
seller_id int,
foreign key(customer_id) references customer_inf(customer_id),
foreign key(seller_id) references seller_inf(seller_id)
);
insert into customer_inf
values
(null , '孙泰声' , '小新塘'),
(null , '王五' , '石牌村');
insert into seller_inf
values
(null , '小赵' , '电器部'),
(null , '小王' , '蔬菜部');
insert into customer_seller
values
(1 , 1),
(1 , 2),
(2 , 1);
check约束:check约束就是一个boolean表达式。
只有当check约束的boolean表达式返回true时,这条记录才能被插入或者被修改。
create table aged_inf
(
aged_id int primary key auto_increment,
aged_name varchar(255),
aged_age int,
check(aged_age > 60 and aged_age < 110)
);
insert into aged_inf
values
(null , '张三' , 23);
----索引----
index 目录。
索引:记录一条记录的关键内容,以及它对应的位置。
位置分为2类:一种是逻辑位置:
还有一种是物理位置:这种索引在Oracle中叫聚簇索引。
索引的好处:加快查询。
坏处:增加数据存储空间。增加、修改、删除记录时,需要较大的开销来维护索引。
建立索引:
自动:建PK、FK、unique都会自动建索引。
手动:由程序员来建立索引。
create index 索引名
on 表名(列);
删除索引:
自动:删除表时,索引被删除。
手动:drop index 索引名 on 指定表。
create index name_index
on aged_inf(aged_name);
drop index name_index on aged_inf;
----------DML语句---------
DDL是对数据库中的对象(表、约束、视图、索引等)进行增、删、修改等操作。
DML对数据表中数据(数据行)进行增、删、修改等操作。
insert 插入
delete 删除
update 修改
■■■■
insert into 表名
values(一行记录);
一般来说,每条insert语句只能插入一条记录。
# 插入一条记录时,不想为每列都指定值。
insert into 表名(列1 , 列2 , 列3)
values (val1 , val2 , val3);
insert into aged_inf(aged_name)
values ('关羽');
可以将选择出来的记录插入进入
insert into 表名[(列1 , 列2 , 列3)]
select 子句
■■■■delete
delete from 表名
where logic_expression
----当logic_expression的值为true,对应的记录行被删除。
delete from aged_inf
where aged_id > 5;
如果没有where子句,相当于where子句总是返回true。
■■■■update
update 表名
set 列1=val1 , 列2=val2, 列3=val3 ...
where logic_expression
----当logic_expression的值为true,对应的记录行被修改
update aged_inf
set aged_name = '猪八戒'
where aged_id%2 = 0;
--------select语句--------
select 列名 | 表达式 | 变量 | 常量
from 表名 | 视图 | 子查询
where logic_expression
----当logic_expression的值为true,对应的记录行被选择出来。
where确定要选择哪些行。
select 确定选择哪些列。
select *
from 表
select aged_id , aged_name
from aged_inf
where aged_id > 3;
select 12
from aged_inf;
select语句的执行过程:
for(row : table)
{
if(where子句中logic_expression)
{
输出 select子句的列表
}
}
select 12 * aged_id test
from aged_inf;
select 12 * aged_id , test
from aged_inf;
select 12 * aged_id , 'test'
from aged_inf;
select 12 * aged_id 'test'
from aged_inf;
select 12 * aged_id , "test"
from aged_inf;
select 12 * aged_id , 234
from aged_inf;
select 12 * aged_id '234'
from aged_inf;
select aged_name , length(aged_name)
from aged_inf;
#mysql中直接计算某个表达式的值:
select 5;
select now();
SQL语句中函数:
不同的数据库,单行函数大同小异,虽然函数的名称可能各有差异,
但这些函数实现的功能最后是差不多的。
单行函数:
字符串函数 LENGTH
日期/时间函数 now、dayofmonth
数学函数 ceil、floor、ABS、round、rand
转换函数: 负责完成类型转换。
mysql> SELECT 1+'1';
-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'
mysql> SELECT 38.8, CAST(38.8 AS CHAR);
-> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
-> 38.8, '38.8'
SELECT PI()+0.000000000000000000;
SELECT ROUND(1.298, 1);
SELECT FLOOR(7 + (RAND() * 5));
SELECT TRUNCATE(1.223,1);
流程控制函数:
IF(logic_expresss, val1 , val2) 当logic_expr为true,返回val1 ,否则返回val2
CASE Case operator
IFNULL(val1 , val2) 如果val1为null,返回val2;否则返回val1。
NULLIF(val1 , val2) 如果val1 = val2 返回null ,否则返回val1。
对aged_name进行处理,当aged_name的长度小于4时,直接输出。
当aged_name的长达大于4时,只保留前2位,并添加...
select if(length(aged_name) <= 4 , aged_name , concat(substr(aged_name , 1 , 2) , '...')) '人名'
from aged_inf;
CASE value WHEN [compare_value1] THEN result1 [WHEN [compare_value2] THEN result2 ...] [ELSE resultN] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
select aged_age , case when aged_age<30 then '年轻人'
when aged_age>30 and aged_age<48 then '中年人'
when aged_age>48 then '老年人'
end '分类'
from aged_inf;
#update记录
update boy_inf
set boy_age=48
where boy_name='农夫山泉';
update boy_inf
set boy_age=18
where boy_name='下雨天';
update boy_inf
set boy_age=25
where boy_name='character';
update boy_inf
set boy_age=36
where boy_name='越野车一句句科技';
#select语句
#if判断语句
select if(LENGTH(boy_name)<5,boy_name,CONCAT(lEFT(boy_name,3),'...')) Name
,CHAR_LENGTH(boy_name) Length,
if(isnull(girlfriend),'还需寻觅','革命成功') 革命
from boy_inf;
select boy_name,if(isnull(girlfriend),'还需寻觅','革命成功')
from boy_inf;
#case判断语句
select
if(LENGTH(boy_name)<5,boy_name,CONCAT(lEFT(boy_name,3),'...')) Name,
CHAR_LENGTH(boy_name) Length,
if(isnull(girlfriend),'还需寻觅','革命成功') 革命,
case
when boy_age<20 then '未成年'
when boy_age>20 and boy_age<30 then '青年人'
when boy_age>30 then '已过期'
end '分类'
from boy_inf;
SQL语句
DML insert update delete
DDL create table/index/database
drop
alter
select语句
JDBC编程。
允许使用JAVA程序来操作数据库。
需要使用Java程序开发更友好的GUI界面,让用户来操作。
SQL语法:
DML
DDL
DCL
事务控制语句
select
select 列名|表达式|变量|常量
from 数据源(表|视图|子查询)
where logic_expre
for (row : 数据源)
{
if( logic_expre)
{
选出 select子句后的列表
}
}
多表连接查询:
在很多时候,我们要查询的数据并不是来自于一个表,
可能需要来自多个数据表。
这时候就需要进行多表查询!
多表查询的语法:
SQL92标准:就我个人认为SQL92语法简洁,但可读性略差。
SQL99标准:可读性更好。
SQL 92的多表查询语句:
select 列名|表达式|变量|常量
from 表1 , 表2 ...
where 连接条件
and 数据筛选条件
多表查询时,很容易出现一个问题:多个表之间存在同名的列。
为了区分数据列到底来自于哪个表,可以在列前增加表名、表别名作为前缀。
===等值连接===
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w
where h.wrangler_id = w.wrangler_id;
===不等值连接===
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w
where h.wrangler_id > w.wrangler_id;
查询的表有几个,这里的循环就嵌套几次。
for(row1 : table1)
{
for(row2 : table2)
{
...
//查询的表有几个,这里的循环就嵌套几次。
if( logic_expre)
{
选出 select子句后的列表
}
}
}
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w
where h.wrangler_id < w.wrangler_id;
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w
where h.wrangler_id <= w.wrangler_id;
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w
where h.wrangler_id != w.wrangler_id;
===外联接===
MySQL根本不支持SQL92的外联接
如果我们要求某个表中的记录,即使它没有配对的记录,
我们也想将其选出。
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w
where h.wrangler_id = w.wrangler_id(+);
——强制把horse_inf表中不匹配的记录选出。
SQL92的多表语法规则是:
那边增加外能行,对方表中的记录全部被选出!
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w
where h.wrangler_id(+) = w.wrangler_id;
——强制把wrangler_inf表中不匹配的记录选出。
select h.* , w.wrangler_name
from horse_inf h , wrangler_inf w;
SQL 99 的多表查询语句:
select 列名|表达式|变量|常量
from 表1
xxx join 表2
[on 指定连接条件]
xxx join 表3
[on 指定连接条件]
...
xxx join 表N
[on 指定连接条件]
where 数据筛选条件
与SQL92相比:
SQL99中的连接条件不再放到where子句中,而是用on子句来指定。
1. 自然连接
natural join
select h.* , w.wrangler_name
from horse_inf h
natural join wrangler_inf w;
natural join有一个隐含的连接条件:
它的连接条件是基于两个表中同名的列来进行连接。
2. 交叉连接
cross join
它其实和SQL92中不指定连接条件的效果一样。
select h.* , w.wrangler_name
from horse_inf h
cross join wrangler_inf w;
3. 普通内连接
[inner join] 用on来指定连接连接
select h.* , w.wrangler_name
from horse_inf h
inner join wrangler_inf w
on h.wrangler_id = w.wrangler_id;
select h.* , w.wrangler_name
from horse_inf h
inner join wrangler_inf w
on h.wrangler_id > w.wrangler_id;
select h.* , w.wrangler_name
from horse_inf h
inner join wrangler_inf w
on h.wrangler_id < w.wrangler_id;
4. 外联接
left|right|full [outer] join
left join 就是左边表的记录全部被选出。
right join 是右边表的记录全部被选出。
full join 两边的表的记录全部被选出。
select h.* , w.wrangler_name
from horse_inf h
left join wrangler_inf w
on h.wrangler_id = w.wrangler_id;
select h.* , w.wrangler_name
from horse_inf h
right join wrangler_inf w
on h.wrangler_id = w.wrangler_id;
====MySQL并不支持全外联接。====
select h.* , w.wrangler_name
from horse_inf h
full join wrangler_inf w
on h.wrangler_id = w.wrangler_id;
子查询
指在查询语句中嵌套另一个查询。
子查询可以出现在两个位置:
1. from之后 - 子查询本质上就是一个数据源。也叫所谓行内视图,相当于一个临时的视图
2. where子句中。
视图:视图本质上就是一个有名字的查询语句。
create view 视图名
as
select语句
==== 所谓视图,无非就是给select语句起个名字而已。
create view horse_view
as
select h.* , w.wrangler_name
from horse_inf h
left join wrangler_inf w
on h.wrangler_id = w.wrangler_id;
对视图进行查询时,与普通表没有区别。
但通常不要对视图执行DML操作!!!!——因为视图本身只是一个select语句,它自身并不存储数据。
视图的优势:
1. 通过把select语句定义成视图,可以简化查询。
2. 通过视图,可以为同一份数据提供多个逻辑视图,从而能更好地保护数据。
select * from horse_view where horse_id<2;
===子查询作为数据源===
select s.* from (select h.* , w.wrangler_name
from horse_inf h
left join wrangler_inf w
on h.wrangler_id = w.wrangler_id) s where horse_id<2;
===子查询作为筛选条件===
select * from horse_view
where horse_id > 2;
==单行、单列子查询,子查询的结果相当于一个标量值==
select * from horse_view
where horse_id > (select aged_id
from aged_inf
where aged_name = '猪八戒');
==多行、单列子查询==
此时子查询相当于返回一个List,因此需要使用多行运算符。
select * from horse_view
where horse_id in (select aged_id
from aged_inf);
select * from horse_view
where horse_id >any (select aged_id
from aged_inf);
select * from horse_view
where horse_id >all (select aged_id
from aged_inf);
select * from horse_view
where horse_id <all (select aged_id
from aged_inf);
select * from horse_view
where horse_id <any (select aged_id
from aged_inf);
==多行、多列子查询==
子查询相当于返回一个List,每个List元素相当于一个数组。
或者要求一个数组和另一个数组相当。
select * from horse_view
where (horse_id , horse_id) in (select horse_id , wrangler_id
from horse_inf);
====分组和组函数====
在SQL语句中可以使用函数:
单行函数:每行输入,将会产生一行输出。以数据库配套的文档为准,就像你们查API文档一样。
多行函数:聚集函数。多行输入,会产生一行的统计结果。
count 统计记录条数count(*) ,
select count(aged_name) from aged_inf;
去除重复记录,可以在select后紧跟distinct。
统计时去除重复: select count(distinct aged_name)from aged_inf;
sum
计算总和:select sum(aged_age) from aged_inf;
计算总和重复记录只统计一条:select sum(distinct aged_age) from aged_inf;
max
select max(aged_age) from aged_inf;
min
select min(aged_age) from aged_inf;
avg
计算平均值:select avg(aged_age) from aged_inf;
计算平均值重复记录只统计一条:select avg(distinct aged_age) from aged_inf;
默认情况下,分组函数将表中的所有记录当成一组,整个的最终只生成一条记录。
为了显式进行分组,可以考虑使用group by子句,
group by的作用是:将指定列,或指定列列表中值相同的记录当成一组进行计算。
select avg(emp_age) , emp_depart from emp_inf
group by emp_depart;
having对组进行过滤:
select avg(emp_age) , emp_depart from emp_inf
group by emp_depart
having avg(emp_age) > 30;
having子句和where子句有点像
select avg(emp_age) , emp_depart from emp_inf
group by emp_depart
having emp_depart like '研%';
select avg(emp_age) , emp_depart from emp_inf
where emp_depart like '研%'
group by emp_depart;
应该优先考虑使用where子句进行数据筛选!
SQL优化的规范:数据筛选尽早完成!
如果having子句中出现了组函数,那么where子句就无能为力了!
因为where子句中不能出现组函数!。
SQL里有2个通配符:
% 可以代表任意多个字符。
_ 可以代表一个任意的字符。