Skip to content
| Marketplace
Sign in
Visual Studio Code>Data Science>Jupyter for SQLNew to Visual Studio Code? Get it now.
Jupyter for SQL

Jupyter for SQL

Sujhan Vikramkumar 1

|
3 installs
| (0) | Free
Open any .sql file as a Jupyter-style notebook — run cells, browse schema, export results. Supports Trino, PostgreSQL, MySQL, SQLite and MSSQL. No Python or Jupyter required.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Jupyter for SQL

Run SQL like a notebook — right inside VS Code and Cursor.

Open any .sql file as a Jupyter-style notebook: split queries into cells, run them one at a time, and see results as rich inline tables with sorting, filtering, charts, and one-click export. No Python, no Jupyter, no extra tooling required.

Supports Trino · PostgreSQL · MySQL · SQLite · MSSQL out of the box.


What it looks like

  • SQL cells separated by -- %% markers, each with its own inline result table
  • Cell numbers — [1], [2], [3]… shown in the left gutter after each run, just like Jupyter. Numbers are position-based so they're always stable for referencing
  • Toolbar per result — filter, sort, export to CSV / Excel / clipboard, toggle charts and data bars
  • CodeLens actions above every cell — add a LIMIT, beautify SQL, or open an AI fix prompt with one click
  • Schema sidebar — browse catalogs, schemas, tables, and columns; click a column to insert its name
  • Query history — every execution logged with connection, timing, and row count
  • Cursor-optimised — schema, active cell, and full notebook structure are automatically written to .cursor/rules/ so Cursor AI always knows your tables, columns, and which cell you're editing

Quick Start

1. Install

Search Jupyter for SQL in the VS Code or Cursor Extension Marketplace, or install the .vsix directly.

2. Add a connection

Click the database icon in the activity bar → + → fill in the form.

Passwords are stored in VS Code SecretStorage (your OS keychain). They are never written to settings.json.

Example connections in settings.json (host + non-sensitive fields only):

"sqlNotebook.connections": [
  {
    "name": "Trino Prod",
    "driver": "trino",
    "host": "trino.example.com",
    "port": 443,
    "catalog": "awsdatacatalog",
    "schema": "analysis",
    "user": "me",
    "ssl": true
  },
  {
    "name": "Local Postgres",
    "driver": "postgres",
    "host": "localhost",
    "port": 5432,
    "database": "mydb",
    "user": "postgres"
  },
  {
    "name": "SQLite Dev",
    "driver": "sqlite",
    "database": "/path/to/file.db"
  }
]

3. Open any .sql or .sqlnb file

Both open as notebooks automatically. The active connection is shown in the status bar — click it to switch.

Tip: Use .sqlnb if you want outputs that survive window reloads and Cursor AI edits with zero flicker. Use .sql if you want a clean plain-text file that's easy to commit and diff.


Writing Notebooks

Cell separators — -- %%

-- %% Daily revenue
SELECT DATE(created_at) AS day, SUM(total) AS revenue
FROM orders
WHERE created_at >= CURRENT_DATE - INTERVAL '30' DAY
GROUP BY 1 ORDER BY 1

-- %% Top 10 customers
SELECT customer_id, COUNT(*) AS orders, SUM(total) AS spend
FROM orders
GROUP BY customer_id
ORDER BY spend DESC
LIMIT 10

-- %% [md]
## Analysis notes
Customers with spend > $5,000 qualify for the enterprise tier.

Each -- %% block becomes an independent cell. A -- [md] suffix creates a markdown cell.

Semicolon-delimited files (existing SQL files work too)

SELECT * FROM users LIMIT 10;

SELECT count(*) FROM orders WHERE status = 'PAID';

Variables — -- @var

-- @var schema = analytics
-- @var days   = 30

SELECT *
FROM {{schema}}.events
WHERE event_date >= CURRENT_DATE - INTERVAL '{{days}}' DAY
LIMIT 100

Define once at the top of any cell; reference with {{name}} anywhere in the notebook.

Per-cell connection override

-- @connection Staging Postgres
SELECT * FROM users LIMIT 5

Overrides the active connection for that cell only.


Result Table

Every successful query renders an interactive table with:

Feature Detail
Search Real-time filter across all columns
Sort Click any column header — ascending / descending
Resize Drag column borders to adjust width
Wrap Toggle text wrap for long values
Data bars Proportional blue bars inside numeric cells
Stats tooltip Hover a column header — see row count, nulls %, distinct values, min / max / avg
Row highlight Shift+click any row to pin it for comparison
Pagination Shows 10 rows at a time; "Show N more" to load the rest

Export

Button What it does
CSV Downloads all rows as a .csv file
XLS Downloads as Excel-compatible .xls (SpreadsheetML, preserves number types)
Copy Copies all rows as tab-separated values (TSV) to clipboard — paste directly into Google Sheets, Excel, or Numbers

Charts

Click Chart in the toolbar to toggle a visualisation:

  • Line / area chart — auto-selected when a date, time, or timestamp column is detected on the x-axis. Great for trends over time.
  • Bar chart — used for all other numeric data.

CodeLens Actions

Small action buttons appear above every SQL cell:

CodeLens When shown What it does
⚡ Add LIMIT 100 SELECT without a LIMIT clause Appends LIMIT 100
✨ Beautify Always Formats SQL — uppercases keywords, fixes indentation
🔴 Fix Error After a failed execution Opens Cursor chat pre-filled with your SQL and the full error message
⚡ Optimisation hint Slow queries (>5s) or suspect patterns Opens Cursor chat with a targeted improvement suggestion

Output Persistence (.sqlnb — Jupyter-style)

Save your notebook as .sqlnb instead of .sql to get full Jupyter-style output persistence: results are embedded directly in the file and come back instantly after a window reload or a Cursor AI edit — zero flicker, zero re-running.

myanalysis.sqlnb   ← results embedded in the file, survive everything
myquery.sql        ← clean plain SQL, outputs stored in a session cache

How it works

When you save a .sqlnb file the extension appends a single base64-encoded line at the bottom of the file containing all cell outputs. On the next open, VS Code hands that data directly to the serializer — outputs are restored in the same parse as the SQL cells, before the screen renders. There is no async restore step and no separate sidecar file.

When Cursor AI edits a cell's SQL, the next reload compares the stored SQL against the new SQL. If they differ, an amber "SQL changed — re-run to refresh" stale banner is shown on the preserved output automatically.

When to use each format

.sql .sqlnb
Git-friendly? ✅ Pure SQL diffs ✅ SQL section diffs cleanly
Outputs survive window reload? ✅ Via sidecar cache ✅ Embedded in file
Zero-flicker on Cursor AI edits? ❌ ~100ms async restore ✅ Synchronous
Share just the queries? ✅ Always — use .sql for this

Multi-cell notebook awareness

The extension automatically maintains three live context files in .cursor/rules/:

File What Cursor sees
sql-schema.mdc All tables and columns from your active connection
sql-active-cell.mdc The cell you're currently editing — its SQL, connection, variables, and neighbouring cells
sql-notebook-context.mdc Every cell in the open notebook — index, exact line range, last result shape (column names + row count), and whether the output is current or stale

This means when you ask Cursor "add a join to cell 2 using customer_id from the first result", it already knows which lines to edit, what columns are available from previous results, and what's been run. No copy-pasting output.

Output persistence while Cursor edits

When Cursor AI rewrites a cell's SQL, VS Code normally clears the notebook outputs. This extension preserves them:

  • .sqlnb files — zero flicker. Outputs are embedded in the file and restored synchronously with the cells. Cursor AI edits are detected on reload; changed cells show an amber stale banner automatically.
  • .sql files — outputs are kept in a session-scoped in-memory cache and a sidecar file next to your .sql. A ~100ms async restore runs after each reload.
  • Auto-reload — a file-system watcher (scoped to the exact file path, so it works anywhere on disk) automatically reloads the notebook when Cursor AI writes changes directly to the file. No more manual close-and-reopen.
  • Stale banner — if the SQL changed since last run, the output shows an amber "SQL changed — re-run to refresh" banner rather than disappearing.
  • Session-scoped — the in-memory cache clears when Cursor is closed and reopened.

Fix errors instantly

When a query fails, click 🔴 Fix Error above the cell. Cursor chat opens with your SQL and error pre-loaded — just send the message.

Query optimisation hints

After execution the extension analyses your SQL and timing. If it spots subqueries in IN(), slow runtimes (>5s), or cartesian joins, a hint CodeLens appears. Click it to get an AI-assisted rewrite.


Connection Sidebar

The SQL Notebook panel in the activity bar has two views:

Connections

  • Browse all configured connections, grouped by label (Prod / Staging / Dev)
  • Expand a connection to see schemas → tables → columns
  • Click any column to insert its name at the cursor
  • Right-click a connection: Set Active · Edit · Test · Refresh Schema · Disconnect · Delete

Query History

  • Every execution logged with connection name, timing, row count, and success/fail status
  • Click any entry to open the SQL in an editor for review or re-use
  • Clear all history with the trash icon

Commands

Access via Cmd+Shift+P (macOS) / Ctrl+Shift+P (Windows/Linux):

Command Description
SQL Notebook: Switch Connection Pick the active connection from a quick list
SQL Notebook: Refresh Schema & Cursor Context Re-fetch schema and update .cursor/rules/
Jupyter for SQL: Export All Rows to CSV (unlimited) Re-runs the cell with no row cap and saves to a CSV file

Supported Drivers

All driver packages are bundled lazily — only the one you actually use is loaded. Cold start stays fast regardless of which drivers are installed.

Driver Key Package
Trino trino trino-client
PostgreSQL postgres pg
MySQL / MariaDB mysql mysql2
SQLite sqlite sql.js (WASM — no native deps)
SQL Server mssql mssql

Security

Area How it's handled
Passwords Stored in VS Code SecretStorage (OS keychain). Never written to settings.json or any file that could be committed.
Query results Rendered only inside isolated VS Code notebook output iframes. No data leaves your machine.
Cell output HTML All database values are HTML-escaped before display. JSON embedded in output scripts has </script> sequences escaped to prevent injection.
Variable substitution -- @var values go directly into SQL and are not rendered as HTML — no XSS surface.
Cursor AI context Schema and cell context files are written to .cursor/rules/ in your workspace. Add **/.cursor/rules/sql-*.mdc to .gitignore if working with sensitive schemas.
Connection editor The webview uses a per-render CSP nonce — only the extension's own script can execute. No inline event handlers.

Settings

Setting Default Description
sqlNotebook.connections [] List of database connections
sqlNotebook.activeConnection "" Name of the currently active connection
sqlNotebook.maxRows 100000 Row cap per cell execution. Use Export All Rows to bypass.
sqlNotebook.historyLimit 100 Maximum query history entries to keep

Local Development

git clone https://github.com/sujhan/sql-notebook-multi-driver
cd sql-notebook-multi-driver
npm install
npm run compile          # type-check only (tsc --noEmit)
# Press F5 in VS Code / Cursor to open the Extension Development Host

To build and package:

npx vsce package --no-dependencies    # → jupyter-style-sql-x.y.z.vsix

See DEVELOPMENT.md for a full architecture guide.


Changelog

See CHANGELOG.md for the full version history.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft