第五章 SQL基础
P63. SQL概述
>.SQL的组成
>.数据定义语言(data definition language,DDL):用于在数据库系统中,对数据库,表,视图,索引等数据库对象进行创建和管理
>.数据控制语言(data control language,DCL):实现对数据库中数据的完整性,完全性等的控制
>.数据操纵语言(data manipulation language,DML):用于插入,修改,删除和查询数据库中的数据.
>.SQL语句结构
>.每条SQL语句均是由一个谓词(Verb)开始,该谓词描述了这条语句要产生的动作,比如:select,update,drop,insert into等,注意SQL中的关键字不区分大小写.
>.谓词后面紧接着一个或者多个子句(clause),子句中给出被谓词作用的数据或提供谓词动作的详细信息
>.每一个子句都由一个关键字开始.这个关键字也可以是谓词.
假设我们有一个简单的学生信息表(Student),包括学生ID(StudentID)、姓名(Name)、年龄(Age)和班级(Class)。现在我们要写一条SQL语句来查询所有年龄大于18岁的学生信息。
SELECT Name, Age, Class FROM Student WHERE Age > 18;
上面的例子以select语句为例,它是一个谓词,描述了我们要执行的动作是查询。在这个例子中,select后面的子句可以包括:
>.列表达式列表(Column Expressions Clause):用来指定我们要查询的列,例如:Name, Age, Class。
>.表列表(From Clause):用来指定我们要查询的表,例如:Student。
>.行过滤(Where Clause):用来指定我们要过滤的条件,例如:Age > 18。
在这个例子中,谓词是select,而子句包括列表达式列表、表列表和行过滤,它们提供了查询动作的详细信息和被作用的数据。
>.SQL语句的分类
>.变量声明语句:声明变量的命令。Declare
>.数据定义语句: 建立数据库、数据库对象和定义列,大部分是以 CREATE 开头的命令,如CREATE TABLE、CREATE VIEW 和 DROP TABLE 等。
>.数据操纵语句: 操纵数据库中数据的命令,如 SELECT、INSERT、UPDATE、DELETE和CURSOR 等.
>.数据控制语句: 控制数据库组件的存取许可、存取权限等命令,如GRANT、REVOKE等.
GRANT 音标:[ɡrænt] 意思:授予、准予、同意、给予 GRANT:GRANT语句用于向用户或用户组授予特定的数据库对象(如表、视图、存储过程等)的访问权限和操作权限。通过GRANT语句,数据库管理员可以授权用户执行特定的数据库操作。 示例:GRANT SELECT, UPDATE ON table_name TO user_name; REVOKE 音标:[rɪˈvoʊk] 意思:撤销、取消、废除、吊销 REVOKE:REVOKE语句用于撤销已经授予用户或用户组的数据库对象的访问权限和操作权限。通过REVOKE语句,数据库管理员可以收回之前授予的权限。 示例:REVOKE SELECT ON table_name FROM user_name; DENY 音标:[dɪˈnaɪ] 意思:否认、拒绝、拒绝承认 DENY:在一些数据库管理系统中,DENY语句用于显式地拒绝用户访问或操作特定的数据库对象,即使该访问权限已经通过GRANT语句授予。这是一种更严格的权限控制方式。 示例:DENY INSERT ON table_name TO user_name;
>.流程控制语句:设计应用程序流程的语句,如IF WHILE和CASE 等.
>.内嵌函数:说明变量的命令.
>.其他命令:嵌于命令中使用的标准函数.
P64. 常量
>.数字常量
>.位之间不能写逗号,比如123456,不能写作123,456
>.浮点常量通常用符号e指定,如1.5e3,2.5e-7等.e几就是小数点偏移几位,方向由e后面的值指定,比如2.5e-7,就是小数点向左移7位;1.5e3 就是向右移3位
>字符串常量
>.SQL SERVER中字符串是用单引号包起来的,如果字符串中包含了单引号,记住"一个变两儿"就够了
>.日期和时间常量
>.标准日期格式YYYY-MM-DD’,例如 ‘2022-12-11’
>.标准日期时间格式 ‘YYYY-MM-DD HH:MI:SS’, 例如 ‘2023-12-02 12:34:56’
>.作业:掌握CONVERT [kənˈvɜrt] 的用法
>.符号常量
>.CURRENT_DATE : 当前日期
>.CURRENT_TIME: 当前时间
>.CURRENT_TIMESTAMP: 当前日期和时间,包括毫秒数。它与使用 GETDATE()
函数的效果相同。
p65.变量
>.局部变量
>.通过 DECLARE [dɪˈklɛər] 语句声明局部变量。示例:DECLARE @变量名 数据类型;。例如:DECLARE @Name NVARCHAR(50);
>.变量名必须以@开头,后面跟着一个合法的标识符(注意,两个@@是全局变量)
>.除了text,ntext和Image类型以外,可以使用其他的数据类型,包括自定义数据类型
>.局部变量的作用范围仅限于声明它的存储过程、函数、批处理或语句块。但在适当的情况下,也可以将其作为参数传递给存储过程或函数
>.可以使用setect 或者 set 两种方式赋值
>.此时setect 的作用是给变量赋值,而不是从表中查询数据,所以不一定要附带FROM和WHERE子句
DECLARE @CurrentDate DATE; SET @CurrentDate = SELECT GETDATE(); -- 不需要 FROM 或 WHERE 子句
>.使用set 语句赋值:
DECLARE @Name NVARCHAR(50); SET @Name = 'John';
>.你还可以同时声明多个变量和同时给多个变量赋值,用逗号隔开
--同时声明多个变量或者给多个变量赋值时,用逗号隔开 DECLARE @Name VARCHAR(50) = 'John', @Age INT = 30, @Salary DECIMAL(10, 2) = 5000.00; SELECT @Name AS Name, @Age AS Age, @Salary AS Salary; --是的,你没看错,变量还可以取别名... ---变量间的运算 DECLARE @Num1 INT, @Num2 INT, @Sum INT; SET @Num1 = 5; SET @Num2 = 10; SET @Sum = @Num1 + @Num2; SELECT @Num1 AS Num1, @Num2 AS Num2, @Sum AS Sum;
下面是其他一些赋值示例
DECLARE @Age INT; SELECT @Age = Age FROM Users WHERE Name = 'John'; --使用 SELECT 语句赋值,但是带了子句 DECLARE @TotalCount INT; SELECT @TotalCount = COUNT(*) FROM Customers; --使用 SELECT 语句赋值 DECLARE @StartDate DATE = '2023-01-01'; --声明时,直接赋值 DECLARE @IsAdmin BIT = 1; --请特别注意以下这种类型,它包含了隐式转换 DECLARE @A VARCHAR(8) SELECT @A =CONVERT(TIME,GETDATE(),108) --CONVERT返回的类型是TIME,但是因为@A定义的是字符串,所以TIME被转换成了字符串VARCHAR(8) PRINT @A --'12:01:23'
>.全局变量
>.SQL SERVER系统内部都定义好了,不需要用户参与定义.会用就行.看看就可以了
P68.注释符,运算符与通配符
>.注释符
>.两个减号:--
>./*注释语句*/
>.注释快捷键: Shift+Ctrl+C
>.反注释快捷键: Shift+Ctrl+R
>.运算符
>.算术运算符.+ ,- ,* ,/ ,%
>.赋值运算符:=
>.比较运算符: >,<,>=,<=,<>,比较运算的结果是个布尔值,与其他数据库的TRUE与FALSE不同,SQL Server用BIT数据类型来表示布尔值,即BIT(1),0值表示False,1值表示TRUE.
>.逻辑运算符
>. ALL:用于将一个条件与集合中的所有值进行比较。例如,当使用子查询时,可以通过 ALL 运算符确保子查询返回的所有值都满足条件。
>.AND:逻辑运算符,表示逻辑与关系。当条件中的所有表达式都为 true 时,AND 运算符返回 true。
>.ANY:用于将一个条件与集合中的任意值进行比较。类似于 IN 运算符,但 ANY 不限定要匹配整个集合。
示例:假设我们有两个表:Students 表和 Scores 表。Students 表包含学生ID和姓名,Scores 表包含学生成绩信息。我们想找出在 Scores 表中有任何一个分数大于等于 90 分的学生。可以使用 ANY 运算符来实现:
SELECT Name FROM Students WHERE StudentID = ANY (SELECT StudentID FROM Scores WHERE Score >= 90);
>.BETWEEN:用于检查一个值是否在指定范围内。通常用于检查一个值是否在两个边界之间(包括边界值)。
>.EXISTS:用于检查子查询是否返回任何数据行。如果子查询返回结果集,则 EXISTS 返回 true。
示例:假设我们有一个 Orders 表,我们想找出已经生成了订单的客户。可以使用 EXISTS 运算符来实现:
SELECT CustomerName FROM Customers WHERE EXISTS (SELECT 1 FROM Orders WHERE Customers.CustomerID = Orders.CustomerID);
>.IN:用于检查一个值是否存在于给定的列表或查询结果集中。可以简化包含多个值的条件。
>.LIKE:用于在 WHERE 子句中搜索与指定模式匹配的文本值。通常与通配符结合使用,以实现模糊搜索。
>.NOT:逻辑运算符,用于否定一个条件。如果条件为 true,则 NOT 返回 false;如果条件为 false,则 NOT 返回 true。
>.OR:逻辑运算符,表示逻辑或关系。当条件中的任一表达式为 true 时,OR 运算符返回 true。
>.SOME(或任意):类似于 ANY 运算符,用于将一个条件与集合中的任意值进行比较。简化代码逻辑并确保数据准确性。
>.位运算符
>.位运算符在实际场景中并不是经常用到,它们更多地被用在特定的计算机科学和工程领域,比如底层系统编程、嵌入式系统开发、密码学等领域。
&(AND):按位与运算符,对两个整数的每一位执行与操作。只有当两个对应位都为 1 时,结果为 1;否则为 0。 示例: 假设我们有一个整数字段 Flags,其值为 17(二进制表示为 10001)。我们想要检查第二位是否为 1,可以使用按位与运算符: SELECT Flags & 2 AS Result 这将返回 2,因为 17 的二进制表示为 10001,与 2 的二进制表示 00010 进行按位与操作后得到 00000,即第二位为 0。 |(OR):按位或运算符,比较两个整数的每一位,只要有一个为 1,结果为 1;否则为 0。 ^(XOR):按位异或运算符,按位比较两个整数,相同位为 0,不同位为 1。 示例: 假设我们有一个整数字段 Flags,其值为 10(二进制表示为 1010)。我们想要将第三位取反,可以使用按位异或运算符: SELECT Flags ^ 4 AS Result 这将返回 14,因为 10 的二进制表示为 1010,与 4 的二进制表示 0100 进行按位异或操作后得到 1110,即第三位取反。 ~(NOT):按位非运算符,用于对整数的每一位取反,0 变为 1,1 变为 0。 示例: 假设我们有一个整数字段 Flags,其值为 5(二进制表示为 0101)。我们想要对 Flags 进行取反操作,可以使用按位非运算符: SELECT ~Flags AS Result 这将返回 -6,因为 5 的二进制表示为 0101,取反后得到 1010,即 -6。
>.连接运算符
>.+ 号.
>.运算符优先级
运算符的优先级由高到低,顺序如下:
>.+(正),-(负),~(位反).
>.*(乘),/(除),%(取余)
>.+(加),+(连接运算符),-(减)
>.比较运算符.
>.位运算符
>.NOT(取反)
>.AND
>.除了AND以外的逻辑运算符
>.=(赋值)
如果表达式过于复杂,建议使用括号隔离每一部分,提高代码的可阅读性.
>.通配符.
>.% :匹配任意多个任意字符,包括0个
>._ (下划线):匹配一个任意字符
>.[] : 匹配集合内的任意个字符.比如[a~z0~9A~Z],[0~9]
SELECT CASE WHEN '5' LIKE '[0-9a-zA-Z]' THEN '存在' ELSE '不存在' END AS result;
>.[^] 与 [] 相反.
>.流程控制.
>.BEGIN...END : 用于将多条SQL语句组合为一个逻辑块.
BEGIN DECLARE @total_salary DECIMAL(10, 2); SET @total_salary = (SELECT SUM(salary) FROM employees); IF @total_salary > 100000 THEN SELECT 'Total salary is greater than 100000' AS message; ELSE SELECT 'Total salary is not greater than 100000' AS message; END IF; END;
>.IF
DECLARE @score INT = 85; IF @score >= 60 BEGIN PRINT 'Pass'; END ELSE BEGIN PRINT 'Fail'; END
>.IF...ELSE...
DECLARE @num INT = 10 IF @num > 0 BEGIN PRINT 'Number is positive.' END ELSE BEGIN PRINT 'Number is non-positive.' END
>.CASE.若没有指定else子句,且之前的条件统统不满足,则返回NULL值,以下是两种常用的CASE写法
SELECT ProductName, Quantity, CASE WHEN Quantity <= 10 THEN 'Low' WHEN Quantity <= 50 THEN 'Medium' ELSE 'High' END AS QuantityCategory FROM Products;
SELECT ProductName, Quantity, QuantityCategory = CASE WHEN Quantity <= 10 THEN 'Low' WHEN Quantity <= 50 THEN 'Medium' ELSE 'High' END FROM Products;
>.WHILE循环.
DECLARE @counter INT SET @counter = 1 WHILE @counter <= 10 BEGIN PRINT 'The counter is: ' + CAST(@counter AS VARCHAR) --CAST,数据类型转换 SET @counter = @counter + 1 END
>.WHILE...CONTINUE...BREAK: CONTINUE跳过当前的循环,BREAK 跳出循环.
DECLARE @counter INT SET @counter = 1 WHILE @counter <= 10 BEGIN IF @counter = 5 BEGIN SET @counter = @counter + 1 CONTINUE; -- 跳过本次循环,继续下一次循环 END PRINT 'The counter is: ' + CAST(@counter AS VARCHAR) IF @counter = 8 BEGIN BREAK; -- 跳出循环 END SET @counter = @counter + 1 END
>.RETURN语句通常用于从存储过程中提前返回结果,并结束存储过程的执行。一般来说,RETURN 语句用于返回一个整数值,表示存储过程的执行状态或特定信息。
CREATE PROCEDURE ExampleProcedure AS BEGIN DECLARE @result INT -- 在这里可以进行一些逻辑操作 IF (条件满足) BEGIN SET @result = 1 RETURN @result END ELSE BEGIN SET @result = 0 RETURN @result END END
注意,如果RETURN没有指定一个返回值,则SQL SERVER会根据执行的结果返回一个内定值.这些内定值如表所示:
>.GOTO命令用来改变程序执行的流程,使程序跳到标识符指定的程序行再继续往下执行.
CREATE PROCEDURE ExampleProcedure AS BEGIN DECLARE @counter INT SET @counter = 1 -- 正常执行的逻辑 PRINT 'Start of the loop' LoopStart: --我是标识符 IF @counter <= 5 BEGIN PRINT 'Counter: ' + CAST(@counter AS VARCHAR) SET @counter = @counter + 1 GOTO LoopStart END PRINT 'End of the loop' END
>.WAITFOR:指定触发器/存储过程或者事务执行的时间,时间间隔;还可以暂时停止程序的执行,直到所设定的等待时间已过才继续往下执行.
--1.等待一段时间后执行操作: WAITFOR DELAY '00:00:10'; -- 等待10秒 PRINT '10 seconds have passed.'; --2.等待一个时间点执行操作: DECLARE @time DATETIME = '2024-03-24 13:00:00'; WAITFOR TIME @time; PRINT 'It is now 1 PM.'; --3.等待一个条件变为真后执行操作: DECLARE @condition BIT = 0; WAITFOR (WHILE @condition = 0); PRINT 'The condition is now true.';
P80. 常用指令
>.DBCC:数据库一致性检查.用于验证数据库完整性,查找错误和分析系统使用情况等.
DBCC命令后面必须要加上子命令,系统才能知道你要做什么,常见的有:CHECKALLOC,SHOWCONTIG
--检查数据库完整性: DBCC CHECKDB ('YourDatabaseName'); --这个命令将对指定的数据库进行检查,包括表、索引等对象的完整性,以确保数据库结构没有损坏。如果发现问题,会生成相应的报告。 --检查指定表的完整性: DBCC CHECKTABLE ('YourTableName'); --这个命令将仅对指定的表进行完整性检查,用于验证该表的数据结构和完整性是否正常。 --清空数据库缓存: DBCC DROPCLEANBUFFERS; --这个命令用于清空数据库缓存,也就是清除数据库在内存中的缓存数据,可以用于测试数据库性能。 --查看数据库统计信息: DBCC SHOW_STATISTICS ('YourTableName', 'YourIndexName'); --这个命令用于显示指定表的统计信息,包括索引的选择性、直方图等相关信息,有助于优化查询性能。 --查看数据库分配的空间情况: DBCC SQLPERF (LOGSPACE); --这个命令用于显示数据库日志文件的空间使用情况,包括日志文件的大小、空间占用情况等。
>.CHECKPOINT命令用于检查当前工作的数据库中,被更改过的数据页或者日志页,并将这些数据强制的,从数据缓冲器写入硬盘.
语法: CHECKPOINT [checkpoint_duration]
参数checkpoint_duration表示以秒为单位,指定检查点完成所需要的时间.
USE DBName CHECKPOINT;
>.DECLARE 声明变量,略
>.PRINT 显示一个字符串,略.
>.PAISERROR 用于在SQL SERVER系统中返回错误信息时同时返回用户指定(或者说是拟定)的信息.
>.READTEXT 用于读取text,ntext或者image列中的值,从指定的位置开始读取指定的字符数.语法如下:
READTEXT {table.column text_ptr offset size} [HOLDLOCK]
--READTEXT 命令通常与 TEXTPTR 函数一起使用,该函数用于获取文本或图像数据的指针,以便可以使用 READTEXT 读取数据。 --以下是一个示例,演示了如何使用 READTEXT 命令读取表中的文本数据: DECLARE @ptr varbinary(16); SELECT @ptr = TEXTPTR(text_column) FROM text_table WHERE id = 1; READTEXT text_table.text_column @ptr 1 100; --这个示例中,首先使用 TEXTPTR 函数获取了文本数据的指针,然后使用 READTEXT 命令从指定的偏移量开始读取 100 个字节的文本数据。
READTEXT 命令通常在以下场景下使用:
1.读取大型文本或图像数据:当需要处理大型文本或图像数据时,例如存储在数据库表中的文档、图像或音频文件等,READTEXT 可以用于逐块地读取这些数据。
2.处理LOB(大型对象)数据:LOB 数据类型(如 TEXT、NTEXT、IMAGE 等)通常存储着大量数据,而 READTEXT 可以用来分块读取这些数据,以便在应用程序中进行处理。
3.文本或图像数据的逐段读取:有时候需要逐段读取文本或图像数据,例如显示长文本、部分加载图像等,READTEXT 可以帮助实现这一需求。
4.数据导出或转换:在数据迁移、备份和恢复等过程中,可能需要将数据库中的大型文本或图像数据导出到其他系统中或转换为其他格式。READTEXT 可以用来读取这些数据,以便进行后续处理。
5.检查数据内容:在某些情况下,需要检查特定文本或图像数据的内容,例如验证文档的完整性或查看图像的部分内容,READTEXT 可以帮助实现这一目的。
文本或图像数据的分析或处理:某些应用场景下,需要对文本或图像数据进行分析、处理或转换,例如进行全文搜索、提取图像特征等,READTEXT 可以用来读取数据以进行进一步处理。
>.BACKUP 备份数据.
--BACKUP 命令是 Server 中用于创建数据库备份的关键命令之一。它允许用户创建完整备份、差异备份和日志备份,以确保数据的安全性和可恢复性。以下是 BACKUP 命令的基本语法和一些常见用法: --1. **完整备份**: BACKUP DATABASE database_name TO disk = 'backup_path\backup_file.bak'; --这条命令将指定数据库的完整备份保存到指定的磁盘位置。完整备份包含了整个数据库的所有数据和对象。 --2. **差异备份**: BACKUP DATABASE database_name TO disk = 'backup_path\backup_file.bak' WITH DIFFERENTIAL; --差异备份是基于最近一次完整备份的变化部分的备份。它只包含自上次完整备份或差异备份以来发生的更改。 3. **日志备份**: BACKUP LOG database_name TO disk = 'backup_path\backup_file.trn'; --日志备份用于备份数据库事务日志,以便实现基于日志的恢复和恢复到特定时间点的操作。 4. **备份操作参数**: -- WITH INIT:表示初始化备份文件,覆盖现有的备份文件。 -- WITH FORMAT:表示将备份文件格式化,以便可直接进行完整数据库恢复。 -- WITH COMPRESSION:表示使用压缩备份,减少备份文件大小但会增加 CPU 使用。 -- WITH CHECKSUM:表示在备份时执行校验和检查,以确保备份文件的完整性。 5. **示例**: BACKUP DATABASE AdventureWorks TO DISK = 'D:\Backups\AdventureWorks_full.bak' WITH INIT, FORMAT, COMPRESSION; 这个示例演示了对 AdventureWorks 数据库进行完整备份,并将备份文件保存到指定路径,并且使用了初始化、格式化和压缩选项。
>.RESTORE 还原数据.
--RESTORE 命令是 SQL Server 中用于恢复数据库的关键命令之一。它允许用户从数据库备份中还原数据,并支持完整数据库恢复、差异数据库恢复以及事务日志恢复等操作。以下是 RESTORE 命令的基本语法和一些常见用法: --1. **完整数据库恢复**: RESTORE DATABASE database_name FROM disk = 'backup_path\backup_file.bak' WITH REPLACE, RECOVERY; --这条命令将从指定的备份文件中还原数据库的完整备份。选项 WITH REPLACE 表示如果目标数据库已经存在,则覆盖它;选项 WITH RECOVERY 表示数据库恢复后将处于可用状态。 --2. **差异数据库恢复**: RESTORE DATABASE database_name FROM disk = 'backup_path\backup_file.bak' WITH RECOVERY; --如果之前已经进行了完整备份并启用了差异备份,那么可以使用差异备份来恢复数据库,语法与完整数据库恢复类似。 --3. **事务日志恢复**: RESTORE LOG database_name FROM disk = 'backup_path\backup_file.trn' WITH RECOVERY; --这条命令用于将事务日志应用到数据库,实现事务级别的恢复或将数据库恢复到特定时间点的操作。 --4. **恢复操作参数**: -- WITH REPLACE:表示替换已存在的同名数据库。 -- WITH RECOVERY:表示将数据库恢复到可用状态。 -- WITH NORECOVERY:表示将数据库保持为不可用状态,以便后续应用事务日志。 -- WITH MOVE:在恢复时可以指定新的数据文件和日志文件的位置。 -- WITH STANDBY:用于将数据库设置为 standby 模式,允许在恢复过程中进行只读访问。 --5. **示例**: RESTORE DATABASE AdventureWorks FROM DISK = 'D:\Backups\AdventureWorks_full.bak' WITH REPLACE, RECOVERY; --这个示例演示了从指定路径的完整备份文件还原 AdventureWorks 数据库,并且使用了替换和恢复选项。 --RESTORE 命令是数据库管理中非常重要的操作,它用于从备份中还原数据,保证数据的可用性和完整性,并支持多种恢复场景,因此在数据库管理和运维中经常会用到。
>.SELECT. 略
>.SET. 略
备注:select 可以同时给多个变量赋值,而set一次只能给一个变量赋值.但SET命令功能更强且更严密,因此推荐使用SET命令给变量赋值.
>.SHUTDOWN. 用于停止SQL SERVER的执行.它的执行步骤如下:
>. 终止任何用户登录SQL SERVER:这意味着在执行 SHUTDOWN 命令之后,不再允许新的用户连接到 SQL Server。这是确保在关闭过程中不会有新的活动。
>.等待尚未完成的SQL命令或者存储过程执行完毕:在关闭 SQL Server 之前,系统会等待所有已经开始但尚未完成的 SQL 命令或存储过程执行完成。这是为了确保正在进行的操作不会被中断。
>.在每个数据库中执行CHECKPOINT命令:CHECKPOINT 是一个 SQL Server 命令,用于将所有已修改的数据页面写入磁盘,以确保数据库的一致性。在关闭 SQL Server 之前,会在每个数据库中执行 CHECKPOINT 命令,以便将数据写入磁盘,避免数据丢失。
>.停止SQL SERVER的执行:一旦所有用户已断开连接、未完成的操作已完成、并且数据已经被检查点写入磁盘,SQL Server 将会停止执行,关闭服务。
>.WRITETEXT. 与READTEXT相反的操作,略
>.USE. 略
小结:
本章介绍了SQL的基础知识,包括SQL的数据类型,常量,变量,流程控制语句和常用的命令等.学习本章时,读者需要了解与SQL相关的概念,区分常量和变量,熟悉常用命令,熟练地掌握流程控制语句的用法,因为流程控制语句可以提高SQL语句的处理能力.
标签:语句,读书笔记,--,数据库,SERVER,运算符,SQL,SELECT From: https://www.cnblogs.com/yoooos/p/17871245.html