sql-server

v2026.09.24

SQL Server and Azure SQL Database with T-SQL, indexes, stored procedures, and performance optimization patterns. USE WHEN: user mentions "SQL Server", "T-SQL", "MSSQL", "Azure SQL", "SQL Server indexes", "stored procedures", "SQL Server performance" DO NOT USE FOR: PostgreSQL - use `postgresql`, MySQL - use `mysql`, MongoDB - use `mongodb`

GitHub
Install command
npx skhub add claude-dev-suite/sql-server
Markdown
SKILL.md

SQL Server - Quick Reference

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: aspnet-core for EF Core + SQL Server patterns.

Common T-SQL Patterns

-- 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;

Indexes

-- 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;

Stored Procedures

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;

Performance Tips

TipWhy
Use NVARCHAR over VARCHAR for UnicodeAvoid encoding issues
Add indexes on WHERE/JOIN columnsSpeed up queries
Use SET NOCOUNT ON in proceduresReduce network traffic
Avoid SELECT *Only fetch needed columns
Use parameterized queriesPrevent SQL injection, plan reuse
Use DATETIME2 over DATETIMEBetter precision, smaller storage

Query Performance Analysis

-- 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;

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
SELECT *Wastes I/O, breaks on schema changeList specific columns
Cursors for row-by-rowVery slowUse set-based operations
No indexes on FKsSlow JOINsAdd non-clustered indexes
NOLOCK everywhereDirty readsUse proper isolation levels
String concatenation in SQLSQL injectionUse parameterized queries

Quick Troubleshooting

IssueLikely CauseSolution
Slow queryMissing indexCheck execution plan
DeadlocksConflicting locksCheck sys.dm_tran_locks
TimeoutLong-running queryOptimize or increase timeout
Truncation errorColumn too smallCheck NVARCHAR length
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/databases/sql-server

Default branch

main

Latest commit

9496306

Tree SHA

fe4e2f1