Skip to content

SQL 语法

约 1675 个字 85 行代码 预计阅读时间 7 分钟

SQL虽然有统一的标准,但是各家公司产品的语法并不完全统一,部分是因为不同的数据库公司要体现自己产品的特点。SQL语句可以分为DDL,DML和DCL三类。这篇文章里面是mysqlsql server语法都有,具体会有说明。

语法及分类

通用规则

  • 单行或者多行书写,以分号结尾
  • MySQL的语句不区分大小写,关键字建议使用大写
  • 注释:
  • 单行注释:--或者#(MySQL特有)
  • 多行注释:/* */

DDL

创建库

新建一个数据库,但是如果有图形化界面(如SSMS)可能就无需这么做

CREATE DATABASE 数据库名;

创建表

新建一张表

CREATE TABLE 表名(
    变量名 变量类型
    一些限制(可选)
);

比如我新建一张图书的表

CREATE TABLE book(
    bno         char(8) PRIMARY KEY,
    category    char(10),
    title       varchar(40) not null,
    press       varchar(30),
    year        int,
    author      varchar(20),
    price       decimal(7,2),
    total       int,
    stock       int 
    -- 主键也可以写在最后
    -- PRIMARY KEY(bno)
    CHECK (stock >= 0)
);

常见的类型有:

  • char(n):固定长度为n的字符串,输入数据可以长度不足,虽然会浪费空间,但是如果超长应该会被阻止输入
  • varchar(n):最长为n的字符串,会根据字符串实际长度调整存储空间大小
  • int:整型,也许还会有smallint
  • float(n):浮点型,至少有n位小数
  • numeric(m,n):m位精度,n位小数
  • date:日期,在sql sever里面是datetime,格式为2025-02-26
  • time:时间,格式为13:14:15

SQL 提供了用于类型转换计算的函数,但是这个不是很统一,列举一些基本都有的:

  • Abs:绝对值
  • exp:指数
  • round:四舍五入
  • sin
  • cos

删除和修改

首先是删除表,一般来说可能会需要管理员权限

DROP TABLE 表名;
其次可以给表增加列,新增的列默认值是null

ALTER TABLE 表名 ADD A D;
ALTER TABLE 表名 ADD A1 D1,A2 D2,...,An Dn;

也可以删除列,这个很多数据库都不支持

ALTER TABLE 表名 DROP A;

此外还可以调整

ALTER TABLE 表名 MODIFY (A1 D1,A2 not null);

创建索引

索引会优化查询速度,如果你要经常用某个键查询,那么最好给这个键创建一个索引

CREATE INDEX 索引名 ON 表名 键(属性表);
--还可以指定为 UNIQUE 来声明候选键
DROP INDEX 索引名 --可以用来删除索引

选择

USE 数据库名;

查询语句

SQL 里面最复杂的就是查询,有非常多相关的语法和技巧。

基础用法

用于从数据库中选取数据,可以指定多个字段,不指定则会选择所有字段

SELECT column1, column2, ... FROM table_name;

或者,其中*是通配符,表示选择表中的所有列

SELECT * FROM table_name;
有个冷知识,SELECT 1并非毫无意义,它常用于测试数据库连接;还有另一个冷知识,SQL不允许在名称中有-,此外SQL中的名称是大小写不敏感的,一般关键字大写,其余小写。

SQL是允许表中有重复(没有设置主键或者UNIQUE之类的)和查询结果有重复的,我们可以使用DISTINCT来去重,与之相对的关键字是ALL,默认状态下就是ALL

SQL查询是允许进行计算的,比如

SELECT salary/1.2 FROM instructor

重命名

可以用AS来给重命名,既可以是属性名,也可以是表名。

SELECT A.title AS 标题, A.bno AS书号, B.cno AS 借书卡号
FROM book AS A, borrow AS B 
WHERE A.bno=B.bno

WHERER 子句

SELECT column1, column2, ... FROM table_name WHERE condition;

condition 可以使用ANDORNOT以及BETWEEN连缀

需要注意SQL里面的不等于是<>以及WHERE子句里面是不允许有聚合函数的,这是因为 WHERE 子句用于在聚合之前过滤行,而聚合函数是对一组行进行计算。

ORDER BY 关键字

用于对结果集按照一个列或者多个列进行排序

SELECT column1, column2, ... FROM table_name 
ORDER BY column1, column2, ... DESC; --默认是升序,但是经常需要的是降序

ASC是升序,DESC是降序

SELECT LIMIT 子句

用于只需要查询前几行数据的情况,mysqlLIMITsql serverTOP

--这个是mysql的语法
SELECT column1, column2, ...
FROM table_name 
LIMIT number1
OFFSET number2;
这个表示从第number2条记录开始截取number1条记录

LIKE 操作符

用于模糊化查询,类似于正则表达式

SELECT column1, column2, ... FROM table_name
WHERE column_name LIKE pattern;
pattern中可以使用通配符: * %用于匹配任意字符串 * _用于匹配单个字符 * []用于匹配字符列中的任何单一字符 * [^]用于匹配不在字符列中的任何单一字符

字符串操作

比如我想在查询结果前面加一串文字,在mysql里面是CONCAT

SELECT '教师名=' || name FROM instructors WHERE ...

以及转换大小写,求字符串长度等操作都有相应函数

BETWEEN 操作符

用于选取介于两个值之间的数据范围内的值

SELECT column1, column2, ...
FROM table_name WHERE column BETWEEN value1 AND value2;

聚合查询

对于统计总数、平均数这类计算,SQL提供了专门的聚合函数,包括以下这些 |函数|说明| |-|-| |COUNT|计算行数| |AVG|计算平均值| |SUM|计算最大值| |MAX|计算某一列的最大值| |MIN|计算某一列的最小值|

SQL还提供了分组聚合的功能,可以用GROUP BY进行分组。需要注意在有聚合函数的情况下,不是聚合函数的属性必须在GROUP BY列表里面,换言之就是SELECT 子句中的列必须是聚合函数或 GROUP BY 子句中包含的列

HAVING 子句

对聚合函数结果进行选择,需要注意,HAVING子句里面的元素如果不是聚合函数里的属性,那么就必须在GROUP BY列表里面

关于 null

null表示未定义,不等于0,含null的算数运算结果都是null,含null的逻辑比较结果都是unknow,对unknow的逻辑运算比较特别,既不能肯定它也不能否定它

(unknow or false) = unknow
(unknow and true) = unknow
not unknow = unknow

此外需要注意null是不能用=null去判定的,正确的写法应该是is null

聚合函数除了COUNT都会忽略null,如果全是null,结果也自然是null

嵌套查询

也可以叫子查询(subquery),查询的结果是一张表,然后我们对这张表进行查询,格式是(SELECT 语句);

SELECT DISTINCT course_id FROM section
WHERE semester = 'Fall' and yaer = 2025
    and course_id in (
        SELECT course_id FROM section
        WHERE semester = 'Spring'
            and year = 2024
    );

子查询操作

some

与集合中的某些值比较,相当于存在

5 < some(1,3,5,7) true 因为 5 < 7
5 = some(1,3,5,7) true 因为 5 = 5
5 > some(1,3,5,7) true 因为 5 > 1

=somein是等价的,但是反过来不等价,!=some不等价于not in

ALL

与集合中任意元素比较,相当于任意,可以用来查找最大或者最小的元素

空集测试

用于判断子查询是否存在,EXIST r等价于r非空

唯一性

unique用于验证子查询结果中是否有重复语句

视图

用于对特定的用户隐藏特定的数据,主要是出于安全考虑

CREATE VIEW 视图名 AS ... SELECT c1,c2,... FROM ...;
DROP VIEW 视图名

复合查询

导出关系

相当于从子查询结果中查询,这种情况下必须给子查询结果命名

SELECT dept_name, avg_salary
FROM (
    SELECT dept_name, avg(salary)
    FROM instructors
    GROUP BY dept_name
) AS dept_avg(dept_name, avg_salary) --相当于一个视图
WHERE avg_salry > 42000;

WITH 语句

允许创建局部(针对一个查询语句而言)视图,而非全局,上面那个查询语句可以改写为

WITH dept_avg(dept_name, avg_salary) AS
    SELECT dept_name, avg(salary)
    FROM instructors
    GROUP BY dept_name
SELECT dept_name, avg_salary
FROM dept_avg
WHERE avg_salry > 42000;

修改与删除

INSERT INTO 语句

用于向表中插入新记录,没有指定要插入数据的列名的形式需要列出插入行的每一列名称:

INSERT INTO table_name
VALUES (value1,value2,value3,...);
--在高版本的 SQL Server里面允许一次性写多个VALUES
也可以指定列名和插入的值
INSERT INTO table_name (column1,column2,column3,...)
VALUES (value1,value2,value3,...);

UPDATE 语句

用于更新指定值

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

DELETE 语句

用于删除表中的行

DELETE FROM table_name WHERE condition;