skills/sqlserver/SKILL.md
Use when writing T-SQL, editing SQL Server .sql files, using sqlcmd, SQL Server connection strings, stored procedures, execution plans, indexes, Always On, JSON, security, or connector code.
npx skillsauth add cofin/flow sqlserverInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Microsoft SQL Server is a relational database engine spanning on-premises, containers, and Azure SQL. This skill covers T-SQL development, performance tuning, high availability, security, and connectivity across all major languages.
import pyodbc
conn_str = (
"DRIVER={ODBC Driver 18 for SQL Server};"
"SERVER=myserver.database.windows.net,1433;"
"DATABASE=mydb;"
"UID=myuser;PWD=mypassword;"
"Encrypt=yes;TrustServerCertificate=no;"
)
conn = pyodbc.connect(conn_str)
cursor = conn.cursor()
# Always use parameterized queries
cursor.execute("SELECT OrderID, Total FROM Orders WHERE CustomerID = ?", (42,))
rows = cursor.fetchall()
CREATE OR ALTER PROCEDURE dbo.usp_GetCustomerOrders
@CustomerID INT,
@StartDate DATE = NULL, -- optional with default
@TotalCount INT OUTPUT -- output parameter
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
SELECT OrderID, OrderDate, Total
FROM Orders
WHERE CustomerID = @CustomerID
AND (@StartDate IS NULL OR OrderDate >= @StartDate)
ORDER BY OrderDate DESC;
SET @TotalCount = @@ROWCOUNT;
END TRY
BEGIN CATCH
THROW;
END CATCH
END;
GO
-- Clustered index (one per table, defines physical order)
CREATE CLUSTERED INDEX IX_Orders_OrderDate ON Orders(OrderDate);
-- Non-clustered covering index (INCLUDE avoids key lookups)
CREATE NONCLUSTERED INDEX IX_Orders_CustomerID
ON Orders(CustomerID)
INCLUDE (OrderDate, Total);
-- Filtered index (partial index for common queries)
CREATE NONCLUSTERED INDEX IX_Orders_Active
ON Orders(Status)
WHERE Status = 'Active';
-- CTE with window function
WITH RankedOrders AS (
SELECT
CustomerID, OrderID, Total,
ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY Total DESC) AS RowNum
FROM Orders
)
SELECT CustomerID, OrderID, Total
FROM RankedOrders
WHERE RowNum = 1;
-- MERGE upsert
MERGE INTO Inventory AS tgt
USING @Updates AS src ON tgt.ProductID = src.ProductID
WHEN MATCHED THEN UPDATE SET tgt.Qty = src.Qty
WHEN NOT MATCHED THEN INSERT (ProductID, Qty) VALUES (src.ProductID, src.Qty);
-- Offset pagination (2012+)
SELECT OrderID, OrderDate, Total
FROM Orders
ORDER BY OrderDate DESC
OFFSET @PageSize * (@PageNum - 1) ROWS
FETCH NEXT @PageSize ROWS ONLY;
<workflow>
| Need | Go to | Key Concept | | --- | --- | --- | | Write a complex query | tsql_patterns.md | CTEs, window functions, APPLY | | Build a stored procedure | stored_procedures.md | SET NOCOUNT ON, TRY/CATCH | | Query is slow | performance.md | Execution plans, Query Store | | Connect from app code | connections.md | Parameterized queries, drivers | | Work with JSON data | json.md | JSON_VALUE, OPENJSON, FOR JSON | | Lock down access | security.md | RLS, Dynamic Data Masking | | Backup, maintain, monitor | admin.md | DBCC, DMVs, SQL Agent | | HA / DR architecture | availability.md | Always On AG, FCI |
SET NOCOUNT ON to suppress row count messagesTRY/CATCH and THROWINCLUDE columns) to eliminate key lookupsSET STATISTICS XML ON or SSMS Ctrl+M)Run through the validation checkpoint below before considering the work complete.
</workflow> <guardrails>? placeholders in pyodbc, @Param in T-SQL -- never string concatenationTHROW (not RAISERROR) for re-throwingCREATE OR ALTER (2016 SP1+) instead of DROP/CREATE to preserve permissionsOFFSET/FETCH over ROW_NUMBER() for simple pagination (2012+)SELECT * in production queries -- always specify columns explicitlyBefore delivering SQL Server code, verify:
SET NOCOUNT ON as the first statementBEGIN TRY / BEGIN CATCH with THROWINCLUDE columns to cover common query patternsCREATE OR ALTER used instead of DROP/CREATE where supportedTask: "Create a stored procedure to search orders by customer and date range, with a Python caller using parameterized queries."
-- T-SQL: Stored procedure with proper error handling
CREATE OR ALTER PROCEDURE dbo.usp_SearchOrders
@CustomerID INT,
@StartDate DATE = NULL,
@EndDate DATE = NULL,
@PageNum INT = 1,
@PageSize INT = 50
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
SELECT
o.OrderID,
o.OrderDate,
o.Total,
c.CustomerName
FROM Orders o
INNER JOIN Customers c ON c.CustomerID = o.CustomerID
WHERE o.CustomerID = @CustomerID
AND (@StartDate IS NULL OR o.OrderDate >= @StartDate)
AND (@EndDate IS NULL OR o.OrderDate <= @EndDate)
ORDER BY o.OrderDate DESC
OFFSET @PageSize * (@PageNum - 1) ROWS
FETCH NEXT @PageSize ROWS ONLY;
END TRY
BEGIN CATCH
THROW;
END CATCH
END;
GO
# Python: Parameterized call via pyodbc
import pyodbc
conn = pyodbc.connect(
"DRIVER={ODBC Driver 18 for SQL Server};"
"SERVER=myserver,1433;DATABASE=mydb;"
"UID=myuser;PWD=mypassword;"
"Encrypt=yes;TrustServerCertificate=no;"
)
cursor = conn.cursor()
cursor.execute(
"EXEC dbo.usp_SearchOrders @CustomerID=?, @StartDate=?, @PageNum=?, @PageSize=?",
(42, "2025-01-01", 1, 25),
)
for row in cursor.fetchall():
print(row.OrderID, row.OrderDate, row.Total, row.CustomerName)
cursor.close()
conn.close()
</example>
For detailed guides and code examples, refer to the following documents in references/:
testing
Use when syncing Beads state to markdown, checking Flow status, refreshing context docs, validating task markers, or reporting ready/blocked Flow work.
testing
Use when initializing Flow in a repo, configuring .agents, installing or checking Beads bd, setting local-only sync policy, or creating first project context files.
data-ai
Use when drafting PRDs, researching, planning, refining, revising, or creating .agents/specs/<flow_id>/spec.md worksheets for Flow.
testing
Use when implementing Flow tasks from Beads or spec.md, claiming ready work, applying TDD, recording task notes, committing, and syncing after task state changes.