Tracks
T‑SQL(Transact-SQL)是微软对标准 SQL 的扩展,专为 Microsoft SQL Server 而设计。它不仅包含用于查询和管理数据的所有 SQL 核心功能,还新增了过程式编程特性,使您能够编写更强大、更动态的数据库逻辑。
在本指南中,我将向您展示 T-SQL 的工作原理,以及如何在真实场景中高效使用它。我还将结合实际示例,介绍查询数据库、编写存储过程和自动化日常流程等常见用例。
如果您是 SQL 新手,请从我们的SQL 入门课程开始;如果已有一定经验,可学习SQL 进阶课程。另外,我认为可下载的 SQL 基础速查表很有用,因为它汇总了最常用的 SQL 函数,便于查阅。
什么是 T-SQL,与 SQL 有何不同
为了更好地理解 T-SQL,可以将 SQL 视为通用语言,而 T-SQL 则是某一职业领域的专业方言。
SQL(结构化查询语言)是与关系型数据库交互的标准语言。它是声明式的,也就是说,您只需指定想要的结果(例如选择或筛选数据),数据库引擎将决定如何执行查询。
而 T-SQL 是微软在 Microsoft SQL Server 中使用的 SQL 扩展。它在标准 SQL 之上增加了过程式编程能力,使您可以按步骤控制操作的执行方式。
由此可见,T-SQL 引入了多项超越基础查询的强大功能,包括:
-
变量: 您可以使用
DECLARE和SET关键字在内存中存储数据,并在脚本中复用 -
控制流:可以使用
IF、WHILE和BEGIN...END等逻辑来控制执行并决定运行哪些代码。 -
错误处理:T-SQL 引入了
TRY...CATCH块,允许数据库捕获错误并优雅地处理,而不会导致整个操作崩溃。 -
存储过程:您可以创建在数据库内部运行的可复用逻辑块。
如果您正在使用 SQL Server,DataCamp 提供了大量优质资源可供学习。建议从 DataCamp 的SQL Server 入门课程开始,掌握用于数据分析的 SQL Server 基础。
T-SQL 的基本语法与结构
T-SQL 使用与标准 SQL 相同的核心语法,如果您已经熟悉 SQL,将很容易上手。本节将通过简明的实用示例带您了解 T-SQL 最常见的语句。
SELECT、INSERT、UPDATE、DELETE
这些命令在大多数 SQL 方言中都是通用的,T-SQL 面向的 Microsoft SQL Server 亦然。
SELECT
用于从特定表中检索数据。例如,以下查询从 Customers 表中检索 FirstName 和 LastName。
-- Retrieve data from the Customers table
SELECT FirstName, LastName
FROM Customers
WHERE Country = ‘USA’; -- Filters rows to only customers in the USA
INSERT
用于向表中插入新数据。下面的查询向 customers 表插入一行新记录。
-- Insert a new row into a table
INSERT INTO customers (FirstName, city)
VALUES (‘Alice’, ‘Nairobi’);
UPDATE
用于修改数据库中的现有数据。例如,下面的查询将用户“Alice”的城市名称改为“Mombasa”。
-- Update existing data
UPDATE customers
SET city = ‘Mombasa’
WHERE FirstName= ‘Alice’; -- Always use WHERE to avoid updating all rows
DELETE
用于从数据库中删除数据。例如,下面的查询删除 FirstName 为“Alice”的那一行。
-- Delete data from a table
DELETE FROM customers
WHERE FirstName= ‘Alice’; -- Filters which rows to remove
建议您学习我们的SQL Server 基础技能路径,进一步了解如何使用 SQL Server 函数汇总与分析数据。
批处理执行
T-SQL 的一大特色在于其按批处理执行代码。批处理是一次发送到 SQL Server 的一组一个或多个 SQL 语句。
GO 关键字用于分隔批处理:
-- First batch
SELECT * FROM Customers;
GO
-- Second batch (executed separately)
SELECT * FROM Orders;
GO
需要注意:
-
GO不是 T-SQL 命令,但会被 SQL Server Management Studio 等工具识别。 -
它用于标记一个批处理的结束和另一个批处理的开始。
-
变量不会在批处理之间保留。同一会话中的临时对象实际上会在批处理之间保留。
注释与格式
您可以在 T-SQL 中使用注释,让 SQL 代码更易读、易维护。既可使用单行注释,也可使用多行注释,如下所示:
-- This query retrieves all customers
SELECT * FROM Customers;
/* This query retrieves customers
from the USA and Canada */
SELECT *
FROM Customers
WHERE Country IN ('USA', 'Canada');
T-SQL 中的变量与数据类型
T-SQL 允许您将值存储在变量中并在查询中使用,使脚本更灵活、更动态。下面看看如何创建这些变量。
声明变量
创建变量需使用 DECLARE 关键字。按照惯例,所有 T-SQL 变量名都必须以 @ 符号开头。
-- Declares a variable to store text
DECLARE @CustomerName VARCHAR(50);
赋值
可以使用 SET(推荐用于单一值)或 SELECT(从表中取值时很有用)来赋值。
-- Assign using SET
SET @CustomerName = 'Alice';
-- Assign using SELECT
SELECT @Age = 30;
例如,下面的查询使用变量而非硬编码,返回居住在伦敦的客户列表。
-- Assign the variable city
DECLARE @City VARCHAR(50);
SET @City = 'London';
-- Use the variable in a query
SELECT name, city
FROM customers
WHERE city = @City; -- Filters results based on variable value
常见数据类型
以下是一些常用的 T-SQL 数据类型,这些类型在SQL 数据类型中也较为标准:
-
INT:整数,例如 1、100。 -
VARCHAR(n):可变长度文本,如姓名和邮箱。 -
DATETIME:日期和时间值。 -
DECIMAL(p, s):定点精度数字,如货币。
T-SQL 中的控制流(IF、WHILE、BEGIN...END)
T-SQL 的优势之一是可以为查询添加编程逻辑。您不仅能检索数据,还能控制代码的执行方式和时机。以下是控制流逻辑的示例。
IF...ELSE(条件执行)
IF 语句允许仅在满足特定条件时执行代码块。如果条件为假,可使用 ELSE 提供备用操作。
例如,下面的查询统计订单总数;若超过 100,则打印“High order volume”,否则打印“Low order volume”。
DECLARE @TotalOrders INT;
SELECT @TotalOrders = COUNT(*)
FROM Orders; -- Count total number of orders
IF @TotalOrders > 100
BEGIN
PRINT 'High order volume'; -- Runs if condition is true
END
ELSE
BEGIN
PRINT 'Low order volume'; -- Runs if condition is false
END
WHILE 循环(迭代逻辑)
WHILE 循环会在条件为真时重复执行代码块。它适用于分批执行的任务或生成测试数据。
下面的查询将计数器初始化为 1,并通过循环打印当前数字,每次加 1,直到达到 5。
DECLARE @Counter INT = 1;
WHILE @Counter <= 5
BEGIN
PRINT @Counter; -- Prints numbers from 1 to 5
SET @Counter = @Counter + 1; -- Increment counter
END
BEGIN...END(语句分组)
BEGIN...END 用于将多条语句分组为一个代码块,确保成组代码原子性地一起执行。
例如,下面的查询将同时打印“Customers found in USA”和“Proceeding with operation.”。若不使用 BEGIN...END,则仅会执行 IF 之后的第一条语句。
IF EXISTS (SELECT 1 FROM Customers WHERE Country = 'USA')
BEGIN
PRINT 'Customers found in USA';
PRINT 'Proceeding with operation'; -- Both statements run together
END
控制流何时有用?
T-SQL 中的控制流常用于:
- 自动化:运行计划脚本或维护任务
- 数据校验:在插入或更新数据前检查条件
- 批处理:分步骤或循环处理数据
- 业务逻辑:将规则直接应用于数据库内部
T-SQL 中的存储过程
存储过程是一组保存下来的 T-SQL 语句,您可以反复复用。与其每次都从应用程序发送大量代码到服务器,不如将代码保存在服务器上,随后只需调用其名称即可。
存储过程之所以有用,是因为它们可多次复用。预编译的执行计划可提升效率,并将复杂逻辑隐藏在简单接口之后。
例如,下面的存储过程会根据您提供的 ID 返回客户的名与姓。
-- Create a stored procedure named GetCustomerByID
CREATE PROCEDURE GetCustomerByID
@CustomerID INT -- Input parameter to pass a customer ID
AS
BEGIN
-- Select the first and last name of a customer
SELECT FirstName, LastName
FROM Customers
WHERE CustomerID = @CustomerID; -- Filter to match the given ID
END;
随后,您可通过下面的查询来执行该存储过程:
-- Calls the procedure
EXEC GetCustomerByID @CustomerID = 1; T-SQL 中的函数
T-SQL 包含内置函数和用户自定义函数(UDF),用于转换数据。
内置函数
这些函数已在 SQL Server 中提供,可直接在查询中使用。
字符串函数
用于转换字符串数据类型。例如,下面的查询从 Customers 表中检索所有名字,并将其转换为大写。
-- Converts text to uppercase
SELECT UPPER(FirstName)
FROM Customers;
日期函数
用于处理日期函数。下面的查询返回当前系统日期和时间。
-- Returns current date and time
SELECT GETDATE();
聚合函数
用于对表中的值进行聚合。例如,下面的查询统计 Customers 表中的总行数(客户数)。
-- Counts rows
SELECT COUNT(*) AS TotalCustomers
FROM Customers;
用户自定义函数(UDF)
您也可以创建自己的函数,在多条查询中复用逻辑。
标量函数
标量函数返回单个值,适用于需要单一计算结果(如格式化或计算)的场景。下面的函数以名字和姓氏为输入,并返回合并后的全名。
-- Create a function that combines the first and last name
CREATE FUNCTION GetFullName
(@FirstName VARCHAR(50), @LastName VARCHAR(50))
RETURNS VARCHAR(100)
AS
BEGIN
RETURN @FirstName + ' ' + @LastName; -- Concatenates the two values
END;
表值函数
表值函数返回一个表。例如,下面的函数返回属于指定国家的所有客户组成的表。
-- Create a table-valued function named GetCustomersByCountry
CREATE FUNCTION GetCustomersByCountry (@Country VARCHAR(50))
RETURNS TABLE -- Specifies that the function returns a table
AS
RETURN
(
-- Select all columns from the Customers table
SELECT *
FROM Customers
WHERE Country = @Country -- Filter rows by the given country
);
建议您学习完整的SQL Server 开发者职业路径,不仅能掌握创建、更新与执行存储过程的技能,还将学习聚合函数、连接、插入与删除表等诸多内容。
T-SQL 中的错误处理
T-SQL 使用 TRY...CATCH 块处理错误,而不致使整个脚本停止。这一点很重要,可防止脚本意外崩溃,并便于返回有用的信息用于调试或日志记录。
例如,下面的查询尝试运行会触发错误的计算,捕获错误后打印可读的错误信息,而不是直接崩溃。
BEGIN TRY
-- Attempt to run this code
SELECT 1 / 0; -- This causes a divide-by-zero error
END TRY
BEGIN CATCH
-- Runs if an error occurs in the TRY block
PRINT 'An error occurred: ' + ERROR_MESSAGE(); -- Displays the error message
END CATCH;
T-SQL 中的事务
事务确保一组操作要么全部成功、要么全部失败。这遵循 ACID 原则,即使在更新中途断电,也能保证数据库保持一致性。
在下面的示例中,事务在两个账户之间转账,并将两项更改一起保存。
BEGIN TRANSACTION; -- Start the transaction
-- Deduct money from Account 1
UPDATE Accounts
SET Balance = Balance - 100
WHERE AccountID = 1;
-- Add money to Account 2
UPDATE Accounts
SET Balance = Balance + 100
WHERE AccountID = 2;
COMMIT; -- Save all changes permanently
如果出现问题,您可以使用 ROLLBACK 回滚事务,将数据还原至之前的状态。
-- Undo all changes made in the current transaction
ROLLBACK;
T-SQL 中的事务十分重要,它们可确保数据完整性,尤其在金融等关键系统中,部分更新可能导致数据不一致。
您可以学习我们的SQL Server 中的事务与错误处理职业路径,系统掌握 SQL Server 的事务与错误处理。
用于数据分析的常见 T-SQL 功能
T-SQL 包含一些对数据专业人士尤为有用的工具。下面看看示例以及如何在数据分析中应用它们。
窗口函数
窗口函数可在不将多行聚为单一结果的情况下跨行进行计算,多用于排名、运行总计和高级分析。
在下面的示例中,查询根据 CustomerID 为每位客户分配唯一的行号。
-- Assigns row numbers to customers
SELECT
FirstName,
ROW_NUMBER() OVER (ORDER BY CustomerID) AS RowNum -- Assigns row numbers
FROM Customers;
在该查询中:
-
ROW_NUMBER():分配唯一行号
-
RANK():为并列值分配有间隙的名次 -
OVER():定义窗口(排序/分区)
建议查看我们的SQL 窗口函数速查表(可下载),它提供各类 SQL 窗口函数的便捷参考。另外,欢迎学习我们的SQL Server 进阶课程,了解更多在数据分析中使用 T-SQL 的方法,包括使用窗口函数汇总数据。
公用表表达式(CTE)
CTE(公用表表达式)可创建临时结果集,便于在一个查询中复用。下面的查询创建了一个美国客户的临时列表,然后从中检索数据。
-- Define a CTE
WITH CustomerCTE AS (
SELECT FirstName, Country
FROM Customers
WHERE Country = 'USA' -- Filter only USA customers
)
-- Query the CTE
SELECT *
FROM CustomerCTE;
另一方面,递归 CTE 是一种特殊类型的 CTE,它在定义中引用自身,从而能够执行重复性操作。这使其非常适合处理组织架构等层级数据。
建议学习我们的SQL Server 中的层级与递归查询课程,掌握编写包含 CTE 和递归 CTE 的高级查询(含实用示例)。
临时表
临时表用于在会话期间短期存储数据。它们适合用于数据分阶段处理、简化多步转换,或在复杂查询中提升性能。
为演示 t-SQL 中临时表的工作方式,请参考以下三个查询块。第一个创建临时表,然后插入客户数据,最后在同一会话中对其进行查询。
-- Create a temporary table
CREATE TABLE #TempCustomers (
FirstName VARCHAR(50),
Country VARCHAR(50)
);
-- Insert data into the temporary table
INSERT INTO #TempCustomers
SELECT FirstName, Country
FROM Customers;
-- Retrieve data from the temporary table
SELECT * FROM #TempCustomers;
需要注意的是,临时表以 # 为前缀,并会在会话结束时自动删除。
T-SQL 与其他 SQL 方言对比
各 SQL 方言具有共同基础,但每种数据库系统都会加入各自的语法与功能。T-SQL 专为 Microsoft SQL Server 而设计,这也影响了它的工作方式及最佳适用场景。
T-SQL 与 PostgreSQL(PL/pgSQL)
PostgreSQL 使用 PL/pgSQL 实现过程式逻辑,与 T-SQL 相似,但语法与优势不同。下表概述了这些差异:
|
类别 |
T-SQL(SQL Server) |
PostgreSQL(PL/pgSQL) |
|
过程式语言 |
内置于 T-SQL |
使用 PL/pgSQL |
|
变量语法 |
|
|
|
变量命名 |
使用 |
无前缀(如 |
|
块结构 |
更简洁,常为隐式或 |
显式:需要 |
|
示例代码块 |
标准 T-SQL 批处理 |
包裹于 |
|
高级数据类型 |
相对有限 |
原生支持更丰富(JSONB、数组、几何) |
|
工具与集成 |
与 SQL Server 工具深度集成 |
跨平台更灵活 |
|
生态 |
优化面向 Windows、Azure、SSMS 与 Power BI |
开源、跨平台 |
查看我们的数据库管理员的 SQL技能路径,学习如何设计关系型数据库并优化查询结构以提升性能。
T-SQL 与 MySQL
MySQL 也支持过程式 SQL,但实现更为简洁、功能相对有限。下表比较了两种方言的语法与特性差异。
|
类别 |
T-SQL(Microsoft) |
MySQL |
|
行数限制 |
|
|
|
错误处理 |
健全的 |
较为受限的 DECLARE HANDLER 语法 |
|
过程式逻辑 |
丰富、结构化、可编程性强 |
更简单、过程式功能较少 |
|
分析能力 |
支持窗口函数与 CTE |
基础分析功能(新版本在改进) |
|
生态系统 |
与 SQL Server 与企业级工具深度绑定 |
轻量级;LAMP 堆栈核心(Linux、Apache 等) |
|
最佳适用场景 |
复杂业务逻辑与数据仓库 |
Web 应用与高速读操作 |
T-SQL 的真实世界用例
T-SQL 的应用远不止简单的数据查询。以下是我在数据工作中发现它很有用的一些场景。
报表查询
T-SQL 常用于直接从数据库生成报表。例如,您可以按区域汇总销售额,或使用窗口函数对高绩效产品进行排名。
ETL 流程(抽取、转换、加载)
数据工程师在数据管道中使用 T-SQL 准备与搬运数据。例如,从暂存表抽取数据、转换格式、清理不一致项,并加载到最终的报表表中。
数据清洗脚本
当数据库中有数百万行且地址格式不一致时,您可以使用包含 WHILE 循环或 CTE 的 T-SQL 脚本,识别重复、填补缺失值或标准化格式。
应用的后端逻辑
许多应用依赖 T-SQL 在数据库内部处理业务逻辑。您可以用存储过程执行 CRUD 操作、在插入数据前进行校验,或在关键操作中使用事务处理。
常见错误与最佳实践
尽管 T-SQL 对高级数据库查询很有帮助,但您可能会遇到一些常见问题。以下是我在使用 T‑SQL 时见到的常见错误:
-
过度使用循环而非基于集合的逻辑: 使用
WHILE等循环逐行处理会拖慢性能。SQL 的设计初衷是一次性处理数据集合。 -
忽视索引: 未正确使用索引会使查询变慢,尤其在大表上。
-
不正确使用事务: 将多个相关操作不放入事务中执行,一旦中途失败,可能导致数据不一致。
-
忽略错误处理: 若跳过
TRY...CATCH块,将加大调试难度,且在生产环境中可能导致脚本无声失败或出现不可预期的错误。
以下是我建议的最佳实践,可帮助您编写更高效、更可靠的查询:
-
优先采用基于集合的查询: 尽可能使用
JOIN、GROUP BY和窗口函数代替循环处理,这与 SQL Server 的高效数据处理方式相契合。 -
编写可读、可维护的代码: 使用清晰的命名规范、保持一致的格式,并在必要处添加注释。这能提升代码的可读性,便于调试与协作。
-
测试过程: 始终使用不同输入测试存储过程与查询,确保其正确运行并妥善处理边界情况。
结语
T-SQL 在标准 SQL 的基础上增加了编程能力,使其成为用于自动化、数据处理与分析的灵活而强大的工具。借助变量、存储过程与错误处理等功能,您可以构建更为动态高效的数据库解决方案。
接下来,我建议您学习SQL 方向的助理数据分析师职业路径,成为熟练的数据分析师。我们的SQL 报表课程也将帮助您熟练构建复杂报表。最后,建议获取我们的SQL 助理认证,展示您运用 SQL 解决业务问题的能力,从众多专业人士中脱颖而出。
T-SQL 常见问答
T-SQL 与标准 SQL 有何不同?
SQL 主要是声明式的,而 T-SQL 将声明式查询与过程式编程相结合,使您可以控制操作的执行方式。
学习 T-SQL 之前需要先学 SQL 吗?
是的,了解 SQL 的基础很重要,因为 T-SQL 直接建立在 SELECT、INSERT、UPDATE、DELETE 等核心概念之上。
所有 SQL 方言都提供 T-SQL 吗?
不需要。T-SQL 属于微软生态,主要用于 Microsoft SQL Server 及 Azure SQL 等相关工具。
什么是存储过程?为何有用?
存储过程是在数据库内部运行的可复用 T-SQL 代码块。它们有助于提升性能、确保一致性,并简化应用逻辑。
T-SQL 中的窗口函数用于做什么?
窗口函数用于高级分析任务,如排名、运行总计,以及在不分组数据的情况下跨行比较数值。