DDL
DDL(数据库定义语言),用于数据库、表、列、索引等数据库对象的定义(创建)
和结构的修改
。
数据库
- 创建:
create
database 数据库名 - 删除:
drop
database 数据库名 - 改变使用的数据库:
use
数据库名
表
- 创建:
create
table 表名(
〈列名〉〈数据类型〉〈列级完整性约束条件〉……
CONTRAINT〈约束名〉〈表级完整性约束条件〉……)- 列级约束条件
- NOT NULL 或 NULL
NOT NULL约束不允许字段值为空,而NULL约束允许字段值为空。 - UNIQUE
惟一性约束,即不允许列中出现重复的属性值。 - PRIMARAY KEY [CLUSTERED|NON CLUSTERED]
定义该字段为主码并建立聚集(非)索引。
1、多个属性构成的主码只能通过表级约束条件定义:PRIMARY KEY (Sno,Cno)
2、单个属性构成的主码可通过列级或表级约束条件定义:Sno CHAR(9) PRIMARY KEY 或 PRIMARY KEY (Sno) - DEFAULT
默认值约束。 DEFAULT 默认值
DEFAULT〈约束名〉〈默认值〉FOR〈列名〉 - CHECK
检查约束。CONSTRAINT〈约束名〉CHECK (〈约束条件表达式〉)
1、单一属性设限
CONSTRAINT C2 CHECK(性别 IN (‘男’,‘女’))
CONSTRAINT C3 CHECK(成绩 BETWEEN 0 AND 100)
2、多属性之间设限
CHECK (Ssex=‘女’ OR Sname NOT LIKE ‘Ms.%’) - identity(初值,步长)
定义字段为数值型数据,并指出它的初始值和逐步增加的步长值 - reference 参照表(对应字段)
定义该字段为外码,并指出被参照表及对应字段 - AUTO_INCREMENT
设置该字段为自增字段
- 表级约束条件
- UNIQUE(列1, 列2, …)
- PRIMARY KEY[CLUSTERED|NON CLUSTERED](列1, 列2, …)
- check(条件表达式)
- FOREIGN KEY
CONTRAINT〈约束名〉FOREIGN KEY(〈外码〉) REFERENCES〈被参照表名〉(〈与外码 对应的主码名〉)
- NOT NULL 或 NULL
- 删除表:
drop
table 表名 - 修改表的约束or属性:
alter
table 表名
[rename
新表名] 更改表名
[add
column 列名 类型 约束 or CONSTRAINT 约束名 约束定义] 增加字段或者字段和表的约束
[drop
column 列名 or CONSTRAINT 约束名] 删除字段或约束
[alter
] 增加字段宽度或约束,一般不允许修改和减少,也不能改动字段标识
[modify
] 修改字段类型和约束,不能改动字段标识
[change
] 修改字段类型和约束,允许修改字段标识。后面要写两次列名,比较麻烦。
{check
|nocheck
}constraint{all|约束名组}使约束有效或无效(check使之有效,nocheck使之无效,all指全部约束)
first
after
:配合add、alter、modify、change使用,用于改变列的位置
- 列级约束条件
索引
-
创建:
create
[UNIQUE] [CLUSTERED|NONCLUSTERED]
index〈索引名〉 ON〈表名〉(〈列名〉[〈次序〉][,〈列名〉[〈次序〉]]…);UNIQUE
建立唯一索引,不允许有两行具有相同索引值
CLUSTERED|NONCLUSTERED
建立聚集或者非聚集索引,每张表只能有一个聚集索引,默认值为非聚集索引- alter table 表名
add
[UNIQUE|FULLTEXT] index 索引名 [using [BTREE|HASH]] (列名); - create table 表名{
学号 char(6),
课程号 char(3),
成绩 tinyint(1),
学分 tinyint(1),
primary key(学号,课程号);
index cj(成绩)//index 索引名 [索引类型] (索引列名)
}
-
删除:
drop
index 索引名 -
查看:
show
index in 表名
DML
DML(数据库操纵语言),用于实现对数据库表的内容
(而非结构)的增删改查
功能。
-
增加行
INSERT INTO
〈表名〉[(〈属性列1〉[,〈属性列2〉…)](不指定属性列时,需要把所有列都一一对应地写上)
VALUES
(〈常量1〉[,〈常量2〉]…),
(〈常量1〉[,〈常量2〉]…)……
或
INSERT INTO
〈表名〉[(〈属性列1〉[,〈属性列2〉]…)]
〈子查询〉- 如果想实现表中有重复的记录,则忽略本次插入的功能,可以通过
INSERT IGNORE
来实现这个功能:
INSERT IGNORE INTO 〈表名〉 - 如果想实现表中有重复的记录,则更新成本次插入的功能,可以通过
INSERT ... ON DUPLICATE KEY UPDATE
来实现这个功能:
INSERT INTO first_table (first_column, second_column) VALUES(1, ‘哇哈哈’) ON DUPLICATE KEY UPDATE second_column = ‘雪碧’;
这个语句的意思就是,对于要插入的数据(1, ‘哇哈哈’)来说,如果first_table表中有某些重复的记录,那就把记录的second_column列更新为’雪碧’
INSERT INTO first_table (first_column, second_column) VALUES(1, ‘哇哈哈’) ON DUPLICATE KEY UPDATE second_column = VALUES(second_column);
遇到重复记录时把该重复记录的second_column列更新成准备插入的记录中的值
- 如果想实现表中有重复的记录,则忽略本次插入的功能,可以通过
-
删除行
DELETE FROM
〈表名〉[WHERE〈条件〉]; -
修改某几行的属性值
UPDATE
〈表名〉
SET
〈列名〉=〈表达式〉[,〈列名〉=〈表达式〉][,…n]
[where] -
查找行
查询-注意事项
SELECT
〈属性1,属性2,……〉(可以使用distinct、top等关键字)
from 表1,表2,……(可以有多个表,结果是笛卡尔乘积;可以是左右连接)
where 元组需要满足的条件(可以用in)- 可以对同一个列重复查询显示
select num,num from strudentInfo;
- select后面的列是什么,临时表的列名就是什么
select 列1,列2的表达式,…… 查询结果中,列名就是: 列1,列2的表达式,……
查询-执行顺序
SQL语言不同于其他编程语言的最明显特征是处理
代码的顺序(书写
查询语句也需要符合顺序)。在大多数据库语言中,代码按编码顺序被处理。但在SQL语句中,第一个被处理的子句式FROM,而不是第一出现的SELECT。SQL查询处理的步骤序号:
(7)SELECT 投影,不删除结果中相同元组(注意,和关系运算中的投影π不同,π会删除结果中相同元素,相当于select distinct) (9) DISTINCT|TOP (11) <TOP_specification> <select_list>
(12) INTO tablename 将结果保存到新表中
(1) FROM <left_table> 笛卡尔乘积
(3) <join_type> JOIN <right_table> 隐含的筛选条件
(2) ON <join_condition> 筛选条件
(4) WHERE <where_condition> 筛选条件
(5) GROUP BY <group_by_list> 分组
(6) WITH {CUBE | ROLLUP}
(8) HAVING <having_condition> 筛选条件
(10) ORDER BY <order_by_list> ASC|DESC 排序条件
查询-分类
- 简单查询
查询过程中只涉及到一个表的查询 - 连接查寻
where子句
中,使用=
的连接查询- 自身连接:MySQL服务器会把名称一样的表当作是一个表处理,名称不同的当做不同的表处理。
下面的语句中,t1和t2会都被当做不同的表(相当于赋值了一个和test一样的表,和test进行连接查询),查询结果是两个test笛卡尔乘积后,留下满足条件的结果。 select * from test as t1, test as t2 where t1.num=t2.num; 下面的语句中,是一个表,查询结果为test原表 select * from test as t1, test as t2 where t1.num=t2.num;
- 复合连接:多个表的=连接
- 自身连接:MySQL服务器会把名称一样的表当作是一个表处理,名称不同的当做不同的表处理。
from子句中
,使用join
的连接查询- 内连接:使用innner join 或 cross join 或 join,等效于 from t1,t2。
后可跟连接条件:where 连接条件, on 连接条件, using 相同列名 - 外连接:使用了full join、left join、right join的全、左、右外连接查询
后只能跟连接条件: on 连接条件(on后面可再加where,但是不能直接用where) - 交叉连接:使用了cross join的交叉连接查询。返回被连接的两个表的
笛卡尔积
,返回结果的行数等于两个表行数的乘积。
- 内连接:使用innner join 或 cross join 或 join,等效于 from t1,t2。
- 嵌套查询
引出了子查询
概念。一个select from where成为一个查询块。- 按照
使用的运算符
分类:- 使用比较运算符(如> < =)连接子查询select
- 使用范围运算符(如in,any,all,exists)连接子查询select
- 按照
子查询和父查询的依赖关系
分类:- 相关子查询:子查询的查询条件依赖于父查询。
依次取父查询中每一个元组,处理内查询
,为真则保留结果。执行过程:
(1)从外层查询中取出一个元组
,将元组相关列的值传给内层查询。
(2)执行内层查询,得到子查询操作的值。
(3)外查询根据子查询返回的结果或结果集得到满足条件的行。
(4)然后外层查询取出下一个元组重复做步骤1-3,直到外层的元组全部处理完毕。 - 非相关子查询:子查询条件不依赖与父查询。即子查询
可以
完全脱离父查询单独执行
。
- 相关子查询:子查询的查询条件依赖于父查询。
- 按照
- 集合查询
使用了union(并)、intersect(交)、minus(差)关键字的查询。
注意:- 查询的结果集中显示的列名将
以第一个查询中的列名为准
。 - 被合并的各个查询的查询对象
个数必须相同
,类型不必完全相同
。 - 单独使用,系统会
自动去掉重复的
元组。union all则会保留重复的元素。 - 有的数据库没有intersect和minus,需要通过
exists
实现差和交操作。
- 查询的结果集中显示的列名将
- 分组查询
使用了group by的查询
SELECT TOP 子句
SELECT TOP 子句用于规定要返回的记录的数目。并非所有的数据库系统都支持 SELECT TOP 语句。
数据库 | 选取前几列的实现方式 |
---|---|
SQL Server / MS Access | SELECT TOP 语句 |
MySQL | LIMIT 开始行(从0开始),限制条数 |
Oracle | ROWNUM 语句 |
例子:从"Customers"表中选择前三个记录:
# SQL Server / MS Access
SELECT TOP 3 * FROM Customers;
# MySQL
SELECT * FROM Customers
LIMIT 3;
# Oracle
SELECT * FROM Customers
WHERE ROWNUM <= 3;
例子:从"Customers"表中选择记录的前50%:
SELECT TOP 50 PERCENT * FROM Customers;
查询-运算符
假设变量 a 的值为 10, 变量 b 的值为 20
- 算数运算符
操作符 | 描述 | 示例 |
---|---|---|
+ | 相加:将符号两边的数值加起来。 | a + b 得 30 |
- | 相减:从最边的操作数中减去右边的操作数。 | a - b 得 -10 |
* | 相乘:将两边的操作数相乘。 | a * b 得 200 |
/ | 相除:用右边的操作数除以左边的操作数。 | b / a 得 2 |
DIV | 相除:取商的整数部分。 | b / a 得 2 |
% | 取余:用右边的操作数除以左边的操作数,并返回余数。 | b % a 得 0 |
- 比较运算符
操作符 | 描述 | 示例 |
---|---|---|
= | 检查两个操作数的值是否相等,是的话返回 true。 | (a = b) 不为 true。 |
!= | 检查两个操作数的值是否相等,如果不等则返回 true。 | (a != b) 为 true。 |
<> | 检查两个操作数的值是否相等,如果不等则返回 true。 | (a<>b) 为真。 |
> | 检查左边的操作数是否大于右边的操作数,是的话返回真。 | (a > b) 不为 true。 |
< | 检查左边的操作数是否小于右边的操作数,是的话返回真。 | (a < b) 为 true. |
>= | 检查左边的操作数是否大于或等于右边的操作数,是的话返回真。 | (a >= b) 不为 true。 |
<= | 检查左边的操作数是否小于或等于右边的操作数,是的话返回真。 | (a <= b) 为 true. |
!< | 检查左边的操作数是否不小于右边的操作数,是的话返回真。 | (a !< b) 为 false. |
!> | 检查左边的操作数是否不大于右边的操作数,是的话返回真。 | (a !> b) 为 true。 |
- 逻辑运算符
操作符 | 描述 |
---|---|
AND | AND运算允许多个条件在SQL语句中,存在WHERE子句 |
OR | OR运算符是用来多个条件WHERE子句结合起来的SQL语句 |
NOT | NOT是一个否定运算符。例如:NOT EXISTS,NOT BETWEEN,NOT IN,NOT LIKE等 |
- 范围运算符
操作符 | 描述 |
---|---|
BETWEEN | BETWEEN运算符用于搜索是在一组值的那个值,给定的最小值和最大值 |
EXISTS | 代表存在,exists操作符后子查询结果集如果不为空 (即只要存在一条满足),则返回true,否则返回false |
IN | IN运算符用于一个值进行比较,以已被指定的文字值的列表 |
ALL | ALL运算符是用来在另一个值设定比较值的所有值,可以和比较运算符一起使用 |
ANY | ANY运算符用于根据条件在列表中的值进行比较的任何应用值,可以和比较运算符一起使用 |
SOME | 一些,可以和比较运算符一起使用 |
- 字符串运算符
操作符 | 描述 |
---|---|
+ | 连接 |
LIKE | LIKE运算符用来比较使用通配符运算符相似的值 |
- 其他运算符
操作符 | 描述 |
---|---|
IS NULL | NULL运算符用来比较一个NULL值 |
UNIQUE | UNIQUE操作搜索指定表的每一行的唯一性(不重复) |
查询-通配符
如果需要匹配 % 和 _ ,则需要使用 \ 进行转义。
通配符 | 描述 |
---|---|
% | 替代 0 个或多个字符 |
_ | 替代一个字符 |
[charlist] | 字符列中的任何单一字符 |
[^charlist] 或 [!charlist] | 不在字符列中的任何单一字符 |
查询-聚集函数
函数 | 描述 |
---|---|
SUM(column) | 返回某列的总和 |
AVG(column) | 返回某列的平均值 |
FIRST(column) | 返回在指定的域中第一个记录的值 |
LAST(column) | 返回在指定的域中最后一个记录的值 |
MAX(column) | 返回某列的最高值 |
MIN(column) | 返回某列的最低值 |
COUNT(*) | 返回被选行数 |
COUNT(column) | 返回某列的行数(不包括 NULL 值) |
COUNT(DISTINCT column) | 返回相异结果的数目 |
查询-表达式
表达式主要有以下两种使用:
- 作为查询对象
select num+50 from t1; --列名就是 num+50 ,列值是t1的 num+50
- 作为查询条件
select num from t1 where num>50;
group by的注意事项
- 在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚集函数(可以不是group by子句中指定列的聚集函数),原因在于
最终的结果集中只为每个组包含一行
。并且此时,检索列表中的表达式和GROUP BY子句中的表达式必须完全一样,而且不能使用别名
。 - 由于最终的结果集中只为每个组包含一行,对于不包含聚集函数的group by语句,筛选结果只保留第一个结果值,相当于使用了distinct
--结果是显示每个部门的名称(无重复) select 部门 from table group by 部门
- 如果分组列中含有NULL值,那么NULL也会作为一个独立的分组存在。
- GROUP BY子句后也可以跟随表达式,但不能是聚集函数(很显然,根据聚集函数无法分组)
- group by和group by all的区别
- group by all 不管where的筛选条件,而对表中所有的行根据属性进行分组并显示在结果集中
- 如果select里面有聚集函数,则group by all 中不符合where筛选的结果显示为null
select 类别,AVG(定价) 平均价 from 图书馆 where 出版社='机械出版社' group by 类别
--会对出版社非机械出版社的书也根据类别进行分组,只不过对应的平均价为null select 类别,AVG(定价) 平均价 from 图书馆 where 出版社='机械出版社' group by all 类别
DISTINCT-去重
- 使用格式
SELECT DISTINCT 列名1, 列名2, ... 列名n FROM 表名;
- 注意事项
distinct会将结果中重复的行去除,即没有任何两行“列名1, 列名2, … 列名n”完全相同
null值检查
null代表没有值,判断某一属性是否为null时,不能用 =
,不能用通配符(任意字符不等于没有字符),必须用is (not)
DCL
DCL(数据库控制语言),用于控制访问权限和设定安全级别。
- grant
- 功能:授权
- 格式
grant 权限列表 on 库.表 to 用户名@'ip' identified by "密码" [WITH GRANT OPTION];
- 应用
- 普通数据用户,查询、插入、更新、删除 数据库中所有表数据的权利。
grant select on testdb.* to common_user@ '%' grant insert on testdb.* to common_user@ '%' grant update on testdb.* to common_user@ '%' grant delete on testdb.* to common_user@ '%' --上面四条可以合成下面1条 grant select, insert, update, delete on testdb.* to common_user@ '%' --all等同于all privileges,其中的privileges可以省略 grant all on *.* to wang@ '192.168.1.150' identified by "password"; --把查询权限授予所有用户 GRANT SELECT ON TABLE SC TO PUBLIC; --把INSERT权限授予用户U5,并允许将此权限再授予其他用户 GRANT INSERT ON TABLE SC TO U5 WITH GRANT OPTION; --192.168.1.%表示一个网段 grant all privileges on *.* to wang@'192.168.1.%' identified by "123456"; --grant 作用在表中的列上: grant select(id, se, rank) on testdb.apache_log to dba@localhost; --授权之后,不要忘记更新权限表 flush privileges
- 数据库开发人员,创建表、索引、视图、存储过程、函数等权限。
--grant 创建、修改、删除 MySQL 数据表结构权限。 grant create on testdb.* to developer@ '192.168.0.%'; grant alter on testdb.* to developer@ '192.168.0.%'; grant drop on testdb.* to developer@ '192.168.0.%'; --grant 操作 MySQL 外键权限: grant references on testdb.* to developer@ '192.168.0.%'; --grant 操作 MySQL 临时表权限: grant create temporary tables on testdb.* to developer@ '192.168.0.%'; --grant 操作 MySQL 索引权限: grant index on testdb.* to developer@ '192.168.0.%'; --grant 操作 MySQL 视图权限 grant create view on testdb.* to developer@ '192.168.0.%'; --grant 操作 MySQL 存储过程、函数权限: grant create routine on testdb.* to developer@ '192.168.0.%'; -- now, can show procedure status grant alter routine on testdb.* to developer@ '192.168.0.%'; -- now, you can drop a procedure grant execute on testdb.* to developer@ '192.168.0.%'; grant execute on procedure testdb.pr_add to 'dba'@ 'localhost'; grant execute on function testdb.fn_add to 'dba'@ 'localhost';
- 查看权限
--查看当前用户下所有的权限 show grants; --查看其他 MySQL 用户权限: show grants for dba@localhost;
- 普通数据用户,查询、插入、更新、删除 数据库中所有表数据的权利。
- revoke
- 功能: 收回权限
- 格式: revoke跟grant语法差不多,只需要把关键字 “to” 换成 “from” 即可,并且revoke语句中不需要跟密码设置。
revoke 权限列表 on 库.表 from 用户名@'ip';
- 应用
--撤销已经赋予给 MySQL 用户权限的权限。 revoke all on *.* from dba@localhost; revoke insert,select,update,delete,drop,create,alter on huanqiu.* from wang@'%'; flush privileges;
grant和revoke的注意事项
- grant, revoke用户权限后,该用户只有重新连接MySQL数据库,权限才能生效。
- 如果想让授权的用户,也可以将其拥有的权限grant给其他用户,那么授权时需添加选项 “grant option”!
- mysql
授权表
一共涉及到5个表,分别是user、db、host、tables_priv和columns_priv。
这5张表的内容和用途如下:1)user表
user表列出可以连接服务器的用户及其口令,并且它指定他们有哪种全局(超级用户)权限。在user表启用的任何权限均是全局权限,并适用于所有数据库。例如,如果你启用了DELETE权限,在这里列出的用户可以从任何表中删除记录,所以在你这样做之前要认真考虑。
2)db表
db表列出数据库,而用户有权限访问它们。在这里指定的权限适用于一个数据库中的所有表。
3)host表
host表与db表结合使用在一个较好层次上控制特定主机对数据库的访问权限,这可能比单独使用db好些。这个表不受GRANT和REVOKE语句的影响,所以,你可能发觉你根本不是用它。
4)tables_priv表
tables_priv表指定表级权限,在这里指定的一个权限适用于一个表的所有列。
5)columns_priv表
columns_priv表指定列级权限。这里指定的权限适用于一个表的特定列。 - 如果给一个用户设置的权限过大,除了上面使用
revoke
回收部分权限外,还可以使用grant
进行权限修改
。也就是说,grant不仅可以添加权限,也可以修改权限(实际上就是对同一’用户名’@'ip’设置权限,以覆盖之前的权限);grant修改后的权限将覆盖之前的权限!
别名
用别名(Alias)来对数据表或者列进行临时命名。重命名是临时的,数据库中表的实际名字并不会改变。
为表或者列设置别名的方法有两种:
- 表名or临时表or属性名 as 别名
- 表名or临时表or属性名+空格+别名
注意:
- 别名只会在本次查询结果中显示,而不会改变表中真实的列名;
mysql> SELECT number AS 学号 FROM student_info; +----------+ | 学号 | +----------+ | 20180104 | | 20180102 | | 20180101 | +----------+ 6 rows in set (0.00 sec)
- 在查询语句中,使用别名后,后面的查询就必须用别名,而不能用原来的名字了。
数据类型
类型转换
当某个值的类型与上下文要求的类型不符时,MySQL就会根据上下文环境中需要的类型自动
对该值进行类型转换。
- 类型转换的场景:
- 把操作数类型转换为
适合操作符
计算的相应类型1 + 2 → 3 '1' + 2 → 3 '1' + '2' → 3
- 将函数参数转换为
适合函数
的类型以拼接字符串的CONCAT函数举例: CONCAT('1', '2') → '12' CONCAT('1', 2) → '12' CONCAT(1, 2) → '12'
存储(insert)
数据时,把某个值转换为某个列需要的类型
我们为列i1和i2填入的值是一个字符串值:‘100’,列s填入的值是一个整数值:200,虽然说类型都不对,但是由于自动转型的存在,在插入数据的时候字符串’100’会被转型为整数100,整数200会被转型成字符串’200’,所以最后插入成功。CREATE TABLE t ( i1 TINYINT, i2 TINYINT, s VARCHAR(100) ); INSERT INTO t(i1, i2, s) VALUES('100', '100', 200);
- 类型转换的方式:MySQL会尽量把值转换需要的类型。
- 类型转换:字符和数字的转换,‘23’ → 23
- 类型提升:200存入TINYINT型中,TINYINT变为BIGINT型
- 截取部分:如在进行加法计算时,‘23sfd’ → 23
常见问题
select 1 和 select null
- select 1
select 1 from 中的1是一常量(可以为任意数值),查到的所有行的值都是它,一般是作条件查询用。
从效率上来说,1>xxx>*,因为不用查字典表。1、Select n(数字) from table 得出一个行数和table表行数一样的临时列,每行的列值是我写在select后的数(n); 2、Select count(n) from table 得出一个数,该数是table表的行数; 3、Select sum(n) from table 得出一个数,该数是table表的行数×写在select后的数(n) ;
- select null
与 select 1 相似。只不过返回的列值为 null,且不可以使用count 和 sum 函数
= 、in 、exists 的区别
- =
用于限定某一属性的唯一取值。= 右面的取值不能是一个范围。可以使用 = any 等实现范围限定。 - in
当右面接子查询的时候,先运行子查询,在运行上级查询。 - exists
当右面接子查询的时候,从上一级查询中依次取出每条元组,判断是否满足子查询。
代码示例:查询所有未修1号课程的学生姓名
1、错误示例:(错误原因:一个学生可能选多种课程)
SELECT Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND Cno <>'1'
2、正确写法:
a.用exists
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno = Student.Sno AND Cno=‘1’);
b.用in
SELECT Sname
FROM Student
WHERE sno NOT IN
(SELECT Sno
FROM SC
WHERE Cno==’1’)
where和having的区别
where | having |
---|---|
对from后表 中的所有字段进行筛选,而不能对group by分组后的数据筛选(也就是说只能对返回的查询结果集进行过滤操作 | 对select from 的结果或者group by分组后 的结果进行筛选 |
不能使用聚集函数 | 可以使用聚集函数 |
- where和having都可以使用的场景:
select goods_price,goods_name from sw_goods where goods_price > 100
解释:上面的having可以用的前提是我已经筛选出了goods_price字段,在这种情况下和where的效果是等效的,但是如果我没有select goods_price 就会报错!!因为having是从前筛选的字段再筛选,而where是从数据表中的字段直接进行的筛选的。select goods_price,goods_name from sw_goods having goods_price > 100
- 只可以用where,不可以用having的情况:
select goods_name,goods_number from sw_goods where goods_price > 100
-- 报错!!!因为前面并没有筛选出goods_price 字段 select goods_name,goods_number from sw_goods having goods_price > 100
- 只可以用having,不可以用where情况:
select goods_category_id , avg(goods_price) as ag from sw_goods group by goods_category having ag > 1000
注意: where 后面要跟的是数据表里的字段,如果我把ag换成avg(goods_price)也是错误的!因为表里没有该字段。而having只是根据前面查询出来的是什么就可以后面接什么。-- 报错!!因为from sw_goods 这张数据表里面没有ag这个字段 select goods_category_id , avg(goods_price) as ag from sw_goods where ag>1000 group by goods_category
Not null unique和primary key的区别
DBMS会给primary key建立索引
drop turncate delete的区别
- drop
将表占用的空间全部释放,包括数据和表的定义结构 - truncate
一次性
地从表中删除所有
数据,通过释放存储表数据所用的数据页来删除数据,并且只在事务日志
中记录页的释放
。TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。
最直观的是 truncate 之后自增字段是从头开始
计数,而delete仍保留着原来的最大数值。
TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE速度快
,且使用的系统和事务日志资源少
。 对于外键(foreignkey )约束引用
的表,不能使用 truncate table,而应使用不带 where 子句的 delete 语句
。 - delete
每次从表中删除一行,并且把同时把该行的删除操作作为事务记录在日志中保存,以便进行回滚
内连接 左连接 右连接 外连接
假设左表有M行,右表有N行,x=max(M,N),y=min(M.N)
- 内连接:笛卡尔乘积结果中,满足删选条件的部分,最少0行,最多M×N行(
全匹配,即笛卡尔乘积
) - 左连接:内连接(
匹配结果
)+左表中没有匹配的元组,最少M行,最多M×N行(全匹配) - 右连接:内连接(
匹配结果
)+右表中没有匹配的元组,最少N行,最多M×N行(全匹配) - 外连接:内连接(
匹配结果
)+两表中没有匹配的元组,最少x行,最多M×N行
MySQL中between and的取值范围
1、取 1<=x<=100的值,即包含两边的边界值
between 1 and 100
2、not between的范围是不包含边界值
3、当使用带有日期值的BETWEEN运算符时,为了获得最佳结果,应使用类型强制转换将列或表达式的类型显式转换为DATE类型。
例如,要获取所需日期为01/01/2003至01/31/2003的订单,请使用以下查询:
SELECT orderNumber,
requiredDate,
status
FROM orders
WHERE requireddate
BETWEEN CAST('2003-01-01' AS DATE)
AND CAST('2003-01-31' AS DATE);
如果是datetime类型,‘2003-01-31’ 会被转成’2003-01-31 00:00:00’类型,就查不出来2003-01-31的数据
char varchar nchar nvarchar
容量 | 长度 | 编码 | |
---|---|---|---|
char | 8000个英文,4000个汉字 | 定长 | 非Unicode |
varchar | 8000个英文,4000个汉字 | 变长 | 非Unicode |
nchar | 4000个字符,无论英文还是汉字 | 定长 | Unicode编码 |
nvarchar | 4000个字符,无论英文还是汉字 | 变长 | Unicode编码 |
- Unicode或非Unicode
- 占用字节不同
非Unicode:英文占用1个字节,汉子等需要占用两个字节
Unicode:所有的字符都用两个字节表示,即英文字符也是用两个字节表示。 - 适用场景不同
如果英文与汉字同时存在,占用空间数不同,容易造成混乱,导致读取出来的字符串是乱码
。
非Unicode:适合存储纯英文和数字,以节省空间
Unicode:适合含有中文字符的情况,以防止乱码
- 占用字节不同
- 定长和变长
- 占用长度不同:
定长中,char(10)表示字符长度为10,不满10个补充空格
变长中,vchar(10)表示最多存储10个字符,实际长度为存储的字符串长度+1(多出的字节用于保存实际使用了多大长度) - 存储效率不同:
定长数据存储效率更高
- 占用长度不同:
通配符和占位符的区别
- 通配符:在
字符串匹配
中替代一个或多个字符( 详情 ) - 占位符:在SQL语句中代替具体值,执行SQL语句时再
接收参数
参考文献
https://www.jianshu.com/p/bb19b6b0fdc3 sql语句执行顺序
http://keep.iteye.com/blog/240665 group by和having/where的区别
https://segmentfault.com/a/1190000008284099 having/where的区别
https://www.jb51.net/article/91915.htm grant revoke语句
https://www.cnblogs.com/kevingrace/p/5719536.html grant revoke语句
https://blog.csdn.net/liuwengai/article/details/51321198 grant revoke语句
https://troywu0.gitbooks.io/spark/content/shu_ju_ku_suo_yin.html 索引操作语句
https://www.yiibai.com/sql/sql-operators.html sql运算符
https://www.w3cschool.cn/sql/dlwiyfom.html SELECT TOP, LIMIT, ROWNUM
https://www.cnblogs.com/jiechn/p/3979261.html select 1
https://blog.csdn.net/lwl20140904/article/details/73882306 select null与select 1区别
https://blog.csdn.net/jueblog/article/details/9673505 in和exist的区别
https://blog.csdn.net/lick4050312/article/details/4476333 in和exist的区别
https://blog.csdn.net/jiuqiyuliang/article/details/10474221 交叉连接
https://github.com/whlmpower/JavaNote/blob/master/MySQL/SQL%E5%8F%82%E7%85%A7%E6%95%B0%E6%8D%AE%E8%AF%BE%E7%A8%8B%E8%AE%B2%E4%B9%89%E6%A2%B3%E7%90%86.md drop truncate delete 区别
http://www.manongjc.com/mysql_basic/mysql-between-and-basic.html between and 的边界问题
https://blog.csdn.net/qq_17011423/article/details/69220231 between and 时间边界问题
http://www.cnblogs.com/smjack/archive/2008/04/14/1152342.html char、varchar、nchar、nvarchar的区别
https://www.cnblogs.com/lichang1987/archive/2009/03/04/1403166.html char、varchar、nchar、nvarchar的区别
https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483845&idx=1&sn=e52cf475a4b0c24989fd0bce37af2efa&scene=19#wechat_redirect 类型转换