初级SQL
1.SQL查询语言概览
1.组成部分
-
数据定义语言
DDL语句用于创建、修改和删除数据库中的表、视图、索引等对象。DDL语句不涉及数据的操作,而是专注于数据库结构的定义。
-
数据操纵语言
DML语句用于插入、更新、删除和查询数据库中的数据。DML语句是数据库操作的核心,因为它们直接影响到数据库中存储的数据。
-
完整性
指确保数据库数据的准确性和一致性的规则和约束。
-
视图定义
视图并不存储实际的数据,而是根据用户的查询需求,从数据库中的一个或多个表中检索数据,并以特定的格式展示给用户。视图的定义包括查询语句,这个查询语句定义了视图将如何从数据库中检索数据。
-
事务控制
数据库管理系统(DBMS)中用于管理事务(一组操作)执行的机制。
-
嵌入式SQL和动态SQL
嵌入式和动态SQL定义SQL语句如何嵌入到通用编程语言,如C,C++和Java中。
-
授权
确保只有经过授权的用户才能执行特定的数据库操作,如查询、插入、更新或删除数据。
2.SQL数据定义
1.基本类型
整数类型
- INTEGER:存储整数,通常用于存储没有小数部分的数字,等价于简称int。
- SMALLINT:存储较小的整数,范围比INTEGER小。
- BIGINT:存储较大的整数,范围比INTEGER大。
浮点数类型
- FLOAT:存储单精度浮点数,适合存储近似值。
- DOUBLE PRECISION或 DOUBLE:存储双精度浮点数,比FLOAT更精确。
定点数类型
- DECIMAL(p, s):存储固定精度的小数,其中p是总位数(加上一个符号位),s是小数点后的位数。
- NUMERIC(p,s):存储固定精度的小数,与DECIMAL类似,但通常用于SQL Server。
字符类型
- 固定长度字符串CHAR(n):存储固定长度的字符串,用户指定长度n,如果字符串长度小于n,则用空格填充,等价于全称character。
- 可变长度字符串VARCHAR(n):存储可变长度的字符串,用户指定最大长度n,如果字符串长度小于n,则不会填充空格,等价于全称character varying。VARCHAR2(n):在Oracle数据库中,VARCHAR2与VARCHAR类似,但通常用于Oracle。
大文本类型
- TEXT:存储可变长度的字符串,适合存储较长的文本。
- CLOB:存储大型文本数据,通常用于存储文章、书籍等。
日期和时间类型
- 日期类型DATE:存储日期,格式为YYYY-MM-DD。
- 时间类型TIME:存储时间,格式为HH:MM:SS。
- 日期时间类型
- DATETIME:存储日期和时间,格式为YYYY-MM-DD HH:MM:SS。
- TIMESTAMP:存储日期和时间,通常用于记录事件的发生时间。
二进制类型
- 二进制类型
- BINARY:存储二进制数据。
- VARBINARY:存储可变长度的二进制数据。
- 大二进制类型
- BLOB:存储大型二进制数据,如文件、图片等。
- 布尔类型
- BOOLEAN:存储布尔值,通常用于表示真或假。
- 枚举类型
- ENUM:存储预定义的枚举值。
集合类型
- SET:存储一个或多个预定义的枚举值。
2.基本模式定义
- 创建数据库
CREATE DATABASE database_name;
示例
create database university;
- 使用数据集库
USE my_database;
示例
USE university;
- 定义SQL关系
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
column3 datatype,
...
columnN datatype,
PRIMARY KEY (column_name)
);
示例
create table department
(dept_name varchar(20),
building varchar(15),
budget numeric(12,2) check (budget > 0),
primary key (dept_name)
);
- 数据插入
关键字传参
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
示例
insert into department (dept_name, building, budget)values ('Biology', 'Watson', '90000');
位置传参
INSERT INTO table_name VALUES (value1, value2, value3, ...);
示例
insert into department values ('Biology', 'Watson', '90000');
- 删除元组
DELETE from table_name;
示例
delete from department;
- 删除关系
drop table table_name;
示例
drop table department;
DELETE
命令是用来删除表中的某些行,而不是整个表。你可以指定条件来删除特定的记录,比如根据某个字段的值来删除。使用DELETE
命令后,表中的数据会被删除,但是表的结构(列和列的数据类型)仍然保留。而DROP
命令则是用来删除整个表,包括表中的所有数据以及表的结构。一旦你执行了DROP
命令,这个表就完全从数据库中消失了。
- 添加属性
ALTER TABLE table_name ADD A D;
A是待添加属性的名字,D是待添加属性的域;
- 删除属性
ALTER TABLE table_name DROP A;
3.SQL查询的基本结构
基本结构由三个子句构成:selecct、from和where。查询的输入是在from子句中列出的关系,在这些关系上进行where和select子句中指定的运算,然后产生一个关系作为结果。
1.单关系查询
SELECT column1, column2, ...
FROM table_name
WHERE condition;
示例
SELECT NAME FROM instructor;
SELECT
:指定你想要从表中检索的列。FROM
:指定查询的数据来源表。WHERE
:用于过滤查询结果,只返回满足特定条件的行。- DISTINCT:去除重复
SELECT DISTINCT NAME FROM instructor;
- all:显式指明不去重
SELECT ALL NAME FROM instructor;
- +、-、*、/:运算对象为常数或元组的属性,instructor关系不会发生改变;
salary*1.1倍
SELECT ID,NAME,dept_name,salary*1.1 from instructor;
- 逻辑连接词:and、or 和 not
SELECT name from instructor WHERE dept_name='Comp. Sci.' and salary>70000;
2.多关系查询
SELECT name,instructor.dept_name,building FROM instructor,department WHERE instructor.dept_name=department.dept_name;
dept_name属性既出现再instructor关系中,也出现在department中,关系名被用作前缀来说明我们们使用的是哪个属性。
SQL查询的含义:
- 为from子句中列出出的关系产生笛卡尔积
- 在步骤1的结果上应用where字句中指定的谓词
- 对于步骤2结果中的每个元组,输出select子句中指定的属性(或表达式的结果)
3.自然连接
自然连接运算作用于两个关系,并产生一个关系作为结果
SELECT name, dept_name, building
FROM instructor
NATURAL JOIN department;
SELECT name, title FROM instructor NATURAL JOIN teaches NATURAL JOIN course;容易出现错误,不易使用。
提倡先使用自然连接,再加入条件进行判定
SELECT name, title from (instructor NATURAL JOIN teaches) JOIN course USING (course_id);
4.附加的基本运算
1.更名运算
as子句:
- 长的关系名替换为短的
SELECT T.NAME, S.course_id from instructor as T, teaches as S WHERE T.`ID`=S.`ID`;
- 比较同一个关系中元组的情况
SELECT DISTINCT T.NAME FROM instructor as T, instructor as S WHERE T.salary > S.salary and `S`.dept_name = 'Biology';
像T和S那样被用来重命名关系的标识符再SQL标准中被称作相关名称,但通常也被称作表别名,或者相关变量,或者元组变量。
2.字符串运算
- 拼接(Concatenation):使用`||`或`CONCAT()`函数来拼接两个字符串。
SELECT 'Hello' || 'World'; -- 输出: HelloWorld
SELECT CONCAT('Hello', 'World');
- 比较(Comparison):使用`=`、`<>`、`<`、`>`、`<=`、`>=`等比较运算符来比较字符串。
SELECT 'apple' = 'apple'; -- 输出: true
SELECT 'apple' < 'banana'; -- 输出: true
- 替换(Replacement):使用`REPLACE()`函数来替换字符串中的某些部分。
SELECT REPLACE('Hello World', 'World', 'Universe'); -- 输出: Hello Universe
- 截取(Substring):使用`SUBSTRING()`函数来截取字符串的一部分。
SELECT SUBSTRING('Hello World' FROM 1 FOR 5); -- 输出: Hello
- 长度(Length):使用`LENGTH()`或`CHAR_LENGTH()`函数来获取字符串的长度。
SELECT LENGTH('Hello'); -- 输出: 5
SELECT CHAR_LENGTH('Hello'); -- 输出: 5
- 位置(Position):使用`POSITION()`函数来查找字符串在另一个字符串中的位置。
SELECT POSITION('World' IN 'Hello World'); -- 输出: 7
去除空格
- 去掉字符串`'Hello World '`后面的空格,你可以使用`RTRIM()`函数:
SELECT RTRIM('Hello World '); -- 输出: Hello World
- 如果你想要去掉字符串`' Hello World'`前面的空格,你可以使用`LTRIM()`函数:
SELECT LTRIM(' Hello World'); -- 输出: Hello World
- 如果你想要去掉字符串两端的空格,你可以使用`TRIM()`函数:
SELECT TRIM(' Hello World '); -- 输出: Hello World
like操作符
LIKE操作符通常与%(百分号)和 _(下划线)通配符一起使用,以匹配任何数量的字符或单个字符。
- %通配符:表示任意数量的字符(包括零个字符)。
- _`通配符:表示单个字符。
1. 查找所有以特定字符开头的记录:
SELECT * FROM table_name
WHERE column_name LIKE 'A%';
这个查询会返回所有列名为`column_name`,且值以'A'开头的记录。
2. 查找所有包含特定子串的记录:
SELECT * FROM table_name
WHERE column_name LIKE '%ABC%';
这个查询会返回所有列名为`column_name`,且值包含'ABC'的所有记录。
3. 查找所有以特定字符结尾的记录:
SELECT * FROM table_name
WHERE column_name LIKE '%Z';
这个查询会返回所有列名为`column_name`,且值以'Z'结尾的所有记录。
4. 查找所有包含单个字符的记录:
SELECT * FROM table_name
WHERE column_name LIKE '_A%';
这个查询会返回所有列名为`column_name`,且值以第二个字符为'A'的所有记录。
5. 查找所有不包含特定字符的记录:
SELECT * FROM table_name
WHERE column_name NOT LIKE '%ABC%';
这个查询会返回所有列名为`column_name`,且值不包含'ABC'的所有记录。
在like比较运算符中使用escape关键词来定义转义字符。
在SQL中,ESCAPE关键字通常与`LIKE`操作符一起使用,当你想要搜索包含通配符(如`%`或`_`)的字符串时,ESCAPE关键字允许你指定一个转义字符,以便将通配符视为普通字符而不是通配符。
搜索包含`%`字符的字符串,而不是使用它作为通配符:
SELECT * FROM table_name
WHERE column_name LIKE '%\%' ESCAPE '\';
`ESCAPE`关键字后面跟着转义字符`\`,它告诉数据库`%`字符应该被当作普通字符来处理。因此,这个查询会返回所有列名为`column_name`,且值包含`%`字符的所有记录。
如果不指定`ESCAPE`关键字,数据库默认会将`%`和`_`视为通配符。如果想要搜索这些字符本身,需要使用`ESCAPE`关键字来指定转义字符。
similar to 操作符(了解)
`SIMILAR TO`操作符是一个正则表达式匹配操作符,它用于在`WHERE`子句中搜索列中的指定正则表达式模式。`SIMILAR TO`操作符与`LIKE`操作符类似,但它使用正则表达式语法来定义模式,而不是使用通配符。
`SIMILAR TO`操作符使用正则表达式的语法,这意味着你可以使用`.`(点号)来匹配任意单个字符,`*`(星号)来匹配零个或多个字符,`+`(加号)来匹配一个或多个字符,以及其他正则表达式操作符。
`SIMILAR TO`操作符的示例:
1. 查找所有包含特定模式的记录:
SELECT * FROM table_name
WHERE column_name SIMILAR TO 'ABC%';
这个查询会返回所有列名为`column_name`,且值以'ABC'开头的记录。
2. 查找所有包含特定子串的记录:
SELECT * FROM table_name
WHERE column_name SIMILAR TO '%ABC%';
这个查询会返回所有列名为`column_name`,且值包含'ABC'的所有记录。
3. 查找所有以特定字符结尾的记录:
SELECT * FROM table_name
WHERE column_name SIMILAR TO '%Z';
这个查询会返回所有列名为`column_name`,且值以'Z'结尾的所有记录。
4. 查找所有不包含特定字符的记录:
SELECT * FROM table_name
WHERE column_name NOT SIMILAR TO '%ABC%';
这个查询会返回所有列名为`column_name`,且值不包含'ABC'的所有记录。
`SIMILAR TO`操作符在支持正则表达式的数据库系统中使用,如PostgreSQL。在其他数据库系统中,你可能需要使用其他正则表达式函数,如`REGEXP`或`RLIKE`。
正则表达式匹配通常比简单的字符串匹配更复杂,但它提供了更强大的模式匹配能力。如果你不熟悉正则表达式,可能需要花一些时间来学习相关的语法和模式。
3.select子句中的属性说明
星号“ * ” 可以用在select子句中表示“所有的属性”
select instructor.* FROM instructor,teaches WHERE instructor.ID=teaches.ID;
4.排列元组的显示次序
`ORDER BY`子句的基本语法:
SELECT column1, column2, ...
FROM table_name
ORDER BY column_name [ASC|DESC] [NULLS FIRST|NULLS LAST];
示例
SELECT name FROM instructor WHERE dept_name='Physics' ORDER BY name;
- `ASC`:表示升序排序,这是默认的排序方式。
- `DESC`:表示降序排序。
SELECT * FROM instructor ORDER BY salary DESC,name ASC;
- `NULLS FIRST`:表示将NULL值放在结果的前面。
- `NULLS LAST`:表示将NULL值放在结果的后面。
5.where子句谓词
- between...and... 可以代替<=和>=
SELECT name from instructor WHERE salary BETWEEN 90000 and 100000;
SELECT name from instructor WHERE salary>=90000 and salary<=100000;
- 字典顺序比较
SELECT name,course_id from instructor, teaches WHERE (instructor.`ID`,dept_name)=(teaches.`ID`,'Biology');
5.集合运算
在SQL中,集合运算用于对查询结果集进行组合,包括并集(UNION)、交集(INTERSECT)和差集(EXCEPT)。这些运算通常用于合并两个或多个查询的结果。
1.并集(UNION)
- 并集运算用于合并两个或多个查询的结果,并去除重复行。
SELECT column1, column2, ...
FROM table1
UNION
SELECT column1, column2, ...
FROM table2;
示例
(SELECT course_id from section WHERE semester='Fall' and year=2009) UNION (SELECT course_id from section WHERE semester='Spring' and year=2010);
2.交集(INTERSECT)
- 交集运算用于找出两个或多个查询结果的共同行。
SELECT column1, column2, ...
FROM table1
INTERSECT
SELECT column1, column2, ...
FROM table2;
示例
(SELECT course_id from section WHERE semester='Fall' and year=2009) INTERSECT (SELECT course_id from section WHERE semester='Spring' and year=2010);
3.差集(EXCEPT)
- 差集运算用于找出两个查询结果之间的差异,即第一个查询结果中存在而第二个查询结果中不存在的行。
SELECT column1, column2, ...
FROM table1
EXCEPT
SELECT column1, column2, ...
FROM table2;
示例
(SELECT course_id from section WHERE semester='Fall' and year=2009) EXCEPT (SELECT course_id from section WHERE semester='Spring' and year=2010);
注意事项
- 每个集合运算的查询必须具有相同的列数。
- 列的数据类型必须兼容。
- 列的顺序必须相同。
- 集合运算默认会去除重复的行,除非使用`ALL`关键字。
6.空值
在SQL中,空值(NULL)表示一个缺失的、未知的或不适用的值。空值与零(0)或空格(' ')不同,它表示没有值。在处理数据库数据时,空值是一个常见的概念,需要特别注意。
1.空值的特点
- 空值表示缺失的信息。
- 空值不是零或任何其他值。
- 空值不能与任何值进行比较,包括它自己。
2.空值的处理
- 检查空值:使用`IS NULL`或`IS NOT NULL`来检查列是否为空。
SELECT * FROM table_name
WHERE column_name IS NULL;
- 处理空值:使用`COALESCE()`函数来将空值替换为其他值。
SELECT COALESCE(column_name, 'Default Value') FROM table_name;
- 使用`IFNULL()`或`NVL()`函数来替换空值。
SELECT IFNULL(column_name, 'Default Value') FROM table_name;
- 删除空值:使用`WHERE`子句来排除空值。
SELECT * FROM table_name
WHERE column_name IS NOT NULL;
- 使用`DELETE`语句来删除包含空值的行。
DELETE FROM table_name
WHERE column_name IS NULL;
- 计算空值:使用`COUNT()`函数时,空值不计入总数。
SELECT COUNT(*) FROM table_name;
- 使用`SUM()`函数时,空值不计入总和。
SELECT SUM(column_name) FROM table_name;
3.空值的影响
空值可能会影响查询结果和聚合函数的计算。例如,在计算平均值时,空值不会包含在内。在处理包含空值的数据时,需要特别注意这些影响。
在处理数据库数据时,理解空值的概念和它们的行为对于确保数据的准确性和完整性至关重要。
7.聚集函数
1.基本聚集函数
在SQL中,聚集函数(Aggregate Functions)用于对一组值执行计算并返回单个值。这些函数通常与`SELECT`语句的`GROUP BY`子句一起使用,以对数据进行分组,并对每个组应用聚集函数。以下是一些常用的基本聚集函数:
1.COUNT():
- 计算表中的行数。
- 可以计算特定列的行数,或者计算所有行的行数。
SELECT count(DISTINCT ID) from teaches WHERE semester='Spring' and year=2010;
2. SUM():
- 计算指定列的总和。
- 通常用于数值类型的列。
3. AVG():
- 计算指定列的平均值。
- 同样适用于数值类型的列。
SELECT avg(salary) as avg_salary from instructor WHERE dept_name='Comp. Sci.';
4. MAX():
- 找出指定列的最大值。
- 可以用于任何数据类型的列。
5. MIN():
- 找出指定列的最小值。
- 也可以用于任何数据类型的列。
2.分组聚集
分组聚集(Grouping and Aggregation)是SQL中一个非常强大的功能,它允许你根据一个或多个列对数据进行分组,并对每个分组应用聚集函数来计算统计数据。
基本步骤
1. 使用`GROUP BY`子句:
- 指定你想要根据哪些列对数据进行分组。
- 每个分组内的所有行都有相同的值。
2. 应用聚集函数:
- 使用`COUNT()`, `SUM()`, `AVG()`, `MAX()`, `MIN()`等函数来计算每个分组的统计数据。
示例
找出每个系的平均工资
SELECT dept_name,AVG(salary) as avg_salary from instructor GROUP BY dept_name;
注意事项
- 在`GROUP BY`子句中指定的列必须是出现在`SELECT`列表中的列,除非这些列是聚集函数的参数。
- 聚集函数会忽略`GROUP BY`子句中未指定的列。
- 如果在`SELECT`列表中指定了除聚集函数参数之外的列,这些列必须出现在`GROUP BY`子句中。
- 聚集函数通常与`HAVING`子句一起使用,以过滤分组后的结果。
分组聚集是数据分析中常用的技术,它可以帮助你快速了解数据的分布和趋势。
3.having子句
·在SQL中,`HAVING`子句用于过滤`GROUP BY`子句返回的结果集。它允许你根据聚集函数的结果(如`COUNT()`, `SUM()`, `AVG()`, `MAX()`, `MIN()`等)来筛选分组后的数据。
` HAVING`子句通常与`GROUP BY`子句一起使用,因为它依赖于分组后的数据。`WHERE`子句在分组之前过滤行,而`HAVING`子句在分组之后过滤分组。
基本语法
SELECT column1, column2, ..., aggregate_function(column3)
FROM table_name
GROUP BY column1, column2, ...
HAVING aggregate_condition;
示例
SELECT dept_name, avg(salary) as avg_salary from instructor GROUP BY dept_name HAVING avg(salary) > 42000;
- `aggregate_function(column3)`:指定一个或多个聚集函数,如`COUNT()`, `SUM()`, `AVG()`, `MAX()`, `MIN()`等。
- `aggregate_condition`:指定基于聚集函数的条件,用于过滤分组后的结果。
注意事项
- `HAVING`子句中的条件可以引用聚集函数,而`WHERE`子句中的条件不能。
- `HAVING`子句在分组之后应用,因此它只能引用分组后的列。
- `HAVING`子句通常用于对分组后的数据进行筛选,而`WHERE`子句用于筛选原始数据。
使用`HAVING`子句可以帮助你根据统计数据(如平均值、总和等)来筛选分组后的结果,这在数据分析中非常有用。
4.对空值和布尔值的聚集
在SQL中,聚集函数通常不适用于空值(NULL),因为空值不参与数值计算。对于布尔值(TRUE 或 FALSE),聚集函数通常也不直接处理,因为它们通常用于筛选或条件判断,而不是作为数值进行聚合。
- 处理空值
空值在SQL中通常被视为未知值或不适用的值。当你使用聚集函数时,空值不会包含在计算中。例如,如果你有一个包含空值的列,并且你使用`SUM()`函数来计算该列的总和,那么结果将是所有非空值的总和。
SELECT SUM(column_name) FROM table_name;
如果你想要包括空值,你可以使用`COALESCE()`函数来将空值替换为0或其他值。
SELECT SUM(COALESCE(column_name, 0)) FROM table_name;
- 处理布尔值
布尔值在SQL中通常用于条件判断,而不是作为数值进行聚合。如果你想要基于布尔值进行筛选,你可以使用`WHERE`子句。
SELECT * FROM table_name
WHERE column_name = TRUE;
如果你想要计算布尔值出现的次数,你可以将它们转换为整数(通常为1表示TRUE,0表示FALSE),然后使用`COUNT()`函数。
SELECT COUNT(CASE WHEN column_name = TRUE THEN 1 END) FROM table_name;
或者,你可以使用`SUM()`函数,因为`TRUE`会被解释为1,而`FALSE`会被解释为0。
SELECT SUM(CASE WHEN column_name = TRUE THEN 1 ELSE 0 END) FROM table_name;
注意事项
- 聚集函数通常用于数值类型的列,而不是布尔类型。
- 布尔值在SQL中通常用于条件判断,而不是作为数值进行聚合。
- 如果你需要基于布尔值进行聚合,你可能需要将它们转换为数值形式。
在处理数据库数据时,理解空值和布尔值的行为对于确保数据的准确性和完整性至关重要。
8.嵌套子查询
子查询是嵌套在另一个查询中的select-from-where表达式。子查询嵌套在where子句中,通常用于对集合的成员资格、集合的比较以及集合的基数进行检查。
1.集合成员资格
在SQL中,集合成员资格(Set Membership)是指检查一个值是否属于一个集合(通常是一个列表)。这可以通过使用`IN`关键字来实现。`IN`关键字用于检查一个值是否存在于指定的集合中,通常与`WHERE`子句一起使用。
基本语法
SELECT column1, column2, ...
FROM table_name
WHERE column_name IN (value1, value2, ...);
示例
SELECT DISTINCT course_id
from section
WHERE semester='Fall' and year=2009 AND
course_id in (SELECT course_id from section WHERE semester='Spring' and year=2010);
- `column_name`:你想要检查其成员资格的列。
- `value1, value2, ...`:一个或多个值,用于检查`column_name`中的值是否在这些值中。
注意事项
- `IN`关键字通常用于检查一个值是否存在于一个集合中,而不是用于比较两个集合。
- 当使用`IN`关键字时,集合中的值应该是明确的,并且集合中的值应该是唯一的。
- `IN`关键字可以与子查询一起使用,以检查一个值是否存在于子查询返回的结果集中。
集合成员资格是SQL中一个非常常用的操作,它使得查询更加灵活和强大。
2.集合的比较
在SQL中,`SOME`关键字通常与`ALL`关键字一起使用,用于比较一个集合中的元素与另一个集合中的元素。`SOME`关键字表示至少存在一个匹配,而`ALL`关键字表示所有元素都必须匹配。
基本语法
SELECT column1, column2, ...
FROM table_name
WHERE column_name SOME (SELECT column_name FROM another_table);
这个查询会返回`table_name`中至少有一个`column_name`值与`another_table`中`column_name`值匹配的行。
注意事项
- `SOME`关键字通常与`EXISTS`关键字一起使用,而不是与`IN`关键字一起使用。
- `SOME`关键字在SQL标准中不是所有数据库系统都支持,例如在MySQL中就不支持`SOME`关键字。
- 在不支持`SOME`关键字的数据库系统中,你可以使用`EXISTS`关键字来实现类似的功能。
`SOME`关键字在SQL中不是非常常见,因为它的使用场景相对有限。在大多数情况下,你可以使用`EXISTS`关键字来实现类似的功能。
3.空关系测试
在SQL中,空关系测试(Empty Relation Testing)通常指的是检查一个查询结果是否为空。这可以通过使用`EXISTS`关键字或`NOT EXISTS`关键字来完成。这些关键字用于测试子查询是否返回任何行。
`EXISTS`关键字
`EXISTS`关键字用于检查子查询是否至少返回一个行。如果子查询至少返回一个行,则`EXISTS`返回`TRUE`;如果没有行返回,则返回`FALSE`。
SELECT column1, column2, ...
FROM table_name
WHERE EXISTS (SELECT column_name FROM another_table WHERE conditions);
`NOT EXISTS`关键字
`NOT EXISTS`关键字用于检查子查询是否不返回任何行。如果子查询不返回任何行,则`NOT EXISTS`返回`TRUE`;如果至少返回一个行,则返回`FALSE`。
SELECT column1, column2, ...
FROM table_name
WHERE NOT EXISTS (SELECT column_name FROM another_table WHERE conditions);
注意事项
- `EXISTS`和`NOT EXISTS`关键字通常与`WHERE`子句一起使用。
- 这些关键字对于检查子查询是否返回任何行非常有用,尤其是在需要确保查询结果非空的情况下。
- 当使用`EXISTS`或`NOT EXISTS`时,子查询通常不需要返回任何列,因为`EXISTS`关键字只关心子查询是否返回至少一行。
空关系测试是数据库查询中一个重要的概念,它帮助确保查询结果不为空,这在业务逻辑处理中非常重要。
4.重复元组存在性测试
在SQL中,重复元组存在性测试(Duplicate Tuple Existence Testing)通常是指检查一个表中是否存在重复的行。这可以通过使用`DISTINCT`关键字或`GROUP BY`子句来实现。
`DISTINCT`关键字
`DISTINCT`关键字用于返回唯一不同的值。当你在`SELECT`语句中使用`DISTINCT`时,它会返回所有唯一的行。如果你想要检查一个表中是否有重复的行,你可以使用`DISTINCT`关键字,然后比较返回的行数与原始表中的行数。
SELECT COUNT(DISTINCT column_name)
FROM table_name;
如果`COUNT(DISTINCT column_name)`的结果与`table_name`中的总行数相同,则没有重复的行;如果不同,则存在重复的行。
`GROUP BY`子句
`GROUP BY`子句用于将查询结果分组,通常与聚集函数(如`COUNT()`、`SUM()`、`AVG()`等)一起使用。如果你想要检查一个表中是否有重复的行,你可以使用`GROUP BY`子句来分组相同的行,然后检查每个分组中的行数。
SELECT column_name, COUNT(*)
FROM table_name
GROUP BY column_name
HAVING COUNT(*) > 1;
这个查询会返回每个唯一列值的计数,如果某个计数大于1,则意味着存在重复的行。
注意事项
- `DISTINCT`关键字和`GROUP BY`子句都可以用来检查重复行,但它们的使用场景略有不同。
- 使用`DISTINCT`时,你需要明确指定要检查的列。
- 使用`GROUP BY`时,你可以通过聚集函数来检查每个唯一值的计数。
在实际应用中,通常建议使用`GROUP BY`子句和`HAVING`子句来检查重复行,因为它可以提供更多的灵活性和信息。
5.from子句中的子查询
在SQL中,`FROM`子句中的子查询(也称为子选择或子查询)是一种将查询结果用作临时表的方法。这种子查询通常用于简化复杂查询,或者当需要从多个表中选择数据时。
基本语法
SELECT column1, column2, ...
FROM (SELECT column1, column2, ...
FROM table_name
WHERE conditions) AS subquery_alias;
示例
SELECT dept_name,avg_salary FROM
(SELECT dept_name,avg(salary) from instructor GROUP BY dept_name)
as dept_avg(dept_name,avg_salary)
WHERE avg_salary > 42000;
- `(SELECT column1, column2, ... FROM table_name WHERE conditions)`:这是子查询,它执行一个查询并返回结果集。
- `subquery_alias`:这是子查询的别名,用于在主查询中引用子查询。
注意事项
- 子查询可以嵌套多层,但通常建议不要嵌套太多层,以免影响查询的性能和可读性。
- 子查询的结果应该是一个表,可以是一个单列的表,也可以是多列的表。
- 子查询通常用于复杂的查询,如连接多个表、执行条件过滤或计算统计数据。
子查询是SQL中一个非常强大的特性,它允许你构建复杂的查询逻辑,以实现更精确的数据检索和分析。
少数SQL支持 lateral关键字,允许from子句中的子查询用关键字lateral作为前缀,以便访问from子句中在它前面的表或子查询的属性。
6.with子句
在SQL中,`WITH`子句(也称为公共表表达式或CTE,Common Table Expressions)允许你定义一个临时的、可重用的查询结果集,这个结果集可以在后续的查询中被引用。`WITH`子句可以简化复杂的查询,提高可读性,并且可以避免重复代码。
基本语法
WITH subquery_name AS (
SELECT column1, column2, ...
FROM table_name
WHERE conditions
)
SELECT column1, column2, ...
FROM subquery_name;
示例
with max_budget (value) AS
(SELECT MAX(budget) from department)
SELECT budget from department,max_budget
WHERE department.budget = max_budget.value;
- `subquery_name`:这是公共表表达式的别名,用于在主查询中引用这个临时表。
- `(SELECT column1, column2, ... FROM table_name WHERE conditions)`:这是子查询,它执行一个查询并返回结果集。
注意事项
- `WITH`子句可以在任何`SELECT`、`INSERT`、`UPDATE`或`DELETE`语句中使用。
- 公共表表达式可以嵌套,但通常建议不要嵌套太多层,以免影响查询的性能和可读性。
- 公共表表达式可以简化复杂的查询逻辑,使得代码更加清晰和易于维护。
`WITH`子句是SQL中一个非常有用的特性,它允许你创建临时的、可重用的查询结果集,从而提高查询的效率和可读性。
7.标量子查询
标量子查询(Scalar Subquery)是一种特殊的子查询,它返回一个单一的值。这种子查询通常用在`SELECT`列表中,或者作为`WHERE`、`HAVING`条件中的比较值。标量子查询的结果必须是单个值,不能是多行或多列。
基本语法
SELECT column1, (SELECT column2 FROM table2 WHERE conditions) AS scalar_value
FROM table1
WHERE column1 = (SELECT column2 FROM table2 WHERE conditions);
示例
SELECT dept_name,
(SELECT COUNT(*) FROM instructor WHERE department.dept_name=instructor.dept_name)
as num_instructors
from department;
- `(SELECT column2 FROM table2 WHERE conditions)`:这是标量子查询,它返回一个单一的值。
- -`scalar_value`:这是标量子查询的别名,用于在主查询中引用这个值。
注意事项
- 标量子查询的结果必须是单个值,不能是多行或多列。
- 标量子查询通常用在需要单个值作为条件的地方,W`EREre`、`VINGng`条件,或者作S`LECTct`列表中的计算值。
- 标量子查询可以嵌套,但嵌套层数过多可能会影响查询的性能和可读性。
标量子查询在SQL中一个非常有用的特性,它允许你在查询中执行复杂的计算,以实现更精确的数据检索和分析。
9.数据库的修改
在数据库中,修改数据通常涉及以下几种操作:
1. 插入数据(INSERT)
- 向表中添加新的记录。
- 语法:
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);
2. 更新数据(UPDATE)
- 修改表中现有记录的数据。
- 语法:
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;
3. 删除数据(DELETE)
- 从表中删除记录。
- 语法:
DELETE FROM table_name WHERE condition;
注意事项
- 在执行`UPDATE`或`DELETE`操作时,如果没有指定`WHERE`子句,那么表中的所有记录都会被更新或删除。
- 在执行`UPDATE`或`DELETE`操作时,最好总是使用`WHERE`子句来指定要修改或删除的具体记录,以避免意外地修改或删除大量数据。
- 在执行`INSERT`操作时,如果表有主键或唯一约束,并且你尝试插入一个已经存在的值,那么插入操作可能会失败。
- 在执行任何修改数据的操作之前,最好备份数据库,以防止数据丢失或损坏。
数据库修改操作是数据库管理的核心部分,需要谨慎操作以确保数据的准确性和安全性。
4.case结构
在SQL中,`CASE`结构是一种条件表达式,它允许你根据不同的条件返回不同的值。`CASE`结构有两种形式:简单`CASE`和搜索`CASE`。
简单`CASE`结构
简单`CASE`结构用于基于一个条件表达式的值返回不同的值。
CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE resultN
END
- `expression`:条件表达式,其值将被比较。
- `value1, value2, ...`:与条件表达式比较的值。
- `result1, result2, ...`:当条件表达式的值匹配时返回的结果。
- `ELSE`:当没有其他条件匹配时返回的结果。
搜索`CASE`结构
搜索`CASE`结构用于基于一系列条件表达式的值返回不同的值。
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE resultN
END
- `condition1, condition2, ...`:条件表达式,其值将被比较。
- `result1, result2, ...`:当条件表达式的值匹配时返回的结果。
- `ELSE`:当没有其他条件匹配时返回的结果。
注意事项
- `CASE`结构可以用在`SELECT`列表、`WHERE`子句、`ORDER BY`子句等位置。
- `CASE`结构可以嵌套,但通常建议不要嵌套太多层,以免影响查询的性能和可读性。
- `CASE`结构是SQL中一个非常有用的特性,它允许你根据不同的条件返回不同的值,从而实现更复杂的逻辑判断。
示例
UPDATE instructor set salary = CASE
WHEN salary <= 100000 THEN salary*1.05
ELSE salary * 1.03
END
`CASE`结构是SQL中一个非常灵活的工具,它可以帮助你根据不同的条件返回不同的值,从而实现复杂的业务逻辑。