SQL语法总结

总结内容


1. 基本概念


 ·  数据库的概念
1)结构化查询语言(Structured Query Language)简称SQL;
2)数据库管理系统(Database Management System)简称DBMS;
3)数据库管理员(Database Administration)简称DBA,功能是确保DBMS的正常高效运行;

 · SQL常用的3个部分
1)数据查询语言(DQL):其语句也称“数据库检索语句”,用以从表中获得数据,保留字SELECT经常使用,DQL也是所有SQL中用的最多的,其他保留字还有WHERE, ORDER BY, GROUP BY和HAVING这些保留字还与DML一起使用;
2)数据操作语言(DML):其余局包括动词INSERT,UPDATE和DELETE。他们分别用于添加,修改和删除表中的行。也称动作语言;
3)数据定义语言(DDL):DDL主要用于操作数据库。


2. SQL列的常用类型
 

MySQL:           |         Java:
INT              |         int
BIGINT           |         long
DECIMAL          |         BigDecimal
DATE/DATETIME    |         java.util.Date
VARCHAR          |         String

3. DDL语言(操作数据库)


3.1 数据库操作


· 连接数据库语句

mysql -u root -p admin;


· 查看数据库列表:

show databases


· 创建数据库

· create database 数据库名称;


· 删除数据库

drop database 数据库名称;;


· 修改数据库(alter databese)

# 修改数据库编码格式
alter database 数据库名称 charset=编码格式;


· 查看当前数据库下所有数据表
 

show tables;

3.2 表操作


· 表的约束
1)非空约束:NOT NULL,不允许某列的内容为空;
2)设置列的默认值:DEFAULT;
3)唯一约束:UNIQUE,该表中,该列的内容必须唯一;
4)主键约束:PRIMARY KEY,非空且唯一;
5)主键自增长:AUTO_INCREMENT,从1开始,步长为1;
6)外键约束:FOREIGN KEY,A表中的外键列。A表中的外键列的值必须参照于B表中的某一列(B表主键)。

· 建表
 1)建表语法:

CREATE TABLE 表名(
     字段1   字段1的类型   [约束], //注意这里有逗号
     字段2   字段2的类型   [约束],
     ....
     字段N   字段N的类型   [约束] 

     //字段最后设置外键,如果有多个外键,外键之间无逗号
     // 注意:最后一行没有逗号
)

(2)主键语法:

       ·单个字段做主键:可以直接在字段定义后写上主键约束:

	cno VARCHAR ( 10 ) PRIMARY KEY NOT NULL,--  课程编号

     ·多个字段组合作为主键,在字段定义结束后写主键约束:

	PRIMARY KEY ( sno, cno, year_semester ) 
      //以(sno, cno, year_semester)的组合作为主键

(3)外键语法:

CONSTRAINT 外键名
	FOREIGN key(当前表中的字段) REFERENCES 该外键做主键的表(该外键在做主键的表中的字段名)

举例:(在当前表中定义三个外键)

	CONSTRAINT for_spno1 FOREIGN KEY ( spno ) REFERENCES speciality19 ( spno ),
	CONSTRAINT for_ctno1 FOREIGN KEY ( ctno ) REFERENCES cousetype19 ( ctno ),
	CONSTRAINT for_dno1 FOREIGN KEY ( dno ) REFERENCES department119 ( dno ) 

(4)综上,建表示例:

DROP TABLE IF EXISTS 't_student';
// 如果表存在就先移除,因为不能存在两个一样名称的表
CREATE TABLE course19 (
	cno VARCHAR ( 10 ) PRIMARY KEY NOT NULL,--  课程编号
	cname VARCHAR ( 20 ) NOT NULL,--  课程名称
	spno CHAR ( 2 ),
	ctno CHAR ( 1 ),
	experiment SMALLINT,-- 实验时数
	hours SMALLINT,--  授课学时
	semester SMALLINT,--  开课学期
	credit SMALLINT,--  课程学分
	duty_tno CHAR ( 7 ),
	dno CHAR ( 2 ),--  课程归属院系代码(外键)
	CONSTRAINT for_spno1 FOREIGN KEY ( spno ) REFERENCES speciality19 ( spno ),
	CONSTRAINT for_ctno1 FOREIGN KEY ( ctno ) REFERENCES cousetype19 ( ctno ),
	CONSTRAINT for_dno1 FOREIGN KEY ( dno ) REFERENCES department119 ( dno ) 
);


注意:建表不要使用关键字

·删除表

(1)语法:

DROP TABLE 表名;

4. DML语言(数据操作)


4.1 修改操作(UPDATE SET)


· 语法

UPDATE 表名
SET 列1 = 值1, 列2 = 值2, ...
WHERE [条件]

· 举例:

UPDATE student119 set sname='龙傲天' WHERE sname='小龙';
//将小龙的姓名改为龙傲天

注意:不要省略where条件子句,省略的话,全表数据都会被修改。


4.2 插入操作(INSERT INTO VALUE)


· 语法

INSERT INTO 表名(字段1,字段2....)VALUES(值1,值2.....);

· 举例:

// 1、插入完整数据记录
INSERT INTO t_student (name, email, age) VALUE ("xiaoming", "[email protected]", 16);
// 2、插入部分数据记录
INSERT INTO t_student (name, age) VALUE ("xiaoming", 16);
// 3、插入查询结果
INSERT INTO t_student(name, email, age) SELECT name,email,age FROM t_student;

4.3 删除操作(DELETE)


· 语法

DELETE FROM 表名 条件

· 举例:

DELETE FROM student119 WHERE sid=202026010111;


注意:Where子句别省略,否则全表的数据都会被删除。


5. DQL语言(查询操作)


5.1 消除重复元素(DISTINCT)
· 语法:

SELECT DISTINCT 列名, ... FROM 表名;

注意:distinct 放在2个字段前,是2个字段组合后重复才去重,放在第一个后会报错

· 实战:

SELECT DISTINCT productName, brand FROM product;

5.2 算术运算符(+,-,*,/)


· 算术运算符的使用范围
  1)对 number 型数据可以使用算术运算符(+,-,*,/)对数据进行操作;对date型数据可以使用部分算术运算符(+,-)对数据进行操作。

· 算术运算符的优先级
  1)与数学中运算相同

·举例

// 查询所有货物的id,名称和批发价(折扣价=销售价*折扣)
SELECT id, productName, salePrice * disCount From product;

5.3 设置别名(AS)


· 作用
1)改变列的标题头;
2)作为计算结果的含义;
3)作为列的别名;
4)如果别名使用特殊字符(强烈不建议使用特殊字符),或是强制大小写或有空格时都需要加单引号。

· 语法

// 第一种
SELECT 列名 AS 别名 FROM 表名 [WHERE];
// 第二种
SELECT 列名 别名 FROM 表名 [WHERE];

· 举例
 

// 查询所有货物的id,名称和折扣价价(折扣价=销售价*折扣)(使用别名)
SELECT id, productName, salePrice * disCount AS price From product;

5.4 按格式输出(CONCAT)


1)为了方便用户浏览查询结果数据,有时需要设置查询结果的显示格式,可以使用CONCAT函数来连接字符串。

· 语法

CONCAT(字符串1, 字符串2, ...)

· 举例
 

// 查询商品的名字和零售价。格式:xxx商品的零售价为:ooo
SELECT CONCAT(productName, " 商品的零售价为:", salePrice) FROM product;

5.6 比较运算符(=, >, >=, <, <=, !=)


1)不等于:<> 等价 !=;

· 举例

// 查询商品名为 罗技G9X 的货品信息
SELECT * FROM product WHERE productName = "罗技G9X";
// 查询批发价大于350的货品信息(折扣价 = 销售价*折扣)
SELECT *, salePrice * discount FROM product WHERE salePrice * discount > 350;

5.7 逻辑运算符(AND、OR、NOT)


1)AND:如果组合的田间都是 true,返回true;
2)OR:如果组合的条件之一是true,返回true;
3)NOT:如果给出的条件是false,返回true;如果给出的条件是true,则返回false。

· 举例

// 查询售价在300-400(包括300和400)的货品信息
SELECT * FROM product WHERE salePrice >= 300 ADN salePrice <= 400;
// 查询分类编号为2, 4的所有货品信息
SELECT * FROM product WHERE dir_id = 2 OR dir_id = 4;
// 查询编号不为2的所有商品信息
SELECT * FROM product WHERE NOT dir_id = 2

5.8 范围和集合(BETWEEN AND)


1)范围匹配:BETWEEN AND 运算符,一般使用在数字类型的范围上。但对于字符数据和日期类型同样可用。
注意:BETWEE AND 使用的是闭区间

· 语法

// 使用的是闭区间,也就是包括minValue 和 maxValue
WHERE 列名 BETWEEN minValue AND maxValue;

· 举例

// 查询零售价不在 300 - 400 之间的货品信息
SELECT * FROM product WHERE NOT salePrice BETWEEN 300 AND 400;


2)集合查询:使用 IN 运算符,判断字段的值是否在指定的集合中

· 语法

WHERE 列名 IN (值1, 值2, ...);

· 举例

// 查询分类编号为 2,4 的所有货品的 id,货品名称
SELECT id, productName FROM product WHERE dir_id IN (2,4);
// 查询分类编号不为 2, 4 的所有货品的 id,货品名称
SELECT id, dir_id, productName FROM product WHERE NOT dir_id IN (2,4);

5.9 判空(IS NULL、IS NOT NULL)


1)IS NULL:判断列的值是否为空值,非空字符串,空字符串使用 == 判断;

· 语法

WHERE 字段N IS NULL;

· 实战

// 查询商品名为NULL的所有商品信息
SELECT * FROM product WHERE productName IS NULL;
SELECT * FROM product WHERE supplier = "";

结论:使用 = 来判断只能判断空字符串,不能判断 null;而使用 IS NULL 只能判断 null 值,不能判断空字符串。


5.10 模糊匹配查询(LIKE,%,_)


1)LIKE:模糊查询数据使用 LIKE 运算执行通配符;
2)通配符:% 表示可有零个或多个任意字符; _ 便是需要一个任意字符;

· 语法

WHERE 列名 LIKE "%M_";

· 举例

// 查询货品名称以 罗技M9* 结尾的所有货品信息,这里的 * 表示一个任意字符,它不具备任何意义,只是我出于题目需要才这样写,便于你理解而已
SELECT * FROM product WHERE productName LIKE "%罗技M9_";

5.11 结果排序(ORDER BY)


1)ORDER BY:使用 ORDER BY子句将查询结果进行排序,ORDER BY子句出现在 SELECT 语句的最后;
2)ASC:升序;DESC:降序

· 实战

// 查询 id,货品名称,分类编号,零售价 按分类编号降序排序,如果分类编号相同再按零售价升序排序
SELECT * FROM product ORDER BY dir_id DESC, salePrice ASC;

5.12 分组查询(GROUP BY)


1)Group By分组查询,一般与having一起用,查询的参数只能是统计函数和分组的条件参数,或者是聚合函数,having 后面的条件只能是分组查询的字段或者统计函数

· 实战
 

# 查询分组条件之外的值,拼接成字符串
select theme_id, group_concat(dest_id) dest_id, group_concat(dest_name) dest_name 
from strategy group by theme_id having theme_id = 1;

5.13 DQL字句的执行顺序


1)FROM字句:从哪张表中去查数据;
2)JOIN table:先确定表,在确定关联条件;
3)ON 条件:表绑定条件;
4)WHERE字句:筛选需要的行数据;
5)GROUP BY子句:分组操作;
6)HAVING:对分组后的记录进行聚合;
7)SELECT字句:筛选需要显示的列数据;(对字段 AS 起别名是在这时候,所以 WHERE 中不能用字段的别名,ORDER BY 中可以使用别名);
8)DISTINCT:去重;
9)ORDER BY子句:排序操作;
10)LIMIT子句:限制条件;


6. 统计函数


6.1 常用关键字(COUNT、SUM、MAX、MIN、AVG)


· 概念
1)COUNT(*):统计表中有多少条数据;
2)SUM(列):汇总列的总和;
3)MAX(列):获取某一列的最大值;
4)MIN(列):获取某一列的最小值;
5)AVG(列):获取某一列的平均值;

· 举例

// 查询货品表共有多少数据
SELECT COUNT(*) FROM product;
// 计算所有货品的销售价
SELECT SUM(costPrice) FROM product;

7  视图、存储过程、触发器:

  7.1 引入一个题目分析,一个工程公司的数据库有如下四张表:

1) 员工表Employee(emp_id,name,sex, birth_day,title,phone, salary,dept_id),其属性分别表示员工工号、姓名、性别,出生日期、岗位,联系电话,工资,所属部门的编号;

2)部门表Department(dept_id,name,phone,manager_id), 其属性分别表示部门编号、部门名称,部门电话,部门经理的员工工号;

3)工程项目表project(proj_id,name,location,budget, dept_id), 其属性分别表示项目编号、项目名称,项目地点,项目金额,项目承担部门的编号。假定一个项目只由一个部门承担。一个部门可承担多个项目;

4)职工参加工程项目年度情况表Work(emp_id, proj_id,year,start_date, end_date, duty,workdays), 其属性分别表示员工工号,项目编号,年度,开始日期,结束日期,员工在项目中的职责,员工实际参与项目的天数。

注意:Work表记录了每个员工的年度工作情况。一个项目可能要多年完成,因此一个员工可能在多年中都参加了同一个项目,此时,每年都会有一行记录。在一年中,一个员工也可参加多个项目。duty取值有PROJ_MANAGER,GROUP_LEADER, MEMBER三种。对于一个项目,除了其承担部门的员工可参加外,其它部门的员工也可能参加。


7.2 回答以下问题:

一、分别表示4个表的主键,如果有外键也请标识出来:

  注意点:指明外键时,要指明该外键引用了哪个表的主键!!!!

回答:

· Employee 主键为:emp_id

                    外键为:dept_id  引用了Department的主键。

·Department主键为:dept_id

                      外键为:manager_id 引用了Employee的主键。

· project主键为: proj_id

              外键为:dept_id  引用了Department的主键。

· Work主键为:(emp_id,proj_id,year)

           外键1:emp_id 引用了Employee的主键;

            外建2:proj_id 引用了project表的主键。

 二、用关系代数式表达:

(1)查找出(名称为‘工程1队’)的部门的女职工名单,输出姓名、出生日期、工资。

(2) 求出在2017年根本就没有参加任何项目的员工名单,输出所在部门名称、姓名、员工工号。

三、使用SQL的DDL写出Work表的定义,要定义主键、外键等数据库的完整性约束

 注意 1:创建表时,要根据题目中的要求,注意字段的域约束!!!!(包括非空、字段类型、字段范围)

 注意 2 :注意外键约束、主键、组合主键的正确写法!

CREATE TABLE Work(

    emp_id CHAR(5) NOT NULL,//非空记得设置

    proj_id CHAR(5) NOT NULL,

    year CHAR(4) NOT NULL,

    start_date DATE,

    end_date DATE,

    duty VARCHAR(20) (CHECK duty IN(‘PROJ_MANAGER’,‘GROUP_LEADER’,‘MEMBER’)),//注意这里!

    workdays INTEGER

    PRIMARY KEY(emp_id, proj_id, year)

    FOREIGN KEY(emp_id) REFERENCES employee(emp_id)

    Foreign KEY(proj_id) REFERENCES project(proj_id)
  //注意!如果有多个外键,外键定义之间没有逗号
);

四、使用SQL语句回答下列十四个问题:

(1)新进一个工程项目:名称:望城电力大楼, 地点:雷锋大道428号,项目金额850万元, 由工程5队(部门编号为‘07’)来负责承担,公司给该工程分配编号‘2018101’。试用SQL 语句将该工程项目信息加到数据库中;

INSERT INTO project (proj_id,name,location,budget,dept_id) VALUES('2018101','望城电力大楼','雷锋大道428号',850,'07');

(2)土建部的员工张开意(工号为‘2011045’)已经从公司调走,试用SQL 语句将该员工的信息从数据库中删除;

DELETE FROM employee WHERE emp_id ='2011045';

(3)员工李欣艺(工号:‘2008013’)从工程1队(部门编号‘03’)调任工程2队(部门编号‘04’)任部门经理,试用SQL 语句修改数据库,反映此调动和任命;

UPDATE employee SET dept_id='04' WHERE emp_id='200813';
//先修改个人信息
UPDATE department SET manager_id='200813' WHERE dept_id='04';
//再修改部门经理的信息

(4)求出2017年公司的劳动模范。其定义是:凡是全年参加项目的实际总计天数大于等于300天的员工就是劳动模范。要求输出姓名、工号、所属部门名称,工作天数,要求对输出结果按照工作量递减原则排序;

思路:首先在work表中挑选出满足劳动模范需求的员工,然后结合各表联系,输出对应的数据。

因此有两种解法:

· 创建临时表法:

SELECT emp_id, SUM(workdays) AS workdays INTO tb1 FROM work WHERE year ='2017' GROUP BY emp_id HAVING workdays >=300;

//这里注意因为一个员工可能会参加不同的项目,因此
//要根据emp_id进行分组累加工作天数

SELECT E.name,E.emp_id,D.name,t.workdays FROM tb1 AS t, employee AS e, 
department AS d WHERE e.emp_id =w. emp_id AND e. dept_id =d. dept_id 
ORDER BY workdays DESC;
//注意DESC是降序,ASC是升序

· 语句嵌套法:

SELECT E.name,E.emp_id,D.name,workdays FROM (SELECT emp_id, SUM(workdays) AS workdays 
FROM work WHERE year ='2017' GROUP BY emp_id HAVING workdays >=300) AS w, 
employee AS e, department AS d WHERE e. emp_id =w. emp_id AND e. dept_id =d. dept_id 
ORDER BY workdays DESC;

(5)求出在2017年全年根本就没有参加任何项目的员工名单,输出所在部门编号,姓名,员工工号和年龄;

注意:巧用NOT IN 、DISTINCT 关键字,并且了解年龄的计算方式。

select e.dept_id,e.name,e.emp_id,(YEAR(NOW())-YEAR(e.birthday)) AS age 
FROM employee AS e where e.emp_id 
NOT IN (Select DISTINCT emp_id From work AS w WHERE w.year='2017');

(6)求出工资低于职工所在部门平均工资的职工工号和姓名;

注意点:GROUP BY的字段,必须出现在查询的队列中!

· 临时表法:

Select AVG(salary) AS avg_salary,dept_id INTO tb1 FROM
employee AS e GROUP BY dept_id;
-- 注意这里按照dept_id分组的话,前边的SELECT中必须有这个字段
Select e.emp_id,e.name FROM tb1 AS t,employee AS e 
WHERE e.salary

· 语句嵌套法:

Select e.emp_id,e.name from 
(select Avg(salary) AS avg_salary,dept_id From employee AS e  GROUP BY dept_id ) 
AS s,employee AS e Where e.dept_id=s.dept_id AND e.salary < avg_salary;

(7)求出工资最高的员工的职工工号、姓名和工资;

SELECT emp_id,name,salary FROM employee WHERE salary=
(SELECT MAX(salary) FROM employee);-- 注意这里!!

注意:这里不能直接salary=MAX(salary)!!!

(8)求出参加了所有工程项目的职工工号和姓名;

思路:统计每个员工参加项目的数量,然后统计项目的总数,如果两个数量一致,就满足条件。

Select e.emp_id,e.name FROM employee AS e,(SELECT COUNT(w.proj_id) AS
w_num,w.emp_id FROM work AS w GROUP BY w.emp_id 
HAVING w_num=(SELECT COUNT(*) FROM project)) AS s 
WHERE s.emp_id=e.emp_id;

(9)创建一个视图dept_info(name, code, manager, clerk_num),其内容为部门概况:部门名称,部门编号,部门经理姓名,部门员工人数);

· 首先复习一下视图的创建语法

CREATE VIEW  视图名  (字段1、字段2、字段3.....字段n)   --视图中显示的字段
AS
  BEGIN
     
      ~ ~~ ~  -- (SQl语句,选择是由表中的哪些字段构成)

  END;

答:

CREATE VIEW dept_info(name, code, manager, clerk_num)
AS 
    BEGIN 
		  SELECT  d.name,dept_id,e.name,s.dept_num FROM 
	      (SELECT dept_id,COUNT(*) AS dept_num From employee GROUP BY
		  dept_id) AS s,department AS d,employee AS e 
          WHERE d.dept_id=s.dept_id AND manager_id=e.emp_id;
	END;

(10) 创建一个存储过程my_work,列出某个员工,在某年中参加项目的情况,输出包括起始日期,结束日期,项目名称proj_name,项目承担部门的名称dept_name,工作天数。要求按照起始日期升序排列;

首先复习一下存储过程的创建语法

CREATE PROCEDURE 存储过程名(参数1,参数2.....参数n)
AS 
   BEGIN

         ~~   //SQL语句
   END;

注意参数的书写格式:

IN +参数名+参数类型

解答:

CREATE PROCEDURE my_work(@ emp_id IN VARCHAR,@ year IN VARCHAR) 
AS -- 我在Navicat中写存储过程时不用这个
  BEGIN

SELECT start_date,end_date,p.name AS proj_name,d.name 
AS dept_name, workdays FROM work AS w, project AS p, department 
AS d WHERE w.proj_id=p.proj_id AND p.dept_id=d.dept_id 
AND w.emp_id=@emp_id AND w.year=@year ORDER BY start_date ASC;

  END;

注意:如果要使用参数的值,就要使用标识符@。

(11) 创建一个触发器add_work_rule,控制往Work表中添加记录时,表中不会出现一个员工在一年中参加多个项目时,其时间上有重叠现象。即在Work表中当出现两行记录的emp_id, year相同时,不允许其(start_date, end_date)时间段上有重叠;

· 首先复习一下触发器的创建语法

CREATE TRIGGER 触发器名
触发器类型  触发条件 ON 操作的表名
REFERENCING NEW ROW AS new
FOR EACH ROW
BEGIN

       ~~~  //SQL语句

END;

· 触发类型有:

BEFORE:先执行触发器中的操作,再执行输入的SQL语句
AFTER :先执行输入的SQl语句,再执行触发器中的操作。
INSTEAD OF:不执行输入的SQL语句,只执行触发器中的操作。

· 解答:

CREATE TRIGGER add_work_rule 
BEFORE INSERT ON work
REFERENCING NEW ROW AS new
FOR EACH ROW

BEGIN

WHEN(EXIST SELECT * FROM Work WHERE [email protected]_id 
AND [email protected]_id AND end_date >[email protected]_date 
AND start_date<[email protected]_date)

raise_application_error(20000,'这个记录与已有记录在时间上有重叠');

END;

(12) 创建一个角色group_leader和一个用户ZhangDF, 给group_leader赋予对work表中记录的end_date和workdays进行修改的权限。然后把角色group_leader指派给用户ZhangDF;

注意:

1. 创建角色时,要给角色赋初始密码,语法为:

CREATE USER 角色名 IDENTIFIED BY 密码;

2.赋予某角色(某用户)对于特定表的权限,语法为:

GRANT 权限(字段1,字段2) ON 表名 TO 角色名(用户名);

· 解答:

CREATE ROLE 'group_leader';

CREATE USER ZhangDF IDENTIFIED BY '123';//注意!别忘了给UER设置密码

GRANT UPDATE(end _date,workdays) ON work TO group_leader;

GRANT group_leader To ZhangDF;

(13) 就Work表的(year, proj_id)字段创建一个索引;

· 创建索引的语法:(千万别忘了写索引名!)

CREATE INDEX 索引名 ON 表名(字段1,字段2...);

· 解答:

CREATE INDEX work_year_proj ON work(year,proj_id);

你可能感兴趣的:(MySQL学习,数据库,sql,mysql,数据库期中)