SQLMentor // cheat sheet

SQL Server Cheat Sheet

Every T-SQL pattern you reach for daily, on one page: data types, string/date functions, joins/CTEs, window functions, APPLY operators, MERGE, TRY...CATCH, index types, and isolation levels. Bookmark it, or work through the underlying concepts in the free SQL Server tutorial.

Common data types

TypeStores
INT / BIGINT / SMALLINT / TINYINTwhole numbers of increasing range
DECIMAL(p,s) / NUMERIC(p,s)exact fixed-point numbers
FLOAT / REALapproximate floating-point numbers
VARCHAR(n) / NVARCHAR(n) / CHAR(n)variable/fixed-length strings -- N-prefixed types store Unicode
DATE / TIME / DATETIME2 / DATETIMEOFFSETdate and time values, with or without a time zone offset
BITboolean-like: 0, 1, or NULL
UNIQUEIDENTIFIERa GUID value
VARCHAR(MAX) / NVARCHAR(MAX)large variable-length text, beyond the normal 8000-byte row limit

String functions

FunctionPurposeExample
+concatenation (NULL propagates)first_name + ' ' + last_name
CONCAT(a, b, ...)concatenation, NULL-safeCONCAT('Hi ', name)
LEN(s)character countLEN('sqlserver') -> 9
SUBSTRING(s, start, len)extract a substringSUBSTRING('sqlserver', 1, 3) -> 'sql'
UPPER(s) / LOWER(s)case conversionUPPER('sql') -> 'SQL'
LTRIM(s) / RTRIM(s) / TRIM(s)remove leading/trailing spacesTRIM(' hi ') -> 'hi'
REPLACE(s, old, new)substring replacementREPLACE('2026','20','19') -> '1926'
CHARINDEX(sub, s)1-based position of a substringCHARINDEX('server','sqlserver') -> 4
STRING_AGG(col, sep)concatenate rows into one stringSTRING_AGG(name, ', ')

Date & time functions

FunctionPurposeExample
GETDATE() / SYSDATETIME()current date and timeSELECT GETDATE();
CAST(GETDATE() AS DATE)current date onlySELECT CAST(GETDATE() AS DATE);
DATEDIFF(unit, d1, d2)difference between two dates in a unitDATEDIFF(day, hire_date, GETDATE())
DATEADD(unit, n, date)add/subtract an intervalDATEADD(month, 3, order_date)
DATEPART(unit, date)extract part of a date as an integerDATEPART(year, order_date)
FORMAT(date, fmt)format a date as textFORMAT(GETDATE(), 'yyyy-MM-dd')
EOMONTH(date)last day of the monthEOMONTH(order_date)

Joins & CTEs

PatternSyntax
Inner joinFROM a JOIN b ON a.id = b.id
Left joinFROM a LEFT JOIN b ON a.id = b.id
Full outer joinFROM a FULL OUTER JOIN b ON a.id = b.id
Common table expressionWITH recent AS (SELECT * FROM orders WHERE order_date > DATEADD(day,-7,GETDATE())) SELECT * FROM recent;
Recursive CTEWITH tree AS (base case UNION ALL recursive case) SELECT * FROM tree OPTION (MAXRECURSION 100);

Window functions

FunctionPurpose
ROW_NUMBER() OVER (...)unique sequential number per row
RANK() / DENSE_RANK() OVER (...)rank with / without gaps after ties
LAG(col, n) / LEAD(col, n) OVER (...)value n rows before / after the current row
SUM/AVG/COUNT(...) OVER (PARTITION BY ...)grouped aggregate without collapsing rows
NTILE(n) OVER (...)split rows into n roughly equal buckets

APPLY operators

CROSS APPLY / OUTER APPLY let a subquery on the right reference columns from a table on the left -- SQL Server's equivalent of PostgreSQL's LATERAL join, commonly used for "top N per group".

SELECT d.department_name, top_emp.first_name, top_emp.salary
FROM departments d
CROSS APPLY (
  SELECT TOP 1 first_name, salary
  FROM employees e
  WHERE e.department_id = d.department_id
  ORDER BY salary DESC
) top_emp;

MERGE (upsert)

MERGE INTO inventory AS t
USING (SELECT 'A1' AS sku, 5 AS qty) AS s
ON (t.sku = s.sku)
WHEN MATCHED THEN UPDATE SET t.qty = t.qty + s.qty
WHEN NOT MATCHED THEN INSERT (sku, qty) VALUES (s.sku, s.qty);

TRY...CATCH

SQL Server's structured error handling -- the SQL Server equivalent of PL/SQL's EXCEPTION block.

BEGIN TRY
  UPDATE accounts SET balance = balance - 100 WHERE id = 1;
  IF @@ROWCOUNT = 0 THROW 50000, 'Account not found', 1;
END TRY
BEGIN CATCH
  PRINT ERROR_MESSAGE();
  ROLLBACK;
END CATCH

Stored procedures & triggers

CREATE PROCEDURE give_raise @emp_id INT, @pct DECIMAL(5,2) AS
BEGIN
  UPDATE employees SET salary = salary * (1 + @pct/100) WHERE employee_id = @emp_id;
END;

CREATE TRIGGER trg_salary_audit ON employees
AFTER UPDATE AS
BEGIN
  INSERT INTO salary_audit (employee_id, old_salary, new_salary)
  SELECT i.employee_id, d.salary, i.salary
  FROM inserted i JOIN deleted d ON i.employee_id = d.employee_id;
END;

Index types

IndexBest for
Clustereddefines the physical row order -- one per table
Nonclustereda separate lookup structure pointing back to the table -- many per table
Uniqueenforces uniqueness, clustered or nonclustered
Covering (with INCLUDE)holds every column a query needs, avoiding a key lookup
Columnstorecolumn-oriented storage tuned for large analytical scans
Filteredindexes only a WHERE-filtered subset of rows

Transaction isolation levels

LevelBehaviour
READ UNCOMMITTEDallows dirty reads -- reads uncommitted changes from other transactions
READ COMMITTED (default)each statement sees only data committed before it started
REPEATABLE READprevents non-repeatable reads on rows already read
SERIALIZABLEfully isolated -- also prevents phantom reads
SNAPSHOTeach transaction sees a consistent versioned snapshot, no blocking reads

Handy admin queries

-- currently running queries/sessions
SELECT session_id, status, command, wait_type, blocking_session_id
FROM sys.dm_exec_requests;

-- table size
EXEC sp_spaceused 'employees';

-- kill a stuck session
KILL 55;

Practise what's on this page

Run any query on this page live against a real schema — free, no signup, results in under a second.

Open the SQL editor →

Frequently asked questions

Is this SQL Server cheat sheet free to use?
Yes. Every reference table here, the underlying tutorial, and the free SQL editor are completely free with no sign-up.
What's the difference between CROSS APPLY and CROSS JOIN?
CROSS APPLY lets the right-hand subquery reference columns from the left-hand table, which a plain JOIN can't do — that's what makes it suitable for "top N per group" queries. A CROSS JOIN can't reference the other side's columns at all.
What's the difference between a clustered and nonclustered index?
A clustered index determines the actual physical storage order of the table's rows, so a table can have at most one. A nonclustered index is a separate structure that stores the indexed columns plus a pointer back to the row, and a table can have many.
Can I print or save this cheat sheet?
Yes — it's a normal web page, so your browser's print-to-PDF or bookmark feature works fine. There is no separate download required.
Where can I practise T-SQL?
The SQL Server tutorial covers every topic on this page in depth, and the free in-browser SQL editor lets you run queries live.