title: 数据库——常用SQL语句
date: 2024-07-06 12:25:36
tags: 数据库
categories: 数据库
cover: /image/T1.jpg
description: 数据库的常用SQL语句
SQL语句
SQL(Structured Query Language)是一种用于访问和操作数据库系统的标准编程语言。它允许用户执行各种数据管理任务,如查询、更新、插入和删除数据库中的数据。以下是一些基本的SQL语句示例:
1. 创建数据库(Create Database)
CREATE DATABASE myDatabase;
2. 创建表(Create Table)
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INT,
grade VARCHAR(50)
);
3. 插入数据(Insert)
INSERT INTO students (name, age, grade) VALUES ('Alice', 20, 'A+');
INSERT INTO students (name, age, grade) VALUES ('Bob', 22, 'B');
4. 查询数据(Select)
- 查询所有记录
SELECT * FROM students;
- 查询特定列
SELECT name, age FROM students;
- 带条件的查询
SELECT * FROM students WHERE grade = 'A+';
5. 更新数据(Update)
UPDATE students SET grade = 'A' WHERE name = 'Bob';
6. 删除数据(Delete)
DELETE FROM students WHERE name = 'Alice';
7. 聚合函数(Aggregate Functions)
- 计数
SELECT COUNT(*) FROM students;
- 求和
SELECT SUM(age) FROM students;
- 平均值
SELECT AVG(age) FROM students;
8. 排序(Order By)
SELECT * FROM students ORDER BY age DESC;
9. 分组(Group By)
SELECT grade, COUNT(*) FROM students GROUP BY grade;
10. 连接(Join)
-- 假设有另一个表grades,包含grade_id和grade_name
SELECT students.name, grades.grade_name
FROM students
JOIN grades ON students.grade = grades.grade_id;
注意事项
- SQL语法可能因数据库系统的不同(如MySQL、PostgreSQL、SQL Server等)而略有差异。
- 在执行删除或更新操作时要格外小心,以避免数据丢失。
- 聚合函数和分组通常与
HAVING
子句结合使用来过滤分组后的结果。 - 连接操作(Join)是处理多个相关表时非常有用的技术。
SQL语句分类
SQL(Structured Query Language)语言是一种用于管理关系型数据库系统的标准化语言。根据功能和应用领域的不同,SQL语言可以大致分为以下几类:
1. 数据查询语言(DQL, Data Query Language)
- 主要功能:用于从数据库中检索所需的数据。
- 核心命令:SELECT。
- 特点:允许用户根据特定条件过滤数据,排序结果集以及执行数据聚合操作。
- 应用领域:网站和应用程序的数据检索、报表生成和数据分析等。
2. 数据操纵语言(DML, Data Manipulation Language)
- 主要功能:用于改变数据库中的数据。
- 主要命令:INSERT(插入)、UPDATE(更新)、DELETE(删除)。
- 特点:通过DML,用户可以向数据库中插入新的数据、修改已有的数据,或者删除不再需要的数据。
- 应用领域:用户在应用程序中提交表单时的数据插入、数据库中记录的更新和修正等。
3. 数据定义语言(DDL, Data Definition Language)
- 主要功能:用于定义数据库的结构和组件。
- 主要命令:CREATE(创建)、ALTER(修改)、DROP(删除)。
- 特点:通过DDL,用户可以创建新的表、修改表结构,或者删除已有的表。DDL操作通常是隐式提交的,不能回滚。
- 应用领域:数据库的初始化和配置、数据库升级和维护等。
4. 数据控制语言(DCL, Data Control Language)
- 主要功能:用于控制数据库用户的访问权限和安全性。
- 主要命令:GRANT(授权)、REVOKE(收回权限)。
- 特点:通过DCL,数据库管理员可以对用户进行授权或者撤销权限,以保护数据库中的敏感信息。
- 应用领域:用户账户管理、数据库安全审计、数据访问权限控制等。
5. 事务控制语言(TCL, Transaction Control Language)(在某些分类中可能不直接列出)
- 主要功能:用于维护数据的一致性。
- 主要命令:COMMIT(提交)、ROLLBACK(回滚)、SAVEPOINT(保存点)。
- 特点:TCL允许用户将一系列操作组合成一个事务,并通过提交或回滚来确保数据的一致性。
- 应用领域:在处理复杂业务逻辑时,确保数据的完整性和一致性。
超键和主键
在数据库管理系统中,超键(Super Key)和主键(Primary Key)是两个重要的概念,它们对于数据的唯一性和完整性起着至关重要的作用。主键是超键的一个特例,具有更严格的唯一性约束和更少的冗余属性:
一、超键(Super Key)
-
定义:在关系中能唯一标识元组(即表中的一行)的属性集称为关系模式的超键。一个属性或多个属性的组合,只要它们能够唯一地确定表中的一行,就可以被视为超键。
-
特点:超键不是唯一的,一个表可以有多个超键。超键包含候选键和主键,是它们的超集。超键中的属性可以是多余的,即去掉某些属性后,剩余的属性仍然能唯一标识元组。
二、主键(Primary Key)
-
定义:主键是用户选作元组标识的一个候选键。在数据库表中,主键是对储存数据对象予以唯一和完整标识的数据列或属性的组合。
-
特点:一个表只能有一个主键。主键的值不能为空(NULL),且不能重复。主键是从候选键中选择的,而候选键是不含有多余属性的超键。主键的选取通常考虑查询的方便性、数据的完整性和系统的性能。
三、超键与主键的关系
- 包含关系:超键包含主键,即主键是超键的一个特例。
- 冗余性:超键可能包含冗余属性,而主键则不含有多余属性。
- 唯一性:超键和主键都能唯一标识表中的一行,但主键是更严格的唯一性约束。
四、示例
假设有一个学生表(Student),包含以下属性:学号(StudentID)、姓名(Name)、性别(Gender)、身份证号(IDCard)。
- 超键:可以是(学号)、(身份证号)、(学号,姓名)、(身份证号,性别)等。其中,(学号,姓名)虽然能唯一标识学生,但姓名是冗余的,因为学号已经足够唯一。
- 候选键:根据候选键的定义(不含有多余属性的超键),学生表中的候选键可以是(学号)或(身份证号)。
- 主键:在候选键中,我们通常会选择一个作为主键。例如,可以选择(学号)作为主键。
SQL约束
SQL约束是在关系型数据库中用于保障数据完整性和一致性的重要工具。它们定义了表中数据的规则和限制条件,确保数据满足预期的要求,防止无效或不一致的数据进入数据库。SQL约束可以分为多种类型,主要包括以下几种:
1. 非空约束(NOT NULL)
- 定义:强制列不接受NULL值。
- 用途:确保字段始终包含值,防止数据缺失。
- 语法:在创建表时,通过在列定义后添加
NOT NULL
来指定。
2. 唯一约束(UNIQUE)
- 定义:唯一标识数据库表中的每条记录或一组记录。
- 用途:保证某一列或列组合的值在表中是唯一的。
- 注意:唯一约束允许列中存在NULL值,但每个NULL值都被视为不同的值(除非在唯一索引上使用了
UNIQUE_NULLS
设置,这取决于具体的数据库系统)。 - 语法:在创建表时,使用
UNIQUE
关键字或UNIQUE(column_name)
来指定。
3. 主键约束(PRIMARY KEY)
- 定义:唯一标识表中的每一行数据,且不允许为空。
- 用途:作为表的唯一索引,保证数据的唯一性和完整性。
- 特点:主键列的值在表中必须是唯一的,且不能包含NULL值。每个表只能有一个主键,但主键可以包含多个列(称为复合主键)。
- 语法:在创建表时,使用
PRIMARY KEY
关键字或PRIMARY KEY(column_name)
来指定。
4. 外键约束(FOREIGN KEY)
- 定义:一个表中的外键指向另一个表的主键,用于建立表与表之间的关系。
- 用途:确保一个表中的某个列或列组合的值必须是另一个表中主键列或主键列组合的值之一,从而维护表之间的引用完整性。
- 注意:外键约束用于预防破坏表之间连接的动作,也能防止非法数据插入外键列。
- 语法:在创建表时,使用
FOREIGN KEY (column_name) REFERENCES parent_table(parent_column_name)
来指定。
5. 检查约束(CHECK)
- 定义:定义一个布尔表达式来评估插入或更新的值是否满足特定条件。
- 用途:限制列中的值的范围,确保数据的准确性。
- 语法:在创建表时,使用
CHECK (condition)
来指定。
6. 默认约束(DEFAULT)
- 定义:为给定列提供默认值,如果插入或更新操作未指定该列的值,则将使用默认值。
- 用途:简化数据输入,确保数据的完整性。
- 语法:在创建表时,使用
DEFAULT value
来指定。
约束的创建、修改和删除
- 创建约束:在创建表时,可以直接在列定义后指定约束。也可以使用
ALTER TABLE
语句在表创建后添加约束。 - 修改约束:通常需要先删除原有的约束,然后添加新的约束。这可以通过
ALTER TABLE
语句来实现。 - 删除约束:使用
ALTER TABLE
语句结合DROP CONSTRAINT
选项来删除已定义的约束。
char和varchar
char和varchar是数据库中常用的两种字符串数据类型,它们之间存在一些关键的区别,主要包括以下几个方面:
-
长度固定与可变:
- char:长度固定。比如char(10),无论存储的字符串多长,都会占用10个字符的空间。如果字符串不足10个字符,剩余部分会用空格填充(尽管在检索时这些空格可能不被显示)。
- varchar:长度可变。varchar(10)只会占用实际字符串长度加上一个或两个额外字节(用于记录长度)的空间。如果字符串是’abc’,则只占用4个字节(3个用于’abc’,1个用于长度)。
-
空间效率:
- char:在存储长度固定的字符串时很有效,但可能会浪费空间,特别是当存储的字符串比定义的长度短时。
- varchar:更节省空间,因为它只占用实际需要的空间加上一点额外的记录长度的空间。
-
性能:
- char:由于长度固定,可能在某些情况下性能稍好(如快速定位),但这也取决于具体的数据库实现和查询类型。
- varchar:当处理可变长度的字符串时,通常提供更好的空间效率,但可能需要更多的处理来管理不同长度的数据。
-
使用场景:
- 使用char时,你知道字段的值将几乎总是具有相同的长度,如日期、电话号码或某些代码。
- 使用varchar时,你预期字段的值长度会有所不同,如名字、地址或描述性文本。
关联查询
关联查询,也称为多表查询,是在数据库中使用多个表的数据来生成一个结果集的查询操作。这些一起查询的表之间通常是通过某些关联字段(如外键)建立关系的。在关联查询中,有多种不同的关联方式,每种方式适用于不同的业务需求和数据模型。以下是几种常见的关联查询方式及其介绍:
1. 内连接(INNER JOIN)
定义:在两个或多个表中查找匹配的行,并返回这些匹配行的数据。如果表之间有至少一个匹配,则返回行。
SQL语句示例:
SELECT a.column1, b.column2
FROM table1 AS a
INNER JOIN table2 AS b
ON a.id = b.id;
使用场景:当只需要返回两个表中符合条件的交集数据时使用。
2. 左连接(LEFT JOIN 或 LEFT OUTER JOIN)
定义:返回左表中的所有行,即使右表中没有匹配的行。如果右表中没有匹配的行,则结果中右表的部分将包含NULL。
SQL语句示例:
SELECT a.column1, b.column2
FROM table1 AS a
LEFT JOIN table2 AS b
ON a.id = b.id;
使用场景:当需要返回左表中的所有数据,以及右表中与左表满足条件的数据时使用。
3. 右连接(RIGHT JOIN 或 RIGHT OUTER JOIN)
定义:与左连接相反,返回右表中的所有行,即使左表中没有匹配的行。如果左表中没有匹配的行,则结果中左表的部分将包含NULL。
SQL语句示例:
SELECT a.column1, b.column2
FROM table1 AS a
RIGHT JOIN table2 AS b
ON a.id = b.id;
使用场景:当需要返回右表中的所有数据,以及左表中与右表满足条件的数据时使用。
4. 全连接(FULL JOIN 或 FULL OUTER JOIN)
定义:返回左表和右表中的所有行。当某行在另一个表中没有匹配时,则对应的结果集部分将包含NULL。
注意:并非所有数据库系统都直接支持FULL JOIN,但可以通过UNION操作结合LEFT JOIN和RIGHT JOIN来实现类似的效果。
SQL语句示例(假设支持FULL JOIN):
SELECT a.column1, b.column2
FROM table1 AS a
FULL OUTER JOIN table2 AS b
ON a.id = b.id;
使用场景:当需要返回左表和右表中的所有数据,以及两个表中满足条件的数据时使用。
5. 交叉连接(Cross Join)
定义:返回两个表中所有可能的行组合。结果集的行数等于左表的行数乘以右表的行数。
SQL语句示例:
SELECT a.column1, b.column2
FROM table1 AS a
CROSS JOIN table2 AS b;
使用场景:当需要返回两个表的笛卡尔积时使用。
6. 自连接(Self Join)
定义:在同一表中进行连接操作的过程,主要用于解决表中字段之间的关联问题。
SQL语句示例:
SELECT a.column1, b.column2
FROM table AS a
JOIN table AS b
ON a.parent_id = b.id;
使用场景:当需要在同一个表中比较不同行的数据时使用,例如,查找员工及其经理的关系。
7. 自然连接(Natural Join)
定义:自动匹配两个表中相同的字段,并返回它们的交集。注意,由于它依赖于字段名相同这一条件,因此在实际应用中可能会因为字段名相同但含义不同而导致错误的结果。
SQL语句示例:
SELECT a.column1, b.column2
FROM table1 AS a
NATURAL JOIN table2 AS b;
使用场景:由于自然连接存在潜在的问题,因此在实际应用中并不推荐使用。如果确实需要类似的功能,建议使用INNER JOIN并明确指定连接条件。
子查询
子查询(Subquery)是嵌套在另一个查询中的查询。子查询可以出现在SELECT、FROM、WHERE等子句中,用于执行更复杂的查询操作。子查询可以返回一个值(标量子查询)、一行多列(行子查询)、多行一列(列子查询)或多行多列(表子查询),具体取决于其使用方式和上下文。
子查询的类型
-
标量子查询:返回一个单一值(如数字、字符串等),通常用于比较操作。
SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);
这个例子中,子查询计算了员工的平均薪资,然后外层查询选择了薪资高于平均薪资的员工。
-
列子查询:返回一列多行的数据,通常与IN、ANY、ALL等操作符结合使用。
SELECT * FROM employees WHERE department_id IN (SELECT department_id FROM departments WHERE location_id = 1700);
这个例子中,子查询找出了位于特定地点的部门ID,然后外层查询选择了属于这些部门的员工。
-
行子查询:返回单行多列的数据,通常与ROW操作符结合使用进行比较。
SELECT * FROM employees e1 WHERE (e1.salary, e1.department_id) = (SELECT MAX(salary), department_id FROM employees e2 GROUP BY e2.department_id);
注意:这个例子可能不完全正确,因为它试图找出每个部门薪资最高的员工,但实际的SQL可能需要更复杂的逻辑(如使用窗口函数)。然而,它展示了行子查询的基本用法。
-
表子查询:返回一个表,可以作为另一个查询的FROM子句中的表。
SELECT * FROM (SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id) AS dept_avg WHERE avg_salary > 50000;
这个例子中,子查询计算了每个部门的平均薪资,然后外层查询选择了平均薪资高于50,000的部门。
子查询的注意事项
- 性能:复杂的子查询可能会降低查询性能,特别是在处理大量数据时。考虑使用JOIN或其他优化技术来提高性能。
- 可读性:过度使用或嵌套过深的子查询可能会降低SQL语句的可读性。在可能的情况下,尝试将复杂的查询分解为更简单的部分。
- 兼容性:不同的数据库系统(如MySQL、PostgreSQL、SQL Server等)在子查询的支持和语法上可能存在差异。编写跨数据库兼容的SQL时,请注意这些差异。
DROP、DELETE 与 TRUNCATE 的区别
特性 | DROP | DELETE | TRUNCATE |
---|---|---|---|
操作对象 | 表或数据库 | 表中的数据行 | 表中的所有数据行(不针对视图) |
执行速度 | 较快(直接删除) | 较慢(逐行删除) | 较快(释放数据页) |
事务与回滚 | DDL操作,自动提交,不可回滚 | DML操作,可回滚(除非已提交) | DDL操作,自动提交,不可回滚 |
因此,在不再需要一张表的时候,采用 DROP
;在想删除部分数据行时候,用 DELETE
;在保留表而删除所有数据的时候用 TRUNCATE
。