1 SQL查询语言概览
SQL(strctured Query Language)包括以下几个部分:
数据定义语言DDL:提供定义关系模式、修改关系模式和删除关系模式的命令
数据操纵语言DML:提供从数据库中查询信息,以及插入、删除、修改元组的能力
完整性:DDL包括完整性约束的命令,保存在数据库中的数据必须满足定义的完整性约束。
视图定义:DDL包括定义视图的命令。
事务控制:SQL包括定义事务开始点和结束点的命令。
嵌入式SQL和动态SQL。嵌入式和动态SQL定义SQL语句如何嵌入诸如C、C++和Java这样的通用编程语言。
授权:SQL和DDL包含定义对关系和视图的访问权限的命令。
在本篇文章,我们学习最基本的DDL和DML,这是SQL-92标准以来就一直存在的部分。工作中,后端开发工程师们最常用的就是这部分内容。
2 SQL数据定义
2.1 基本类型
SQL支持的基本类型如下(后续文章将介绍更多)。
char(n),定长字符串。
varchar(n),最大长度为n的变长字符串
int:整数(依赖于机器的整数的有限子集)
smallint:小整数(依赖与机器的整数类型的子集)
numeric(p,d):总长度为p,小数点右边有d位数字的指定精度定点数。
real,double precision:浮点数和双精度浮点数,精度依赖于机器
float(n):精度至少为n位数字的浮点数。
每种类型都可能包含一个空值,这是一个特殊值,表示一个缺失的值,它有可能存在但不为人所知,有可能根本不存在。在特定情况下,可能希望禁止加入空值。
char是定长的,如果存入的属性长度没有n,会追加空格补全。因此char和varchar类型的数据可能无法比较,因为即使他们存的是相同的值,也可能返回false,建议始终使用varchar避免这样的问题。下表是一些char,varchar存储数据的实例对比。
SQL还提供nvarchar
类型来存放使用Unicode
表示的多语言数据。然而,很多数据库甚至允许在varchar
类型中存放Unicode
(采用utf-8
形式)。
2.2 基本模式定义
(1)创建关系
创建一个关系,很简单。顺带一提,最后的分号是可选的。
create table test ( test_id int, test_depat_name varchar(15), test_price numeric(12,2) not null, test_desc varchar(255), primary key(test_id), foreign key(test_dept_name) references department );
上面使用了主键约束primary key
,外键约束foreign key
,非空约束 not null
。值得关注的是,包括Mysql
在内的数据库需要使用另一种外键约束的用法:foreign key(test_dept_name) references department(dept_name)
(2)删除关系
drop table r;
这个命令会删除r中所有元组,并且删除关系。下面的sql更弱点,会删除元组,但是保留关系。
delete form r;
(3)修改关系结构
给关系r增加属性A,其类型为D。
alter table r add A D;
删除关系中的属性。
alter table r drop A;
3 SQL查询的基本结构
在讲解前,先放下后续会用到的一些表(除此外还有department,emp这种简单的表结构)。
3.1 单关系查询
查询并去重。
SELECT DISTINCT ename FROM emp;
SQL还允许显示指定不去重,但它是可以缺省的元素。
SELECT ALL ename FROM emp;
可以结合+
,-
,*
,/
运算符来使用select子句。
SELECT ename, salary * 1.1 FROM emp;
where子句可以增加查询条件。
select * from emp where sal between 2000 and 3000;
在SQL中,比较运算符>
,<
等等可以用来比较字符串、算数表达式以及特殊类型(如日期)。
3.2 多关系查询
我们可以在where子句中指定匹配条件,然后进行多关系查询。
select e.empno,e.ename,d.dname,e.deptno,d.deptno from emp e,dept d where e.deptno=d.deptno;
上面的实例给关系取了别名,这是区分不同关系中的同名属性的好办法。
事实上查询时,select
,from
,where
子句并不是顺序执行的。正确的理解如下。
1.为from所列出的关系产生笛卡尔积。
2.在1的结果上应用where子句中指定的谓词。
3.对步骤2的结果中的每个元组,输出select子句中指定的属性(或表达式的结果)。
可以料想到,where子句十分关键,否则结果会直接输出笛卡尔积,那可是相当大的数据量
4 附加的基本运算
4.1 更名运算
对属性可以使用更名运算进行更名。
SELECT emp_department AS edept FROM emp;
还可以用它来重命名关系,重命名关系的一个原因时把一个长的关系名替换成为短的。
select e.empno,e.ename,d.dname,e.deptno,d.deptno from emp as e,dept as d where e.deptno=d.deptno;
除此外,一个关系与自身进行笛卡尔积运算也需要使用重命名。比如找出至少比运维部门某一位员工工资更高的所有员工姓名。
select distinct T.name from emp as T,emp as S where T.sal > S.sal and S.deptname = '运维部';
4.2 字符串运算
在SQL标准中,字符串的相等运算是大小写敏感的。但是在一些数据库中(如Mysql和SQL Server),在匹配字符串时并不区分大小写。
字符串可以应用许多函数运算,比如连接字符串(||
),提取子串,去字符串后空格trim
等等。不同数据库系统提供的函数集是不同的,具体可以查阅数据库系统手册。
使用like
可以进行模糊匹配。有两个特殊的字符串可以用来描述模式。
- 百分号
%
:匹配任意字串 - 下划线
_
:匹配任意一个字符
模式是大小写敏感的(Mysql中除外,PostgreSQL使用ilike大小写也不敏感)。
另外,为了能够使模式包含特殊字符(%
和_
),SQL允许使用escape
关键字定义转义字符。如
like 'ab\%cd% escape '\'
表示匹配以'ab%cd
开头的所有字符。
SQL标准还允许我们通过not like
比较运算符来搜索不匹配想。一些实现还提供了不区分大小写的变种。
一些SQL实现,特别是PostgreSQL,提供了similar to
运算。它具备比like
更强大的模式匹配能力,其模式定义语法类似UNIX
中使用的正则表达式。
4.3 排序
使用order by
关键字就可以实现排序了。desc
表示降序,asc
表示升序,缺省时默认升序。
select empno, ename from emp where hiredate between date '1980-01-01' and date '1981-01-01' order by empno desc;