| name | sqlserver |
| description | | Use when this capability is needed. |
SQL Server Core Knowledge
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: sqlserver for comprehensive documentation.
Data Types
Numeric Types
| Type | Description | Range |
|---|
BIT | Boolean (0/1) | 0, 1, NULL |
TINYINT | 1 byte integer | 0 to 255 |
SMALLINT | 2 byte integer | -32,768 to 32,767 |
INT | 4 byte integer | -2^31 to 2^31-1 |
BIGINT | 8 byte integer | -2^63 to 2^63-1 |
DECIMAL(p,s) | Fixed precision | p: 1-38 digits |
NUMERIC(p,s) | Same as DECIMAL | p: 1-38 digits |
FLOAT | 8 byte float | ~15 digits precision |
REAL | 4 byte float | ~7 digits precision |
MONEY | 8 byte currency | ±922 trillion |
SMALLMONEY | 4 byte currency | ±214,748 |
String Types
| Type | Description | Max Size |
|---|
CHAR(n) | Fixed-length | 8,000 bytes |
VARCHAR(n) | Variable-length | 8,000 bytes |
VARCHAR(MAX) | Large variable | 2 GB |
NCHAR(n) | Unicode fixed | 4,000 chars |
NVARCHAR(n) | Unicode variable | 4,000 chars |
NVARCHAR(MAX) | Unicode large | 1 GB |
TEXT | Legacy large (deprecated) | 2 GB |
NTEXT | Legacy Unicode (deprecated) | 1 GB |
Date/Time Types
| Type | Description | Range |
|---|
DATE | Date only | 0001-01-01 to 9999-12-31 |
TIME(n) | Time only (n=0-7 precision) | 00:00:00 to 23:59:59 |
DATETIME | Date + time | 1753-01-01 to 9999-12-31 |
DATETIME2(n) | Extended datetime | 0001-01-01 to 9999-12-31 |
DATETIMEOFFSET(n) | With timezone | Same + timezone |
SMALLDATETIME | Less precision | 1900-01-01 to 2079-06-06 |
Other Types
| Type | Description |
|---|
UNIQUEIDENTIFIER | 16-byte GUID |
BINARY(n) | Fixed binary |
VARBINARY(n) | Variable binary |
VARBINARY(MAX) | Large binary (2 GB) |
XML | XML data |
JSON | JSON (stored as NVARCHAR) |
GEOGRAPHY | Spatial data |
GEOMETRY | Geometric data |
HIERARCHYID | Hierarchy position |
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),
document VARBINARY(MAX)
);
Identity Columns
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+)
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
SELECT GETDATE();
SELECT SYSDATETIME();
SELECT GETUTCDATE();
SELECT SYSUTCDATETIME();
SELECT SYSDATETIMEOFFSET();
SELECT YEAR(GETDATE());
SELECT MONTH(GETDATE());
SELECT DAY(GETDATE());
SELECT DATEPART(QUARTER, GETDATE());
SELECT DATENAME(WEEKDAY, GETDATE());
SELECT DATEADD(DAY, 7, GETDATE());
SELECT DATEADD(MONTH, -1, GETDATE());
SELECT DATEDIFF(DAY, '2024-01-01', GETDATE());
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);
PARSE( );
DATEADD(, DATEDIFF(, , GETDATE()), );
EOMONTH(GETDATE());
String Functions
SELECT 'Hello' + ' ' + 'World';
SELECT CONCAT('Hello', ' ', 'World');
SELECT CONCAT_WS(' ', 'Hello', 'World', NULL);
SELECT SUBSTRING('Hello World', 1, 5);
SELECT LEFT('Hello World', 5);
SELECT RIGHT('Hello World', 5);
SELECT LEN('Hello');
SELECT DATALENGTH('Hello');
SELECT UPPER('hello');
SELECT LOWER('HELLO');
SELECT TRIM(' hello ');
SELECT LTRIM(' hello');
SELECT RTRIM();
( );
REPLACE(, , );
STUFF(, , , );
CHARINDEX(, );
CHARINDEX(, , );
( , );
FORMAT(, );
STRING_SPLIT(, );
STRING_AGG(name, ) employees;
STRING_AGG(name, ) ( name) employees;
JSON Support
DECLARE @json NVARCHAR(MAX) = '{"name":"John","age":30,"address":{"city":"NYC"}}';
SELECT JSON_VALUE(@json, '$.name');
SELECT JSON_VALUE(@json, '$.address.city');
SELECT JSON_QUERY(@json, '$.address');
SELECT ISJSON(@json);
SELECT JSON_MODIFY(@json, '$.age', 31);
SELECT JSON_MODIFY(@json, '$.email', 'john@example.com');
DECLARE @arr NVARCHAR(MAX) = '[{"id":1,"name":"A"},{"id":2,"name":"B"}]';
SELECT * FROM OPENJSON(@arr) WITH (id INT, name NVARCHAR(50));
SELECT id, name, email
FROM employees
FOR JSON AUTO;
id, name, email
employees
JSON PATH, ROOT();
Index Types
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
CREATE PARTITION FUNCTION pf_sales_date (DATE)
AS RANGE RIGHT FOR VALUES ('2022-01-01', '2023-01-01', '2024-01-01');
CREATE PARTITION SCHEME ps_sales_date
AS PARTITION pf_sales_date
TO (fg_2021, fg_2022, fg_2023, fg_2024);
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');
pf_sales_date() ();
sales SWITCH sales_archive;
Temporal Tables (2016+)
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 (SYSTEM_VERSIONING (HISTORY_TABLE dbo.employees_history));
Common Table Expressions
;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;
;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
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;
;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
tsql skill for stored procedures, functions, triggers
- PostgreSQL - Use
postgresql skill for PostgreSQL-specific features
- Oracle - Use
oracle skill for Oracle features
- Basic SQL - Use
sql-fundamentals for ANSI SQL basics
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() |
Quick Troubleshooting
| Problem | Diagnostic | Fix |
|---|
| Slow queries | SET STATISTICS IO ON | Add indexes, check execution plan |
| Blocking | sp_who2 or Activity Monitor | Kill blocking process, optimize |
| Deadlocks | Extended Events, trace flag 1222 | Consistent access order, shorter transactions |
| Identity issues | DBCC CHECKIDENT | Reseed or use SCOPE_IDENTITY |
| TempDB contention | Check wait stats | Add TempDB files, optimize queries |
Reference Documentation
Source: claude-dev-suite/claude-dev-suite — distributed by TomeVault.