LearnThatStack Ace your next interview

SQL Server

Commands for SQL Server 2016+ Checked Oct 2026 103 commands

The model

  • A clustered index stores a table's rows in key order. Nonclustered indexes point to those rows through the clustering key.
  • The optimizer builds a plan from statistics and the first call's values, then reuses it. That's parameter sniffing.
  • COMMIT waits only for the transaction log to reach disk. Under the FULL recovery model, only a log backup frees log space.
  • By default, readers take shared locks and wait for writers. With read committed snapshot (RCSI), they read row versions instead.
Sessiona transactionBuffer poolpages in memoryDisklog and data filesSecondarya standby serverUPDATE changes a pageCOMMIT hardens the logcheckpoint dirty pageslog records replayed
COMMIT waits only for the log to reach disk. A checkpoint later writes the dirty pages, the ones changed in memory. A secondary replays the same log records.

Engine, types & keys

what SQL Server is, and how a table holds its data

What SQL Server is

Say what SQL Server isMicrosoft's relational database. Its SQL dialect is T-SQL.
Name its core componentsThe Database Engine stores the data. SQL Server Agent runs scheduled jobs.
Name its data and reporting servicesSSIS loads data, SSAS builds analysis models, and SSRS makes reports.

Data types

Store money exactlyPrice DECIMAL(10,2)FLOAT is approximate.
Store a date and timeCreatedAt DATETIME2DATETIME rounds to about 3 milliseconds.
Store text in any languageName NVARCHAR(100)Most characters take 2 bytes, where VARCHAR takes 1.
Store long text or a fileNVARCHAR(MAX)VARBINARY(MAX)They replace the deprecated TEXT and IMAGE.

TipFrom 2019, a UTF-8 collation lets VARCHAR hold Unicode. SQL Server 2025 adds a JSON type.

TrapWithout the N in N'...', Unicode literals can lose characters.

Keys, IDENTITY and normal forms

Make a primary keyID INT PRIMARY KEYIt's clustered by default.
Make a foreign key delete child rows tooREFERENCES Departments(ID) ON DELETE CASCADEWithout CASCADE, deleting a parent with children fails.
Number new rows, then read the new IDIDENTITY(1,1)SCOPE_IDENTITY()Avoid @@IDENTITY. A trigger's insert can change it.
Reach third normal form (3NF)Values are atomic, with no partial or transitive dependencies.

TipBoyce-Codd normal form (BCNF) is stricter. Any column that decides another must be a candidate key.

DELETE, TRUNCATE or DROP

Remove the rows a condition matchesDELETE FROM Orders WHERE ID = 1;It logs each row and fires triggers.
Empty the whole table fastTRUNCATE TABLE Orders;It logs only freed pages and resets the identity.
Remove the table, its indexes and triggersDROP TABLE Orders;

TipInside a transaction, ROLLBACK undoes TRUNCATE and DROP too.

TrapTRUNCATE fails on a table that a foreign key references.

Indexes

find rows fast, and fix index fragmentation

Clustered and nonclustered indexes

Name indexName + IDclusteredwhole row
key lookupThe Name index holds ID, the clustering key. A key lookup finds it in the clustered index.
Store the table's rows in key orderCREATE CLUSTERED INDEX cx ON Orders (ID);A table has one at most. Without one, it's a heap.
Index another column you search onCREATE INDEX ix ON Orders (CustomerID);It's nonclustered by default, and it slows every write.
Remove a key lookup with a covering indexINCLUDE (Total)

TipKeep the clustering key narrow. Every other index stores a copy.

TrapKey order is logical, not physical, so pages fragment over time.

Columnstore indexes

Store a large fact table by columnCREATE CLUSTERED COLUMNSTORE INDEXQueries read only the columns they need.
Run reports on a busy OLTP tableNONCLUSTERED COLUMNSTORE

TipColumns compress up to ten times, and batch mode reads many rows at once.

TrapIt suits big scans, not single-row lookups or frequent updates.

Index fragmentation

Measure fragmentation and page densitysys.dm_db_index_physical_stats
Defragment the leaf levelALTER INDEX ALL ON Orders REORGANIZE;It's always online, but leaves statistics alone.
Rebuild the index and its statisticsREBUILD WITH (ONLINE = ON)An offline rebuild blocks the table.

TipThe old rule says reorganize at 5 to 30 percent and rebuild above 30.

TrapA rebuild often helps only because it updates statistics. UPDATE STATISTICS is cheaper.

T-SQL queries

joins, MERGE, CTEs, window functions and temp tables

Joins, UNION and MERGE

Keep only matches, or every row from one sideINNER JOINLEFT JOINFULL OUTER JOINA side with no match comes back as NULL.
Run a function or subquery for each rowCROSS APPLYOUTER APPLYOUTER APPLY keeps rows with no result.
Combine the rows of two queriesUNIONUNION ALLUNION drops duplicates, so it's slower.
Insert or update rows from a sourceMERGE t USING s ON t.ID = s.ID
Delete target rows the source no longer hasWHEN NOT MATCHED BY SOURCE THEN DELETE

TrapConcurrent MERGE upserts need WITH (HOLDLOCK) on the target.

CTEs and window functions

Name a query step for one statementWITH cte AS (...)Each reference runs it again, because it isn't stored.
Let a recursive CTE go past 100 levelsOPTION (MAXRECURSION 0)
Number or rank rows within each groupROW_NUMBER() OVER (PARTITION BY Dept ORDER BY Pay)RANK leaves gaps after ties. DENSE_RANK doesn't.
Keep a running total, row by rowROWS UNBOUNDED PRECEDING

TipThe statement before WITH must end with a semicolon.

TrapThe default frame is RANGE, so tied rows share one total.

Temp tables or table variables

CREATE TABLE #t (ID INT);Hold a large set you join or index again
DECLARE @t TABLE (ID INT);Hold a small set, or one inside a function
CREATE TABLE ##t (ID INT);Share a temp table with every session
yesno

TipBoth live in tempdb. A table variable isn't memory-only.

TrapThe optimizer guesses 1 row for a table variable before 2019.

Procedures & functions

views, procedures, triggers, errors and dynamic SQL

Views, procedures and triggers

Save a query under a nameCREATE VIEW Totals ASIt stores no data.
Store a view's result in an indexed viewWITH SCHEMABINDINGCREATE UNIQUE CLUSTERED INDEX
Run a procedure with an output parameterEXEC dbo.CountOrders 42, @n OUTPUT;Callers need only EXECUTE.
Audit every update to a tableCREATE TRIGGER t ON Orders AFTER UPDATEIt fires once per statement. Join inserted to deleted.
Make a view accept insertsINSTEAD OF INSERTViews allow only this kind.

TipDDL triggers fire on schema changes, and logon triggers as a session starts.

TrapDon't name procedures sp_.... SQL Server checks master first.

Functions or procedures

Return one value per row in a querySELECT dbo.CalcAge(BirthDate)It runs once per row. SQL Server 2019 can inline it.
Return a table from a single SELECTRETURNS TABLE AS RETURNSQL Server optimizes it like a view.
Choose a function or a procedureA function works inside SELECT and can't change data. A procedure can.

TrapA function can't change data or use TRY...CATCH.

Handle errors in T-SQL

SET XACT_ABORT ON;an error rolls back everythingBEGIN TRY BEGIN TRANSACTION; /* writes */ COMMIT;END TRYBEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK; THROW;re-raise the error to the callerEND CATCH
Read the error inside CATCHERROR_NUMBER()ERROR_MESSAGE()Both are NULL outside CATCH.

TipUse THROW, not RAISERROR. Only THROW honors XACT_ABORT.

TrapA CATCH block misses compile errors from its own level.

Dynamic SQL

Run dynamic SQL with typed parametersEXEC sp_executesql @sql, N'@id INT', @id = 7;It reuses one plan, and values can't inject SQL.
Put a table name into dynamic SQLQUOTENAME(@table)Names can't be parameters, so quote them.

TipPlain EXEC compiles each new string and risks injection.

Trapsp_executesql needs an NVARCHAR string.

Locks & isolation

how sessions block each other, and how row versions help

Isolation levels

READ UNCOMMITTEDRead uncommitted changes
READ COMMITTEDUse the default, with no dirty reads
REPEATABLE READKeep the rows you read from changing
SERIALIZABLEAlso block inserts into ranges you read
SNAPSHOTRead data as of the transaction's start
preventedcan happen

TrapNOLOCK is READ UNCOMMITTED. It can read rows that later roll back.

RCSI or SNAPSHOT

WriterUPDATECOMMITLocking RCwaitsreads v2RCSIreads v1reads v2SNAPSHOTreads v1reads v1time

v1 is the row before the UPDATE, v2 after it. A locking READ COMMITTED (RC) reader waits for the COMMIT. RCSI never waits, and SNAPSHOT keeps v1.

Read committed data as of each statementSET READ_COMMITTED_SNAPSHOT ONDefault reads then use row versions.
Read one view of the data for a whole transactionSET ALLOW_SNAPSHOT_ISOLATION ONThen each transaction opts in.

TrapUnder SNAPSHOT, an update conflict fails with error 3960.

Locks, escalation and latches

Name the main lock modesShared (S) for reads, exclusive (X) for writes, update (U) before a change.
Escalate to a partition, not the whole tableSET (LOCK_ESCALATION = AUTO)Escalation starts at 5,000 locks.
Tell a latch from a lockA lock guards data until the transaction ends. A latch guards a page in memory briefly.
Ease inserts that queue on the last page (2019+)OPTIMIZE_FOR_SEQUENTIAL_KEY = ONThe sign is PAGELATCH_EX waits.

TrapEscalation takes one table lock, which can block everyone.

Blocking and deadlocks

Find blocked sessions and who blocks themsys.dm_exec_requestsRead its blocking_session_id column.
Handle being the deadlock victimCatch error 1205 and retry the transaction.
Prevent most deadlocksAccess tables in the same order, and keep transactions short.

TipThe system_health session already records every deadlock graph.

TrapBlocking clears by itself. A deadlock needs SQL Server to roll back a victim.

Tuning & monitoring

find the slow query, see why, and fix its plan

Slow queries and statistics

List the cached queries that cost the mostsys.dm_exec_query_statsSort by reads or CPU.
See reads and CPU time per statementSET STATISTICS IO ON;SET STATISTICS TIME ON;
Compare estimated and actual rowsPress Ctrl+M in SSMS. A big gap means stale statistics or sniffing.
Let an index seek on a filtered columnDon't wrap the column in a function or force a type conversion.
Update a table's statistics yourselfUPDATE STATISTICS Orders WITH FULLSCAN;

TrapSQL Server updates statistics only after enough row changes. New ascending keys fall past the histogram.

Parameter sniffing and hints

Plan for the actual values on every runOPTION (RECOMPILE)Each run compiles again.
Plan for a value you choose, or the averageOPTIMIZE FOR (@id = 7)OPTIMIZE FOR (@id UNKNOWN)A local variable acts like UNKNOWN.
Cache several plans for one query (2022+)Parameter Sensitive Plan optimization, at compatibility level 160.
Force how one table is readWITH (INDEX(ix))WITH (FORCESEEK)

TrapA join hint like INNER HASH JOIN also fixes the join order.

Query Store

Keep each query's plans and run timesSET QUERY_STORE = ONIt's on by default from 2022.
Force the last good planEXEC sp_query_store_force_plan 48, 49;
Add a hint without changing the code (2022+)sys.sp_query_store_set_hints

TrapA forced plan can go stale as the data changes.

Waits, tracing and Resource Governor

See what the server waits on mostsys.dm_os_wait_statsSort by wait_time_ms, and skip idle waits.
Spot slow page reads from diskPAGEIOLATCH_SHLook for scans or slow disks.
Spot slow commitsWRITELOGCheck the log disk.
Trace events with Extended EventsCREATE EVENT SESSION Mon ON SERVERProfiler and SQL Trace are deprecated.
Cap a workload's CPU and memoryCREATE RESOURCE POOL ReportsA classifier function sends sessions to it.

TrapThe wait totals count from the last restart. Compare two snapshots.

tempdb & storage

files, partitions, compression, tempdb and in-memory tables

tempdb

Say what tempdb holdsTemp tables, table variables, sort and hash work, and row versions.
Cut allocation contentionUse one equal-sized file per logical processor, up to eight.
See which kind of data fills ittempdb.sys.dm_db_file_space_usage

TrapIf the shared tempdb fills, the whole workload stops.

Filegroups and partitions

Add a filegroup for old dataADD FILEGROUP ArchiveAdd an .ndf file, then create tables ON Archive.
Shorten backups of old dataMODIFY FILEGROUP Archive READ_ONLYPartial backups then skip it.
Split a table by date with a partition functionRANGE RIGHT FOR VALUES ('2025-01-01')One boundary makes two partitions.
Move a whole partition out in secondsSWITCH PARTITION 1 TO Archive
Empty one partitionTRUNCATE TABLE Sales WITH (PARTITIONS (1));

TipWithout the partition column, a lookup reads every partition.

TrapSWITCH fails unless indexes share the partition scheme.

Compression and in-memory tables

Compress a tableREBUILD WITH (DATA_COMPRESSION = PAGE)Rebuild each nonclustered index too.
Keep a busy table in memoryMEMORY_OPTIMIZED = ONIt needs a memory-optimized filegroup.
Keep only the definition across restartsDURABILITY = SCHEMA_ONLYEvery restart empties the table.

TipCompression trades CPU for I/O. ROW is lighter than PAGE.

TrapMemory-optimized tables must fit in memory.

Backups & high availability

restore to a point in time, and keep a standby copy

Recovery models and bulk loads

Restore to any point in timeSET RECOVERY FULLYou must take log backups.
Let SQL Server reuse log space by itselfSET RECOVERY SIMPLEYou restore only to the end of a backup.
Log bulk loads minimallySET RECOVERY BULK_LOGGEDYou lose point-in-time restore around bulk loads.
Get minimal logging on a loadUse simple or bulk-logged recovery, TABLOCK, and a table that isn't replicated.

TrapUnder FULL, the log keeps growing until a log backup runs.

Back up and restore

fullold logsdifflogtail-log
restore chainRestore the full, the newest diff, each later log, then the tail-log. Skip the old logs.
Take full, differential and log backupsBACKUP DATABASE Sales TO DISK = 'full.bak';WITH DIFFERENTIALBACKUP LOG Sales TO DISK = 'log.trn';You can also back up one file or filegroup.
Take a tail-log backup before a restoreBACKUP LOG Sales TO DISK = 'tail.trn' WITH NORECOVERY;It leaves the database restoring.
Restore a backup and wait for moreRESTORE DATABASE Sales FROM DISK = 'full.bak' WITH NORECOVERY;It overwrites the database.
Stop at a moment and open the databaseWITH STOPAT = '2026-10-20 14:00', RECOVERYUse the same STOPAT on every RESTORE LOG, and RECOVERY on the last.

Always On availability groups

Fail over automatically with no data lossAVAILABILITY_MODE = SYNCHRONOUS_COMMITThe primary waits for the secondary to write the log.
Keep a far-away copy for disaster recoveryAVAILABILITY_MODE = ASYNCHRONOUS_COMMITThe secondary can lag behind.
Fail over to a secondary that lagsFORCE_FAILOVER_ALLOW_DATA_LOSSCommits it never got are lost.

TipThe listener, a DNS name, always points to the primary.

TrapAutomatic failover needs synchronous commit on both replicas.

Log shipping and replication

Copy changes to other servers as they happenTransactional replication. Snapshot sends full copies.
Let several servers change the same dataMerge replication resolves conflicts. Peer-to-peer lets every server write.
Say how log shipping worksAgent jobs back up the log, copy it, and restore it on each secondary.
Let a log shipping secondary serve readsWITH STANDBY = 'undo.tuf'It's read-only between restores.

TrapManual failover loses changes that never shipped.

Security

logins, permissions, row filters and encryption

Logins, permissions and encryption

Let a domain account into one databaseCREATE LOGIN [CORP\Ana] FROM WINDOWS;CREATE USER Ana FOR LOGIN [CORP\Ana];Logins are server-wide. Users belong to one database.
Grant through a role, or block one actionALTER ROLE db_datareader ADD MEMBER Ana;DENY DELETE ON dbo.Orders TO Ana;A DENY overrides a GRANT.
Show each user only their own rowsADD FILTER PREDICATERow-level security, set in a security policy.
Encrypt the data files and backups at restSET ENCRYPTION ONTransparent Data Encryption (TDE).

TrapDynamic data masking only hides values in results. Always Encrypted protects them.

Found this useful? Pass it on.
Pro · $10/mo

This sheet stays free. With Pro, you can:

  • Every answer on this sheet. Read the full answer to all 47 questions it links, not just the 5 free ones.
  • My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
  • PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
  • The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.