数据库基础语句

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〈被参照表名〉(〈与外码 对应的主码名〉)
    • 删除表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]

  • 查找行

查询-注意事项

  1. SELECT 〈属性1,属性2,……〉(可以使用distinct、top等关键字)
    from 表1,表2,……(可以有多个表,结果是笛卡尔乘积;可以是左右连接)
    where 元组需要满足的条件(可以用in)
  2. 可以对同一个列重复查询显示
    select num,num from strudentInfo;
    
  3. select后面的列是什么,临时表的列名就是什么
    select1,列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;
        
      • 复合连接:多个表的=连接
    • 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的交叉连接查询。返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积。
  • 嵌套查询
    引出了子查询概念。一个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 AccessSELECT TOP 语句
MySQLLIMIT 开始行(从0开始),限制条数
OracleROWNUM 语句

例子:从"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。
  • 逻辑运算符
操作符描述
ANDAND运算允许多个条件在SQL语句中,存在WHERE子句
OROR运算符是用来多个条件WHERE子句结合起来的SQL语句
NOTNOT是一个否定运算符。例如:NOT EXISTS,NOT BETWEEN,NOT IN,NOT LIKE等
  • 范围运算符
操作符描述
BETWEENBETWEEN运算符用于搜索是在一组值的那个值,给定的最小值和最大值
EXISTS代表存在,exists操作符后子查询结果集如果不为空(即只要存在一条满足),则返回true,否则返回false
ININ运算符用于一个值进行比较,以已被指定的文字值的列表
ALLALL运算符是用来在另一个值设定比较值的所有值,可以和比较运算符一起使用
ANYANY运算符用于根据条件在列表中的值进行比较的任何应用值,可以和比较运算符一起使用
SOME一些,可以和比较运算符一起使用
  • 字符串运算符
操作符描述
+连接
LIKELIKE运算符用来比较使用通配符运算符相似的值
  • 其他运算符
操作符描述
IS NULLNULL运算符用来比较一个NULL值
UNIQUEUNIQUE操作搜索指定表的每一行的唯一性(不重复)

查询-通配符

如果需要匹配 % 和 _ ,则需要使用 \ 进行转义。

通配符描述
%替代 0 个或多个字符
_替代一个字符
[charlist]字符列中的任何单一字符
[^charlist] 或 [!charlist]不在字符列中的任何单一字符

查询-聚集函数

SQL函数

函数描述
SUM(column)返回某列的总和
AVG(column)返回某列的平均值
FIRST(column)返回在指定的域中第一个记录的值
LAST(column)返回在指定的域中最后一个记录的值
MAX(column)返回某列的最高值
MIN(column)返回某列的最低值
COUNT(*)返回被选行数
COUNT(column)返回某列的行数(不包括 NULL 值)
COUNT(DISTINCT column)返回相异结果的数目

查询-表达式

表达式主要有以下两种使用:

  1. 作为查询对象
    select num+50 from t1; --列名就是 num+50 ,列值是t1的 num+50
    
  2. 作为查询条件
    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,dropcreatealter 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属性名+空格+别名

注意:

  1. 别名只会在本次查询结果中显示,而不会改变表中真实的列名;
    mysql> SELECT number AS 学号 FROM student_info;
    +----------+
    | 学号     |
    +----------+
    | 20180104 |
    | 20180102 |
    | 20180101 |
    +----------+
    6 rows in set (0.00 sec)
    
  2. 在查询语句中,使用别名后,后面的查询就必须用别名,而不能用原来的名字了。

数据类型

SQL数据类型

类型转换

当某个值的类型与上下文要求的类型不符时,MySQL就会根据上下文环境中需要的类型自动对该值进行类型转换。

  • 类型转换的场景:
  1. 把操作数类型转换为适合操作符计算的相应类型
    1 + 23
    '1' + 23
    '1' + '2'3
    
  2. 将函数参数转换为适合函数的类型
    以拼接字符串的CONCAT函数举例:
    CONCAT('1', '2')'12'
    CONCAT('1', 2)'12'
    CONCAT(1, 2)'12'
    
  3. 存储(insert)数据时,把某个值转换为某个列需要的类型
    CREATE TABLE t (
        i1 TINYINT,
        i2 TINYINT,
        s VARCHAR(100)
    );
    INSERT INTO t(i1, i2, s) VALUES('100', '100', 200);
    
    我们为列i1和i2填入的值是一个字符串值:‘100’,列s填入的值是一个整数值:200,虽然说类型都不对,但是由于自动转型的存在,在插入数据的时候字符串’100’会被转型为整数100,整数200会被转型成字符串’200’,所以最后插入成功。
  • 类型转换的方式:MySQL会尽量把值转换需要的类型。
  1. 类型转换:字符和数字的转换,‘23’ → 23
  2. 类型提升:200存入TINYINT型中,TINYINT变为BIGINT型
  3. 截取部分:如在进行加法计算时,‘23sfd’ → 23

常见问题

select 1 和 select null

  • select 1
    select 1 from 中的1是一常量(可以为任意数值),查到的所有行的值都是它,一般是作条件查询用。
    从效率上来说,1>xxx>*,因为不用查字典表。
    1Select n(数字) from table
    得出一个行数和table表行数一样的临时列,每行的列值是我写在select后的数(n)2Select count(n) from table
    得出一个数,该数是table表的行数;
    3Select 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的区别

wherehaving
from后表中的所有字段进行筛选,而不能对group by分组后的数据筛选(也就是说只能对返回的查询结果集进行过滤操作select from的结果或者group by分组后的结果进行筛选
不能使用聚集函数可以使用聚集函数
  • where和having都可以使用的场景:
    select goods_price,goods_name from sw_goods where goods_price > 100
    
    select goods_price,goods_name from sw_goods having goods_price > 100
    
    解释:上面的having可以用的前提是我已经筛选出了goods_price字段,在这种情况下和where的效果是等效的,但是如果我没有select goods_price 就会报错!!因为having是从前筛选的字段再筛选,而where是从数据表中的字段直接进行的筛选的。
  • 只可以用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
    
    -- 报错!!因为from sw_goods 这张数据表里面没有ag这个字段
    select goods_category_id , avg(goods_price) as ag from sw_goods where ag>1000 group by goods_category
    
    注意: where 后面要跟的是数据表里的字段,如果我把ag换成avg(goods_price)也是错误的!因为表里没有该字段。而having只是根据前面查询出来的是什么就可以后面接什么。

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 
2not  between的范围是不包含边界值
3、当使用带有日期值的BETWEEN运算符时,为了获得最佳结果,应使用类型强制转换将列或表达式的类型显式转换为DATE类型。
   例如,要获取所需日期为01/01/200301/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

容量长度编码
char8000个英文,4000个汉字定长非Unicode
varchar8000个英文,4000个汉字变长非Unicode
nchar4000个字符,无论英文还是汉字定长Unicode编码
nvarchar4000个字符,无论英文还是汉字变长Unicode编码
  • Unicode或非Unicode
    • 占用字节不同
      非Unicode:英文占用1个字节,汉子等需要占用两个字节
      Unicode:所有的字符都用两个字节表示,即英文字符也是用两个字节表示。
    • 适用场景不同
      如果英文与汉字同时存在,占用空间数不同,容易造成混乱,导致读取出来的字符串是乱码
      非Unicode:适合存储纯英文和数字,以节省空间
      Unicode:适合含有中文字符的情况,以防止乱码
  • 定长和变长
    • 占用长度不同:
      定长中,char(10)表示字符长度为10,不满10个补充空格
      变长中,vchar(10)表示最多存储10个字符,实际长度为存储的字符串长度+1(多出的字节用于保存实际使用了多大长度)
    • 存储效率不同:
      定长数据存储效率更高

通配符和占位符的区别

  • 通配符:在字符串匹配中替代一个或多个字符( 详情
  • 占位符:在SQL语句中代替具体值,执行SQL语句时再接收参数
    • ?:原生JDBC中就有,用来在PreparedStatement中代替传入参数的位置( 详情
    • #{}${}:MyBatis占位符 ( 详情

参考文献

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 类型转换

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值