关于 sql-server
面向 SQL Server 开发者的 T-SQL 速查技能,提供表结构、索引、存储过程、查询性能分析和故障排查示例。
主要功能
- 01T-SQL 表与结构模式
- 02聚集与非聚集索引
- 03存储过程示例
- 04查询性能分析
- 05SQL 反模式指导
适用场景
- 01创建 SQL Server 表和索引
- 02排查慢查询执行
- 03避免注入与锁定问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill sql-server安装后在 Claude Code 中输入/sql-server确认已加载。
详细介绍
SQL Server - 快速参考
深入了解:使用
mcp__documentation__fetch_docs并将技术指定为:aspnet-core,了解 EF Core + SQL Server 模式。
常见 T-SQL 模式
-- Table creation
CREATE TABLE Users (
Id INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(100) NOT NULL,
Email NVARCHAR(255) NOT NULL UNIQUE,
CreatedAt DATETIME2 DEFAULT GETUTCDATE(),
UpdatedAt DATETIME2 NULL,
IsActive BIT DEFAULT 1
);
-- Pagination (SQL Server 2012+)
SELECT * FROM Users
ORDER BY Name
OFFSET @Skip ROWS
FETCH NEXT @Take ROWS ONLY;
-- MERGE (upsert)
MERGE INTO Users AS target
USING (SELECT @Email AS Email, @Name AS Name) AS source
ON target.Email = source.Email
WHEN MATCHED THEN
UPDATE SET Name = source.Name, UpdatedAt = GETUTCDATE()
WHEN NOT MATCHED THEN
INSERT (Name, Email) VALUES (source.Name, source.Email);
-- CTE (Common Table Expression)
WITH ActiveUsers AS (
SELECT Id, Name, ROW_NUMBER() OVER (ORDER BY CreatedAt DESC) AS RowNum
FROM Users WHERE IsActive = 1
)
SELECT * FROM ActiveUsers WHERE RowNum BETWEEN 1 AND 10;
索引
-- Clustered (one per table, usually PK)
CREATE CLUSTERED INDEX IX_Users_Id ON Users(Id);
-- Non-clustered
CREATE NONCLUSTERED INDEX IX_Users_Email ON Users(Email);
-- Covering index (includes extra columns)
CREATE NONCLUSTERED INDEX IX_Users_Email_Include
ON Users(Email) INCLUDE (Name, CreatedAt);
-- Filtered index
CREATE NONCLUSTERED INDEX IX_Users_Active
ON Users(Email) WHERE IsActive = 1;
-- Check missing indexes
SELECT * FROM sys.dm_db_missing_index_details;
存储过程
CREATE PROCEDURE sp_GetUsersByStatus
@IsActive BIT,
@PageSize INT = 10,
@PageNumber INT = 1
AS
BEGIN
SET NOCOUNT ON;
SELECT Id, Name, Email, CreatedAt
FROM Users
WHERE IsActive = @IsActive
ORDER BY Name
OFFSET (@PageNumber - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
END;
性能提示
| 提示 | 原因 |
|---|---|
使用 NVARCHAR,而非 VARCHAR,以支持 Unicode | 避免编码问题 |
| 在 WHERE/JOIN 列上添加索引 | 加快查询速度 |
在存储过程中使用 SET NOCOUNT ON | 减少网络流量 |
避免使用 SELECT * | 只获取所需列 |
| 使用参数化查询 | 防止 SQL 注入,并复用执行计划 |
使用 DATETIME2,而非 DATETIME | 精度更高,占用空间更小 |
查询性能分析
-- Execution plan
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
-- Run your query
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
-- Expensive queries
SELECT TOP 10
qs.total_elapsed_time / qs.execution_count AS avg_elapsed,
qs.execution_count,
SUBSTRING(qt.text, 1, 200) AS query_text
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
ORDER BY avg_elapsed DESC;
反模式
| 反模式 | 问题所在 | 正确做法 |
|---|---|---|
SELECT * | 浪费 I/O,架构变更时会出错 | 列出具体列 |
| 逐行处理时使用游标 | 速度非常慢 | 使用基于集合的操作 |
| 外键没有索引 | JOIN 速度慢 | 添加非聚集索引 |
到处使用 NOLOCK | 脏读 | 使用适当的隔离级别 |
| 在 SQL 中拼接字符串 | SQL 注入 | 使用参数化查询 |
快速故障排除
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 查询缓慢 | 缺少索引 | 检查执行计划 |
| 死锁 | 锁冲突 | 检查 sys.dm_tran_locks |
| 超时 | 查询运行时间过长 | 优化查询或增加超时时间 |
| 截断错误 | 列容量不足 | 检查 NVARCHAR 长度 |
评论
支持 Markdown