sqlserver
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSQL Server Core Knowledge
SQL Server 核心知识
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsfor comprehensive documentation.sqlserver
深度参考:使用工具并指定technology为mcp__documentation__fetch_docs,可获取完整文档。sqlserver
Data Types
数据类型
Numeric Types
数值类型
| Type | Description | Range |
|---|---|---|
| Boolean (0/1) | 0, 1, NULL |
| 1 byte integer | 0 to 255 |
| 2 byte integer | -32,768 to 32,767 |
| 4 byte integer | -2^31 to 2^31-1 |
| 8 byte integer | -2^63 to 2^63-1 |
| Fixed precision | p: 1-38 digits |
| Same as DECIMAL | p: 1-38 digits |
| 8 byte float | ~15 digits precision |
| 4 byte float | ~7 digits precision |
| 8 byte currency | ±922 trillion |
| 4 byte currency | ±214,748 |
| 类型 | 描述 | 范围 |
|---|---|---|
| 布尔值(0/1) | 0, 1, NULL |
| 1字节整数 | 0 到 255 |
| 2字节整数 | -32,768 到 32,767 |
| 4字节整数 | -2^31 到 2^31-1 |
| 8字节整数 | -2^63 到 2^63-1 |
| 固定精度数值 | p: 1-38位数字 |
| 与DECIMAL功能相同 | p: 1-38位数字 |
| 8字节浮点数 | 约15位精度 |
| 4字节浮点数 | 约7位精度 |
| 8字节货币类型 | ±922万亿 |
| 4字节货币类型 | ±214,748 |
String Types
字符串类型
| Type | Description | Max Size |
|---|---|---|
| Fixed-length | 8,000 bytes |
| Variable-length | 8,000 bytes |
| Large variable | 2 GB |
| Unicode fixed | 4,000 chars |
| Unicode variable | 4,000 chars |
| Unicode large | 1 GB |
| Legacy large (deprecated) | 2 GB |
| Legacy Unicode (deprecated) | 1 GB |
| 类型 | 描述 | 最大容量 |
|---|---|---|
| 固定长度字符串 | 8,000字节 |
| 可变长度字符串 | 8,000字节 |
| 大可变长度字符串 | 2 GB |
| Unicode固定长度字符串 | 4,000字符 |
| Unicode可变长度字符串 | 4,000字符 |
| Unicode大可变长度字符串 | 1 GB |
| 旧版大文本类型(已废弃) | 2 GB |
| 旧版Unicode大文本类型(已废弃) | 1 GB |
Date/Time Types
日期/时间类型
| Type | Description | Range |
|---|---|---|
| Date only | 0001-01-01 to 9999-12-31 |
| Time only (n=0-7 precision) | 00:00:00 to 23:59:59 |
| Date + time | 1753-01-01 to 9999-12-31 |
| Extended datetime | 0001-01-01 to 9999-12-31 |
| With timezone | Same + timezone |
| Less precision | 1900-01-01 to 2079-06-06 |
| 类型 | 描述 | 范围 |
|---|---|---|
| 仅日期 | 0001-01-01 到 9999-12-31 |
| 仅时间(n=0-7表示精度) | 00:00:00 到 23:59:59 |
| 日期+时间 | 1753-01-01 到 9999-12-31 |
| 扩展日期时间类型 | 0001-01-01 到 9999-12-31 |
| 带时区的日期时间 | 范围同上,附加时区信息 |
| 低精度日期时间 | 1900-01-01 到 2079-06-06 |
Other Types
其他类型
| Type | Description |
|---|---|
| 16-byte GUID |
| Fixed binary |
| Variable binary |
| Large binary (2 GB) |
| XML data |
| JSON (stored as NVARCHAR) |
| Spatial data |
| Geometric data |
| Hierarchy position |
sql
CREATE TABLE example (
id INT IDENTITY(1,1) PRIMARY KEY,
uuid UNIQUEIDENTIFIER DEFAULT NEWID(),
name NVARCHAR(100) NOT NULL,
price DECIMAL(10,2),
quantity INT DEFAULT 0,
is_active BIT DEFAULT 1,
created_at DATETIME2 DEFAULT SYSDATETIME(),
metadata NVARCHAR(MAX), -- For JSON
document VARBINARY(MAX) -- For files
);| 类型 | 描述 |
|---|---|
| 16字节GUID |
| 固定长度二进制数据 |
| 可变长度二进制数据 |
| 大二进制数据(2 GB) |
| XML数据类型 |
| JSON数据(存储为NVARCHAR类型) |
| 空间地理数据类型 |
| 空间几何数据类型 |
| 层级位置数据类型 |
sql
CREATE TABLE example (
id INT IDENTITY(1,1) PRIMARY KEY,
uuid UNIQUEIDENTIFIER DEFAULT NEWID(),
name NVARCHAR(100) NOT NULL,
price DECIMAL(10,2),
quantity INT DEFAULT 0,
is_active BIT DEFAULT 1,
created_at DATETIME2 DEFAULT SYSDATETIME(),
metadata NVARCHAR(MAX), -- For JSON
document VARBINARY(MAX) -- For files
);Identity Columns
标识列
sql
-- Auto-increment
CREATE TABLE employees (
id INT IDENTITY(1,1) PRIMARY KEY,
name NVARCHAR(100)
);
-- Get last identity
SELECT SCOPE_IDENTITY(); -- Current scope
SELECT @@IDENTITY; -- Any scope (avoid)
SELECT IDENT_CURRENT('employees'); -- Specific table
-- Insert with identity off
SET IDENTITY_INSERT employees ON;
INSERT INTO employees (id, name) VALUES (100, 'Admin');
SET IDENTITY_INSERT employees OFF;
-- Reseed identity
DBCC CHECKIDENT ('employees', RESEED, 0);sql
-- 自动递增
CREATE TABLE employees (
id INT IDENTITY(1,1) PRIMARY KEY,
name NVARCHAR(100)
);
-- 获取最后生成的标识值
SELECT SCOPE_IDENTITY(); -- 当前作用域内的标识值
SELECT @@IDENTITY; -- 任意作用域的标识值(不推荐使用)
SELECT IDENT_CURRENT('employees'); -- 指定表的标识值
-- 关闭标识插入后插入数据
SET IDENTITY_INSERT employees ON;
INSERT INTO employees (id, name) VALUES (100, 'Admin');
SET IDENTITY_INSERT employees OFF;
-- 重置标识种子
DBCC CHECKIDENT ('employees', RESEED, 0);Sequences (2012+)
序列(2012及以上版本)
sql
-- Create sequence
CREATE SEQUENCE dbo.OrderSeq
AS INT
START WITH 1
INCREMENT BY 1
MINVALUE 1
NO MAXVALUE
NO CYCLE
CACHE 20;
-- Use sequence
INSERT INTO orders (id, customer_id)
VALUES (NEXT VALUE FOR dbo.OrderSeq, 1);
-- In DEFAULT
ALTER TABLE orders
ADD CONSTRAINT df_order_id DEFAULT (NEXT VALUE FOR dbo.OrderSeq) FOR id;
-- Get current without incrementing
SELECT current_value FROM sys.sequences WHERE name = 'OrderSeq';
-- Reset sequence
ALTER SEQUENCE dbo.OrderSeq RESTART WITH 1;sql
-- 创建序列
CREATE SEQUENCE dbo.OrderSeq
AS INT
START WITH 1
INCREMENT BY 1
MINVALUE 1
NO MAXVALUE
NO CYCLE
CACHE 20;
-- 使用序列
INSERT INTO orders (id, customer_id)
VALUES (NEXT VALUE FOR dbo.OrderSeq, 1);
-- 设置默认值为序列
ALTER TABLE orders
ADD CONSTRAINT df_order_id DEFAULT (NEXT VALUE FOR dbo.OrderSeq) FOR id;
-- 获取当前序列值(不递增)
SELECT current_value FROM sys.sequences WHERE name = 'OrderSeq';
-- 重置序列
ALTER SEQUENCE dbo.OrderSeq RESTART WITH 1;Date/Time Functions
日期/时间函数
sql
-- Current date/time
SELECT GETDATE(); -- DATETIME
SELECT SYSDATETIME(); -- DATETIME2 (more precise)
SELECT GETUTCDATE(); -- UTC datetime
SELECT SYSUTCDATETIME(); -- UTC datetime2
SELECT SYSDATETIMEOFFSET(); -- With timezone
-- Date parts
SELECT YEAR(GETDATE());
SELECT MONTH(GETDATE());
SELECT DAY(GETDATE());
SELECT DATEPART(QUARTER, GETDATE());
SELECT DATENAME(WEEKDAY, GETDATE()); -- 'Monday'
-- Date arithmetic
SELECT DATEADD(DAY, 7, GETDATE()); -- Add 7 days
SELECT DATEADD(MONTH, -1, GETDATE()); -- Subtract 1 month
SELECT DATEDIFF(DAY, '2024-01-01', GETDATE()); -- Days between
-- Format (2012+)
SELECT FORMAT(GETDATE(), 'yyyy-MM-dd');
SELECT FORMAT(GETDATE(), 'dd/MM/yyyy HH:mm:ss');
-- Parse
SELECT CAST('2024-01-15' AS DATE);
SELECT CONVERT(DATETIME, '01/15/2024', 101); -- US format
SELECT PARSE('15 January 2024' AS DATE);
-- First/last of month
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0); -- First of month
SELECT EOMONTH(GETDATE()); -- Last of month (2012+)sql
-- 获取当前日期/时间
SELECT GETDATE(); -- 返回DATETIME类型
SELECT SYSDATETIME(); -- 返回DATETIME2类型(精度更高)
SELECT GETUTCDATE(); -- 返回UTC时间(DATETIME类型)
SELECT SYSUTCDATETIME(); -- 返回UTC时间(DATETIME2类型)
SELECT SYSDATETIMEOFFSET(); -- 返回带时区的日期时间
-- 提取日期部分
SELECT YEAR(GETDATE());
SELECT MONTH(GETDATE());
SELECT DAY(GETDATE());
SELECT DATEPART(QUARTER, GETDATE());
SELECT DATENAME(WEEKDAY, GETDATE()); -- 返回星期名称,如'Monday'
-- 日期运算
SELECT DATEADD(DAY, 7, GETDATE()); -- 加7天
SELECT DATEADD(MONTH, -1, GETDATE()); -- 减1个月
SELECT DATEDIFF(DAY, '2024-01-01', GETDATE()); -- 计算两个日期的天数差
-- 格式化日期(2012及以上版本)
SELECT FORMAT(GETDATE(), 'yyyy-MM-dd');
SELECT FORMAT(GETDATE(), 'dd/MM/yyyy HH:mm:ss');
-- 解析字符串为日期
SELECT CAST('2024-01-15' AS DATE);
SELECT CONVERT(DATETIME, '01/15/2024', 101); -- 按美国格式解析
SELECT PARSE('15 January 2024' AS DATE);
-- 获取当月第一天和最后一天
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0); -- 当月第一天
SELECT EOMONTH(GETDATE()); -- 当月最后一天(2012及以上版本)String Functions
字符串函数
sql
-- Concatenation
SELECT 'Hello' + ' ' + 'World';
SELECT CONCAT('Hello', ' ', 'World');
SELECT CONCAT_WS(' ', 'Hello', 'World', NULL); -- With separator, ignores NULL
-- Substring
SELECT SUBSTRING('Hello World', 1, 5); -- 'Hello'
SELECT LEFT('Hello World', 5); -- 'Hello'
SELECT RIGHT('Hello World', 5); -- 'World'
-- Length
SELECT LEN('Hello'); -- 5 (chars, trims trailing spaces)
SELECT DATALENGTH('Hello'); -- 5 (bytes)
-- Case
SELECT UPPER('hello');
SELECT LOWER('HELLO');
-- Trim
SELECT TRIM(' hello ');
SELECT LTRIM(' hello');
SELECT RTRIM('hello ');
SELECT TRIM('x' FROM 'xxxhelloxxx'); -- 2017+
-- Replace
SELECT REPLACE('hello', 'l', 'L');
SELECT STUFF('Hello World', 7, 5, 'SQL'); -- 'Hello SQL'
-- Position
SELECT CHARINDEX('o', 'Hello World'); -- 5
SELECT CHARINDEX('o', 'Hello World', 6); -- 8 (start from 6)
-- Padding
SELECT RIGHT('0000000000' + '123', 10); -- '0000000123'
SELECT FORMAT(123, '0000000000'); -- 2012+
-- Split (2016+)
SELECT value FROM STRING_SPLIT('a,b,c', ',');
-- Aggregate strings (2017+)
SELECT STRING_AGG(name, ', ') FROM employees;
SELECT STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY name) FROM employees;sql
-- 字符串拼接
SELECT 'Hello' + ' ' + 'World';
SELECT CONCAT('Hello', ' ', 'World');
SELECT CONCAT_WS(' ', 'Hello', 'World', NULL); -- 使用分隔符拼接,自动忽略NULL
-- 子字符串
SELECT SUBSTRING('Hello World', 1, 5); -- 返回'Hello'
SELECT LEFT('Hello World', 5); -- 返回'Hello'
SELECT RIGHT('Hello World', 5); -- 返回'World'
-- 长度计算
SELECT LEN('Hello'); -- 返回5(字符数,自动忽略末尾空格)
SELECT DATALENGTH('Hello'); -- 返回5(字节数)
-- 大小写转换
SELECT UPPER('hello');
SELECT LOWER('HELLO');
-- 去除空格
SELECT TRIM(' hello ');
SELECT LTRIM(' hello');
SELECT RTRIM('hello ');
SELECT TRIM('x' FROM 'xxxhelloxxx'); -- 2017及以上版本支持
-- 替换字符串
SELECT REPLACE('hello', 'l', 'L');
SELECT STUFF('Hello World', 7, 5, 'SQL'); -- 返回'Hello SQL'
-- 查找字符串位置
SELECT CHARINDEX('o', 'Hello World'); -- 返回5
SELECT CHARINDEX('o', 'Hello World', 6); -- 从第6位开始查找,返回8
-- 补位操作
SELECT RIGHT('0000000000' + '123', 10); -- 返回'0000000123'
SELECT FORMAT(123, '0000000000'); -- 2012及以上版本支持
-- 拆分字符串(2016及以上版本)
SELECT value FROM STRING_SPLIT('a,b,c', ',');
-- 字符串聚合(2017及以上版本)
SELECT STRING_AGG(name, ', ') FROM employees;
SELECT STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY name) FROM employees;JSON Support
JSON支持
sql
-- JSON functions (2016+)
DECLARE @json NVARCHAR(MAX) = '{"name":"John","age":30,"address":{"city":"NYC"}}';
-- Extract values
SELECT JSON_VALUE(@json, '$.name'); -- 'John'
SELECT JSON_VALUE(@json, '$.address.city'); -- 'NYC'
SELECT JSON_QUERY(@json, '$.address'); -- '{"city":"NYC"}'
-- Check if valid JSON
SELECT ISJSON(@json); -- 1
-- Modify JSON
SELECT JSON_MODIFY(@json, '$.age', 31);
SELECT JSON_MODIFY(@json, '$.email', 'john@example.com');
-- Parse JSON array
DECLARE @arr NVARCHAR(MAX) = '[{"id":1,"name":"A"},{"id":2,"name":"B"}]';
SELECT * FROM OPENJSON(@arr) WITH (id INT, name NVARCHAR(50));
-- Generate JSON
SELECT id, name, email
FROM employees
FOR JSON AUTO; -- Auto-structure
SELECT id, name, email
FROM employees
FOR JSON PATH, ROOT('employees'); -- Custom structuresql
-- JSON函数(2016及以上版本)
DECLARE @json NVARCHAR(MAX) = '{"name":"John","age":30,"address":{"city":"NYC"}}';
-- 提取JSON值
SELECT JSON_VALUE(@json, '$.name'); -- 返回'John'
SELECT JSON_VALUE(@json, '$.address.city'); -- 返回'NYC'
SELECT JSON_QUERY(@json, '$.address'); -- 返回'{"city":"NYC"}'
-- 检查是否为有效JSON
SELECT ISJSON(@json); -- 有效返回1
-- 修改JSON
SELECT JSON_MODIFY(@json, '$.age', 31);
SELECT JSON_MODIFY(@json, '$.email', 'john@example.com');
-- 解析JSON数组
DECLARE @arr NVARCHAR(MAX) = '[{"id":1,"name":"A"},{"id":2,"name":"B"}]';
SELECT * FROM OPENJSON(@arr) WITH (id INT, name NVARCHAR(50));
-- 生成JSON
SELECT id, name, email
FROM employees
FOR JSON AUTO; -- 自动生成结构
SELECT id, name, email
FROM employees
FOR JSON PATH, ROOT('employees'); -- 自定义结构Index Types
索引类型
sql
-- Clustered index (one per table, defines physical order)
CREATE CLUSTERED INDEX IX_emp_id ON employees(id);
-- Non-clustered index
CREATE NONCLUSTERED INDEX IX_emp_email ON employees(email);
-- Unique index
CREATE UNIQUE INDEX IX_emp_email ON employees(email);
-- Composite index
CREATE INDEX IX_emp_dept_name ON employees(department_id, last_name);
-- Included columns (covering index)
CREATE INDEX IX_emp_email ON employees(email)
INCLUDE (first_name, last_name, phone);
-- Filtered index
CREATE INDEX IX_active_emp ON employees(email)
WHERE is_active = 1;
-- Columnstore index (analytics)
CREATE COLUMNSTORE INDEX IX_sales_cs ON sales(product_id, amount, sale_date);
-- Or clustered columnstore
CREATE CLUSTERED COLUMNSTORE INDEX IX_sales_ccs ON sales;
-- Full-text index
CREATE FULLTEXT CATALOG ft_catalog;
CREATE FULLTEXT INDEX ON documents(content) KEY INDEX PK_documents;sql
-- 聚集索引(每个表仅一个,定义物理存储顺序)
CREATE CLUSTERED INDEX IX_emp_id ON employees(id);
-- 非聚集索引
CREATE NONCLUSTERED INDEX IX_emp_email ON employees(email);
-- 唯一索引
CREATE UNIQUE INDEX IX_emp_email ON employees(email);
-- 复合索引
CREATE INDEX IX_emp_dept_name ON employees(department_id, last_name);
-- 包含列索引(覆盖索引)
CREATE INDEX IX_emp_email ON employees(email)
INCLUDE (first_name, last_name, phone);
-- 筛选索引
CREATE INDEX IX_active_emp ON employees(email)
WHERE is_active = 1;
-- 列存储索引(用于分析场景)
CREATE COLUMNSTORE INDEX IX_sales_cs ON sales(product_id, amount, sale_date);
-- 或聚集列存储索引
CREATE CLUSTERED COLUMNSTORE INDEX IX_sales_ccs ON sales;
-- 全文索引
CREATE FULLTEXT CATALOG ft_catalog;
CREATE FULLTEXT INDEX ON documents(content) KEY INDEX PK_documents;Table Partitioning
表分区
sql
-- 1. Create partition function
CREATE PARTITION FUNCTION pf_sales_date (DATE)
AS RANGE RIGHT FOR VALUES ('2022-01-01', '2023-01-01', '2024-01-01');
-- 2. Create partition scheme
CREATE PARTITION SCHEME ps_sales_date
AS PARTITION pf_sales_date
TO (fg_2021, fg_2022, fg_2023, fg_2024);
-- 3. Create partitioned table
CREATE TABLE sales (
id INT IDENTITY(1,1),
sale_date DATE,
amount DECIMAL(10,2),
CONSTRAINT PK_sales PRIMARY KEY (id, sale_date)
) ON ps_sales_date(sale_date);
-- View partitions
SELECT
$PARTITION.pf_sales_date(sale_date) AS partition_number,
COUNT(*) AS row_count
FROM sales
GROUP BY $PARTITION.pf_sales_date(sale_date);
-- Split partition (add new)
ALTER PARTITION SCHEME ps_sales_date NEXT USED fg_2025;
ALTER PARTITION FUNCTION pf_sales_date() SPLIT RANGE ('2025-01-01');
-- Merge partitions
ALTER PARTITION FUNCTION pf_sales_date() MERGE RANGE ('2022-01-01');
-- Switch partition (instant move)
ALTER TABLE sales SWITCH PARTITION 1 TO sales_archive;sql
-- 1. 创建分区函数
CREATE PARTITION FUNCTION pf_sales_date (DATE)
AS RANGE RIGHT FOR VALUES ('2022-01-01', '2023-01-01', '2024-01-01');
-- 2. 创建分区方案
CREATE PARTITION SCHEME ps_sales_date
AS PARTITION pf_sales_date
TO (fg_2021, fg_2022, fg_2023, fg_2024);
-- 3. 创建分区表
CREATE TABLE sales (
id INT IDENTITY(1,1),
sale_date DATE,
amount DECIMAL(10,2),
CONSTRAINT PK_sales PRIMARY KEY (id, sale_date)
) ON ps_sales_date(sale_date);
-- 查看分区情况
SELECT
$PARTITION.pf_sales_date(sale_date) AS partition_number,
COUNT(*) AS row_count
FROM sales
GROUP BY $PARTITION.pf_sales_date(sale_date);
-- 拆分分区(新增分区)
ALTER PARTITION SCHEME ps_sales_date NEXT USED fg_2025;
ALTER PARTITION FUNCTION pf_sales_date() SPLIT RANGE ('2025-01-01');
-- 合并分区
ALTER PARTITION FUNCTION pf_sales_date() MERGE RANGE ('2022-01-01');
-- 切换分区(快速移动数据)
ALTER TABLE sales SWITCH PARTITION 1 TO sales_archive;Temporal Tables (2016+)
时态表(2016及以上版本)
sql
-- Create temporal table
CREATE TABLE employees (
id INT PRIMARY KEY,
name NVARCHAR(100),
salary DECIMAL(10,2),
-- System time columns
valid_from DATETIME2 GENERATED ALWAYS AS ROW START,
valid_to DATETIME2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (valid_from, valid_to)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.employees_history));
-- Query historical data
SELECT * FROM employees FOR SYSTEM_TIME AS OF '2024-01-01';
SELECT * FROM employees FOR SYSTEM_TIME BETWEEN '2024-01-01' AND '2024-06-01';
SELECT * FROM employees FOR SYSTEM_TIME ALL;
-- Disable versioning for maintenance
ALTER TABLE employees SET (SYSTEM_VERSIONING = OFF);
-- ... maintenance ...
ALTER TABLE employees SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.employees_history));sql
-- 创建时态表
CREATE TABLE employees (
id INT PRIMARY KEY,
name NVARCHAR(100),
salary DECIMAL(10,2),
-- 系统时间列
valid_from DATETIME2 GENERATED ALWAYS AS ROW START,
valid_to DATETIME2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (valid_from, valid_to)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.employees_history));
-- 查询历史数据
SELECT * FROM employees FOR SYSTEM_TIME AS OF '2024-01-01';
SELECT * FROM employees FOR SYSTEM_TIME BETWEEN '2024-01-01' AND '2024-06-01';
SELECT * FROM employees FOR SYSTEM_TIME ALL;
-- 为维护操作禁用版本控制
ALTER TABLE employees SET (SYSTEM_VERSIONING = OFF);
-- ... 执行维护操作 ...
ALTER TABLE employees SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.employees_history));Common Table Expressions
通用表表达式(CTE)
sql
-- Basic CTE
;WITH emp_stats AS (
SELECT department_id, COUNT(*) AS emp_count, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
)
SELECT d.name, es.emp_count, es.avg_salary
FROM departments d
JOIN emp_stats es ON d.id = es.department_id;
-- Recursive CTE
;WITH hierarchy AS (
-- Anchor
SELECT id, name, manager_id, 0 AS level
FROM employees WHERE manager_id IS NULL
UNION ALL
-- Recursive
SELECT e.id, e.name, e.manager_id, h.level + 1
FROM employees e
JOIN hierarchy h ON e.manager_id = h.id
)
SELECT * FROM hierarchy OPTION (MAXRECURSION 100);sql
-- 基础CTE
;WITH emp_stats AS (
SELECT department_id, COUNT(*) AS emp_count, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
)
SELECT d.name, es.emp_count, es.avg_salary
FROM departments d
JOIN emp_stats es ON d.id = es.department_id;
-- 递归CTE
;WITH hierarchy AS (
-- 锚点查询
SELECT id, name, manager_id, 0 AS level
FROM employees WHERE manager_id IS NULL
UNION ALL
-- 递归查询
SELECT e.id, e.name, e.manager_id, h.level + 1
FROM employees e
JOIN hierarchy h ON e.manager_id = h.id
)
SELECT * FROM hierarchy OPTION (MAXRECURSION 100);Pagination
分页查询
sql
-- OFFSET-FETCH (2012+)
SELECT id, name, email
FROM employees
ORDER BY id
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;
-- With variable
DECLARE @PageNum INT = 3, @PageSize INT = 10;
SELECT id, name, email
FROM employees
ORDER BY id
OFFSET (@PageNum - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
-- ROW_NUMBER (older method)
;WITH numbered AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM employees
)
SELECT * FROM numbered WHERE rn BETWEEN 21 AND 30;sql
-- OFFSET-FETCH方式(2012及以上版本)
SELECT id, name, email
FROM employees
ORDER BY id
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;
-- 结合变量使用
DECLARE @PageNum INT = 3, @PageSize INT = 10;
SELECT id, name, email
FROM employees
ORDER BY id
OFFSET (@PageNum - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
-- ROW_NUMBER方式(旧版本兼容)
;WITH numbered AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM employees
)
SELECT * FROM numbered WHERE rn BETWEEN 21 AND 30;When NOT to Use This Skill
不适用该技能的场景
- T-SQL programming - Use skill for stored procedures, functions, triggers
tsql - PostgreSQL - Use skill for PostgreSQL-specific features
postgresql - Oracle - Use skill for Oracle features
oracle - Basic SQL - Use for ANSI SQL basics
sql-fundamentals
- T-SQL编程 - 存储过程、函数、触发器相关内容请使用技能
tsql - PostgreSQL - PostgreSQL专属功能请使用技能
postgresql - Oracle - Oracle专属功能请使用技能
oracle - 基础SQL - ANSI SQL基础内容请使用技能
sql-fundamentals
Anti-Patterns
反模式
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Not using SET NOCOUNT ON | Network overhead | Add to all stored procedures |
| Using cursors | Slow performance | Use set-based operations |
| Missing clustered index | Heap scans | Add clustered index |
| Not using INCLUDE in indexes | Key lookups | Use covering indexes |
| Using deprecated TEXT/NTEXT | Compatibility issues | Use VARCHAR(MAX)/NVARCHAR(MAX) |
| @@IDENTITY instead of SCOPE_IDENTITY | Wrong identity value | Use SCOPE_IDENTITY() |
| 反模式 | 问题 | 解决方案 |
|---|---|---|
| 未使用SET NOCOUNT ON | 产生网络开销 | 在所有存储过程中添加该语句 |
| 使用游标 | 性能缓慢 | 使用基于集合的操作替代 |
| 缺少聚集索引 | 导致堆表扫描 | 添加聚集索引 |
| 未在索引中使用INCLUDE | 产生键查找 | 使用覆盖索引 |
| 使用已废弃的TEXT/NTEXT类型 | 兼容性问题 | 使用VARCHAR(MAX)/NVARCHAR(MAX)替代 |
| 使用@@IDENTITY而非SCOPE_IDENTITY | 可能获取错误的标识值 | 使用SCOPE_IDENTITY() |
Quick Troubleshooting
快速故障排查
| Problem | Diagnostic | Fix |
|---|---|---|
| Slow queries | | Add indexes, check execution plan |
| Blocking | | Kill blocking process, optimize |
| Deadlocks | Extended Events, trace flag 1222 | Consistent access order, shorter transactions |
| Identity issues | | Reseed or use SCOPE_IDENTITY |
| TempDB contention | Check wait stats | Add TempDB files, optimize queries |
| 问题 | 诊断方法 | 解决方式 |
|---|---|---|
| 查询缓慢 | 执行 | 添加索引,检查执行计划 |
| 阻塞问题 | 使用 | 终止阻塞进程,优化查询 |
| 死锁问题 | 使用扩展事件、跟踪标志1222 | 统一访问顺序,缩短事务时长 |
| 标识列异常 | 执行 | 重置种子或使用SCOPE_IDENTITY |
| TempDB争用 | 检查等待统计信息 | 添加TempDB文件,优化查询 |
Reference Documentation
参考文档
- Data Types
- Indexes
- Partitioning
- 数据类型
- 索引
- 分区