Install
- Install SpDev from the VS Code Marketplace, or search for “SpDev” in VS Code’s Extensions view.
- SpDev needs the .NET 8 runtime or later. Its command-line engine is bundled with the extension.
- You need a development or test database on SQL Server 2016 or later, or Azure SQL Database. SpDev runs your code for real, so don’t point it at production.
SpDev works on Windows, macOS and Linux, with SQL Server on any of them, including SQL Server in Docker.
Debug a stored procedure
- Open a
.sqlfile that containsCREATE PROCEDURE(orCREATE OR ALTER PROCEDURE), or any T-SQL script. - Click Debug above the procedure.
- The first time, enter a connection string. SpDev keeps it in VS Code’s secret storage, per workspace folder. Change it later with SpDev: Set Connection String.
- Enter the parameter values. SpDev asks for each declared parameter and remembers your answers for the file.
The debugger stops on the first statement. Then:
| Key | Action |
|---|---|
F10 |
Step over: run the statement, stop on the next one |
F11 |
Step into: go into a procedure called with EXEC |
Shift+F11 |
Step out: finish this procedure, stop in its caller |
F5 |
Continue to the next breakpoint |
| Step Back | Go back one statement. Reverse Continue goes back to the previous breakpoint |
While stopped:
- The Variables view shows every parameter and variable, including table variables, temp tables, table-valued parameters and
xml. - Values appear inline, next to the code.
- Hover over
*,SELECTor a column name of a statement that has already run to see the rows it returned. PRINToutput and SQL Server messages appear in the Debug Console.- SQL Server errors stop the debugger on the line that raised them, unless a
TRY...CATCHhandles them.
Press F10 on the last statement and SpDev stops once more on END, so you can check the final values and the last result set.
SpDev runs your local file. It doesn’t run the version deployed in the database. It also uses the local .sql files of the procedures you call, so you can change several procedures and debug them together before deploying anything.
How the debugger runs your code
SpDev creates an instrumented copy of the procedure as a temporary procedure (#name), runs it with your parameters, and records the value of every variable before each statement. Then it replays the recording in VS Code. That is why Step Back works, and also why you can’t change a variable’s value while stopped.
The copy is temporary: nothing is created in your database unless the procedure uses user-defined table types or a schema other than dbo. Then SpDev creates a short-lived procedure and drops it afterwards. The spdev.hosting setting controls this.
Debug procedures called by your app
To stop inside a procedure when your .NET application calls it, add the SpDev.Runtime NuGet package to the app.
With EF Core:
builder.Services.AddSpDev(o => o.Enabled = builder.Environment.IsDevelopment());
builder.Services.AddDbContext<AppDb>((sp, o) => o.UseSqlServer(cs).UseSpDev(sp));
With Dapper or ADO.NET:
await using var connection = new SqlConnection(cs).WithSpDev(serviceProvider);
Then run SpDev: Attach to Application in VS Code, set breakpoints in your .sql files and use the app. When it calls a procedure that has a local file, VS Code stops in it.
launch.json
You can also debug from a launch configuration:
{
"type": "spdev",
"request": "launch",
"name": "Debug usp_CustomerStatement",
"program": "${workspaceFolder}/sql/usp_CustomerStatement.sql",
"parameters": { "CustomerId": 42, "Status": "OPEN" }
}
Use null for SQL NULL, and leave a parameter out to use its default.
Profile a procedure (SpDev Pro)
Click Profile above a procedure, or run SpDev: Profile SQL File. SpDev runs the procedure once and shows:
- On each line, the share of the run it took (as a tint) and its cost at the end of the line:
1.24 s (87%) · 48k reads · ×300 · 300 rows. - On hover, the full breakdown: elapsed time, CPU, logical and physical reads, writes, rows, executions, the slowest execution, and what the statement waited on.
- In the Problems view, the findings from the execution plans, each on its line, with a quick fix to copy the suggested
CREATE INDEXor rewrite. - In the report, opened beside the editor: findings, all statements, calls into other procedures, the captured plans, and a comparison with your earlier runs.
Every profile is kept, up to 30 per file. Run SpDev: Compare with an Earlier Profile… to compare any two, or SpDev: Export Profile Report (Markdown) to paste a report into a ticket or pull request.
What the numbers mean
- Time and CPU come from SQL Server’s own counters for your session (
sys.dm_exec_requests), read before each statement. Their resolution is 1 ms per reading, so very short statements read as 0 ms; compare them by reads, or over many executions. - Logical reads are exact and deterministic. They are the best way to tell whether a change helped.
- SpDev’s own cost, a few microseconds per statement, is measured at the start of every run and subtracted.
- A statement’s self cost excludes the procedures it calls; its total includes them.
Permissions
- Reading your own session’s counters needs no extra permission.
- Plan findings need the
SHOWPLANpermission in the database:GRANT SHOWPLAN TO [your_login];. Without it you still get the line-by-line costs, and SpDev tells you what is missing.
Benchmarks
SpDev: Benchmark SQL File… runs the procedure several times, each run rolled back, and reports the median, the 95th percentile and the spread of every statement. Plans are captured on the first run only. Use it when one run is too noisy to decide between two versions.
Sandbox runs
Profile in a Sandbox, Debug in a Sandbox and Run in a Sandbox wrap the run in a transaction and roll it back at the end, so testing doesn’t change your data. A sandbox can’t undo what your code commits or rolls back by itself, and SpDev tells you when that happened.
Coverage
Every debug and profile run records which statements and which branches of each IF ran. Open VS Code’s Test Coverage view to see the procedures that were never fully exercised. SpDev: Reset Procedure Coverage starts over.
Licences
- Trial: run SpDev: Start Free Pro Trial for 14 days of Pro on this machine. No card needed.
- Buy: run SpDev: Buy SpDev Pro, or see pricing.
- Activate: run SpDev: Enter Pro Licence Key and paste the key from your email or the thank-you page.
- Seats: a seat can be active on two machines. Free a seat on the licence page or with SpDev: Deactivate Pro on This Machine.
- Offline: a machine that can’t reach the internet can use an offline licence. Copy the machine id from SpDev: Pro Licence… and send it to us.
SpDev Pro checks its licence about once a day, and keeps working for 14 days without a connection.
Settings
| Setting | Default | What it does |
|---|---|---|
spdev.stopOnEntry |
true |
Stop on the first statement |
spdev.stopOnErrors |
true |
Stop on SQL Server errors that nothing catches |
spdev.traceNestedProcedures |
true |
Use local files for procedures called with EXEC |
spdev.searchDirectories |
[] |
Extra folders to search for .sql files |
spdev.maxSteps |
20000 |
Snapshot limit per procedure call |
spdev.maxResultRows |
500 |
Rows captured per result set |
spdev.hosting |
auto |
temp never writes to the database; database is needed for user-defined types |
spdev.attachPort |
52341 |
Port for Attach to Application |
spdev.sandbox |
false |
Pro: debug and run inside a transaction that is rolled back |
spdev.profiler.capturePlans |
true |
Pro: capture actual plans for findings (needs SHOWPLAN) |
spdev.profiler.heatMetric |
time |
Pro: tint lines by time, cpu or reads |
spdev.profiler.sandbox |
false |
Pro: always profile inside a transaction that is rolled back |
spdev.profiler.openReport |
always |
Pro: when to open the report after a profile |
spdev.pro.coverage |
true |
Pro: record procedure coverage |
Limits
- Dynamic SQL (
EXEC (@sql),sp_executesql) and procedures without a local.sqlfile run normally but aren’t stepped into. Their cost and plans count toward the statement that called them. - Variables can’t be changed while stopped, because the debugger replays a recording.
- Timing has 1 ms resolution per reading. Logical reads are exact.
- Sandbox runs can’t roll back what the code commits itself.
- Supported servers: SQL Server 2016 and later, and Azure SQL Database. SpDev is tested mainly against SQL Server 2022.
Troubleshooting
SpDev doesn’t start a run. Check that the .NET 8 runtime or later is installed (dotnet --list-runtimes in a terminal), then reload VS Code. The SpDev output channel shows the details.
The connection fails with a certificate error. For a local development server, add TrustServerCertificate=true to the connection string.
No plan findings, only costs. The login lacks SHOWPLAN. Run GRANT SHOWPLAN TO [your_login]; in the database.
A called procedure isn’t stepped into. SpDev couldn’t find its .sql file. Add its folder to spdev.searchDirectories; the file must contain CREATE PROCEDURE with the same schema and name.
Something else? Contact support.