最近复习了一下SQL语句,用把SQL各种基本的用法小小地总结了下
一、表的创建
1、创建表
格式:
1 CREATE TABLE 表名 2 (列名 数据类型(宽度)[DEFAULT 表达式][COLUMN CONSTRAINT], 3 ... 4 [TABLE CONSTRAINT] 5 [TABLE_PARTITION_CLAUSE] 6 );
例子:
1 CREATE TABLE book( 2 book_number VARCHAR2(5), 3 book_name VARCHAR2(30), 4 pub_com_number VARCHAR2(2), 5 author VARCHAR2(10), 6 publishing_date DATE, 7 volume INT(3), 8 price FLOAT9 );
通过上面的SQL语句,我们就在数据库中创建了一个简单的数据表,这里我们使用mysql来进行演示
2、通过现有的表创建表
CREATE TABLE tablename(column_name1,column_name2) AS SQL 查询语句
Eg:
(1)完全复制表结构和数据
create table book1 as select * from book;
PS.关于查看数据表结构,有两种方式:
a.DESCRIBE(简写DESC)`table_name`;
b.SHOW FULL COLUMNS FROM `table_name`;
可以看出,两者的区别使用SHOW FULL COLUMNS还会显示数据表的一些键还有字段注释。
说到这里,顺带说说在win下面如何使用mysql的dos终端:
a.进入mysql.exe所在目录
b.执行mysql.exe -u用户名 -p密码
c.选择你要进行操作的数据库,语法为:use 数据库名 ,如果你不知道都有哪些数据库,可以使用show databases;来查看
d.查看数据库中的数据表,使用show tables;
(2)只复制数据表中的某些字段建表
create table copy_table_name as select `column_name1`,`column_name2`,..., from table;
如果你想在复制的时候对这些字段进行重命名,可以这样做
create table copy_table_name(`new_column_name1`,`new_column_name2`,..) as select `column_name1`,`column_name2`,... From table;
不过这种语法在MySQL里不支持,在Oracle中支持
(2)删除已创建的数据表
DROP TABLE table_name;
二、表的结构修改
1、为数据表增加新列,即增加一个字段
ALTER TABLE `table_name`
ADD `column_name` dataType(maxLength) [DEFAULT `默认值`][字段约束];
(中括号意为可选)
2、对数据表某一列即某个字段进行修改
语法跟增加差不多只是把ADD关键字改成MODIFY
ALTER TABLE `table_name`
MODIFY `column_name` dataType(maxLength) [DEFAULT `默认值`][字段约束];
注意:字段名无法被修改!!!如果要改变列名,只能先删除该列,然后重新增加。其他部分 都可以进行修改,如果没有给出新的定义,表示该部分属性不变。
修改列定义还有以下一些特点:
(1) 列的宽度可以增加或减小,在表的列没有数据或数据为NULL时才能减小宽度。
(2) 在表的列没有数据或数据为NULL时才能改变数据类型,CHAR和VARCHAR2之间可以随意转换。
(3) 只有当列的值非空时,才能增加约束条件NOT NULL。
(4) 修改列的默认值,只影响以后插入的数据。
3、删除数据表的一列即一个字段
ALTER TABLE `table_name` DROP COLUMN `column_name`;
三、表的数据更新
1、插入
INSERT INTO `table_name`(`column_name1`,`column_name2`,..) VALUES (val1,val2,..);
遇到字段很多的表,如果要插入全部字段的值,一个一个字段名声明很麻烦,可以直接省去这一步
INSERT INTO `table_name` values (val1,val2,...)
有的时候我们想从一个表中复制数据数据过来,可以吗?没问题
INSERT INTO `table_name` (`column_name1`,`column_name2`,..) SELECT
(`column_name1`,`column_name2`,..) FROM `other_table_name`;
2、修改数据
使用UPDATE关键字对数据进行修改,不过往往需要用WHERE子句加限制条件,不然会修改所有的行。
UPDATE `table_name` SET `column1` = val1,`column2` = val2,... WHERE condition;
特殊用法:通过其他查询结果更新数据
UPDATE 表名 SET(字段名1, 字段名2, ...)=SELECT (字段名1, 字段名2, ...) FROM 另外的表名WHERE条件;
3、删除数据
删除数据一样非常敏感,在执行之前一定要检查是否有where条件,否则会删除数据表中的全部数据。
DELETE FROM `table_name` WHERE condition;
如果我们想清空数据表中的所有数据,可以用:
DRUNCATE `table_name`
这里你可能会自然而然想到,我用delete from `table_name`不也可以达到相同的效果么?确实,但其实两者还是有一些区别的:
两者均是删除数据表中全部数据,但是使用truncate的速度更快,且使用的系统和事务日志资源少,delete语句每删除一行,都要在事务日志中为所删除的每行记录一项;而truncate通过释放存储表数据所用的数据页来删除数据,并只在事务日志中记录页的释放。Truncate删除内容释放空间,delete删除内容不释放空间。
4、查询数据
(1)指定索引字段
SELECT 字段名列表 FROM 表名 WHRER 条件
(2)显示计算列
查询语句中可以有算术表达式,包括+、-、*
(3)使用别名
(4)字符串拼接
在oracle中使用“||”,在MySQL中则使用concat()函数
要达到相同的效果上图sql语句在oracle中的用法应该为:
select ‘书名为:’||`book_name`||’ 价格为:’||`price` as `descript` from book2;
(5)消除重复
如果在显示结果中存在重复行,可以使用关键字DISTINCT消除重复显示
SELECT DISTINCE 字段名 FROM 表名
加入我们对多个字段去重,那么显示的结果是多个字段的组合不重复结果
(6)排序
使用ORDER BY关键字,有升序降序之分,ASC表示升序,DESC表示降序
升序:
SELECT * FROM表名 ORDER BY `字段名` ASC;
降序:
SELECT * FROM表名 ORDER BY `字段名` DESC;
多列排序:
SELECT * FROM表名 ORDER BY `字段名1`,`字段名2`,... ;
多列排序中,前面字段名的排序优先级高,即后面字段的排序是在前面字段排序的结果的基础上再进行排序的。
PS.多列排序中的字段名包括对字段的重命名和自定义字段
5、条件查询
(1)简单条件查询
要对显示的行进行限定,可在FROM从句后使用WHERE从句,在WHERE从句中给出限定的条件,因为限定条件是一个表达式,所以称为条件表达式。条件表达式中可以包含比较运算,表达式的值为真的记录将被显示。
PS.只有数值和日期型的字段才能进行大小的比较,字符型字段只能比较是否相等
(2)符合条件查询
可以用逻辑运算符构成复合的条件查询,即把两个或多个条件,用逻辑运算符连接成一个条件。有3个逻辑运算符,如下图所示:
运算的优先顺序是NOT,AND,OR。如果要改变优先顺序,可以使用括号。
(3)特殊运算表示法
A.between
对于数值型或日期型数据,表示范围时可用以下运算表示方法
[NOT] BETWEEN ... AND ...
B.in
显示值满足特定集合的结果
[NOT] IN ...
C.like
使用like操作符可完成按通配符查找字符串,适用于模糊查询
[NOT] LIKE 匹配模式
匹配模式中除了可以包含固定的字符之外,还可以包含以下的通配符:
%:代表0个或多个任意字符。
_ :代表一个任意字符。
Eg:
查找开头为“我”的书籍信息
如果想查找书名第二个字符为“+”的书籍
D.判断某字段是否为空值
[NOT] NULL
四、表的高级查询
1、多表联合查询
通过连接可以建立多表查询,多表查询的数据可以来自多个表,但是表之间必须有适当的连接条件。为了从多张表中查询,必须识别连接多张表的公共列。一般是在WHERE子句中用比较运算符指明连接的条件。
忘记说明表的连接条件是常见的一种错误,这时查询将会产生表连接的笛卡尔积(即一个表中的每条记录与另一个表中的每条记录作连接产生的结果)。一般N个表进行连接,需要至少N-1个连接条件,才能够正确连接。两个表连接是最常见的情况,只需要说明一个连接条件。
两个以上的表也可以进行连接,在这里不做专门介绍。
两个表的连接有四种连接方式:
- 相等连接。
- 不等连接。
- 外连接。
- 自连接。
(1)相等连接
通过两个表具有相同意义的列,可以建立相等连接条件。使用相等连接进行两个表的查询时,只有连接列上在两个表中都出现且值相等的行才会出现在查询结果中。
举个例子:
我们假设有一个学生表student和一个老师表teacher。student表里面有学生的信息,其中一个关键字段是老师的t_id,对应teacher表的id,这里我们简化一下老师和学生的关系是一对一的,即一个老师只能执教一个学生,一个学生只能被一个老师执教
我们要求查询学生和老师的对应关系和学生id,这时可以联表相等查询:select s.id,s.name,t.name from student s,teacher t where s.t_id = t.id;
(2)不等连接
跟上面类似
(3)外连接
使用上面的相等或不等连接会产生一个问题,就是我们只能看到有上老师的课的学生的信息而不能看到没有选老师的课的学生的信息,如果我们想在和老师的表进行连接时还想显示全部学生的信息怎么办?外连接可以达到这个目的!
外连接不仅显示满足相等连接条件的记录,还显示不满足条件连接的行。
外连接的种类有三种,分别为:
左外连接:左边的表不加限制
右外连接:右边的表不加限制
全外连接:左右两表都不加限制
这里我们用老师和学生的关系来说明这三种外连接:
如下图所示,学生表里有个t_id表示被执教的老师id,老师表里有个s_id表示老师执教的学生id,老师和学生是一对一的关系。
我们初始化数据,学生表里陈六没有被任何一名老师执教,老师kalay也没有执教任何一名学生。
当我们想查询被执教的学生和对应老师信息时,使用如下查询:
那假如同时我们还想显示其他没有被执教的学生的信息呢?使用左连接left join
如果我们想显示的是全部老师执教情况的信息呢?使用右连接right join
如果我们想显示出了正常执教的老师和正常被执教的学生之外,还想显示没有被执教的学生和没有执教的老师呢?用全连接full join,但是在mysql中是不支持full join的,那怎么达到full join的效果呢?仔细观察上面左右连接,我们发现左右连接的合集就是全连接的集合了,这里我们可以使用union去重达到全连接full join的效果了。
(4)自连接
自连接就是一个表,同本身进行连接。对于自连接可以想像存在两个相同的表(表和表的副本),可以通过不同的别名区别两个相同的表
Eg:
经理和雇员都在雇员表中,每个雇员有一个对应管理的经理,要查询雇员和对应经理的名称。这种查询在无限分类表中也很常见。
假设雇员表的主键是id,雇员名称是name,经理id是man_id,则上述查询要求对应sql应该为
SELECT work.name,manager.name FROM `employ` worker,`employee` manager WHERE work.man_id = manager.id;
2、统计查询
通常需要对数据进行统计,汇总出数据库的统计信息。比如,可能想了解公司的总人数和总工资额,或各个部门的人数和工资额,这个功能可以由统计查询完成。
数据库中提供了一些函数来完成统计工作,这些函数称为组函数,组函数不同于前面介绍和使用的函数(单行函数)。组函数可以对分组的数据进行求和、求平均值等运算。组函数只能应用于SELECT子句、HAVING子句或ORDER BY子句中。组函数也可以称为统计函数。
3、子查询
很多情况下,我们需要做这样的操作,把一个查询的结果作为另一个查询的一部分,第一个查询可以作为第二个查询的一部分出现在第二个查询的条件中,这样的查询叫做子查询。
子查询一般出现在SELECT语句的WHERE子句中,Oracle也支持在FROM或HAVING子句中出现子查询。子查询比主查询先执行,结果作为主查询的条件,在书写上要用圆括号扩起来,并放在比较运算符的右侧。子查询可以嵌套使用,最里面的查询最先执行。子查询可以在SELECT、INSERT、UPDATE、DELETE等语句中使用。
这里已雇员和工资的关系为例,假设有一个雇员表emp,每一行代表一名雇员的信息,有ename、sal、empno、job、deptno字段分别代表雇员名、雇员工资、雇员号、工作岗位和部门。
(1)单行子查询
如果子查询只返回一行结果,我们称之为单行子查询
例子: 查询一个比SCOTT工资高的雇员名字和工资
分析:对SCOTT工资的查询为子查询,只有先查出这个,才能差距SCOTT的工资查到我们想要查询的结果
SQL语句:SELECT ename,sal FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename == ‘SCOTT‘);
(2)多行子查询
如果子查询返回多行结果,称之为多行子查询。多行子查询经常使用不用的比较运算符,它们是IN、ANY和ALL
例子:查询工资低于任何一个“CLERK”的工资的雇员信息
分析:有任何的关键字,故使用ANY比较运算符
SQL语句:SELECT * FROM emp WHERE sal < ANY(SELECT sal FROM emp WHERE job = ‘CLERK‘) AND job != ‘CLERK‘;
例子:查询工资比所有的“SALESMAN”都高的雇员的编号、名字和工资
分析:有所有关键字,使用ALL比较运算符
SQL语句:SELECT empno,ename,sal FROM emp WHERE sal > ALL(SELECT sal FROM emp WHERE job = ‘SALESMAN‘);
例子:查询部门20中职务同部门10的雇员一样的雇员信息
分析:有在什么中的范围关键字,用IN比较运算符
SQL语句:SELECT * FROM emp WHERE job in (SELECT job FROM emp WHERE deptno = 10) AND deptno = 20;
(3)多列子查询
如果子查询返回多列,则对应的比较条件中也应该出现多列,这种查询成为多列子查询。
例子:查询职务和部门与SCOTT相同的雇员的信息
SQL语句:SELECT * FROM emp WHERE (job,deptno) = (SELECT job,deptno FROM emp WHERE ename = ‘SCOTT‘);
4、集合运算
多个查询语句的结果可以做集合运算,结果集的字段类型、数量和顺序应该一样。
并集
差集
MySQL不支持MINUS
要达到类似的效果,可使用IN、NOT IN,也可以配合使用UNION ALL来实现,不过只建议数据量比较小的时候使用,否则效率比较低
使用union all实现差集
使用not in实现交集
交集
使用union all实现交集
使用in实现交集