Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>SQLite sidekickNew to Visual Studio Code? Get it now.
SQLite sidekick

SQLite sidekick

PrasertKana

|
2 installs
| (0) | Free
Read-only SQLite database viewer with a spreadsheet-like grid, explorer, SQL history, and Jupyter export
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

SQLite sidekick

A read-only SQLite 3 database viewer for Visual Studio Code.

Open a .sqlite, .sqlite3, or .db3 file normally. .db is offered under Open With rather than claimed outright, because that extension is shared with LevelDB, Access, and others. For a database with any other extension, or none, run PK SQLite: Open File as SQLite Database.

No native dependency, and nothing bundled. The engine is node:sqlite, built into the Node that VS Code already ships, so one platform-neutral package of about 110 KB serves every platform.

Remote files work too. Databases reached over Remote - SSH, WSL, Dev Containers, or Codespaces open the same way, as do those in a virtual workspace such as GitHub Remote Repositories — see Remote and virtual workspaces, which covers where the extension is best installed and the one case where a database can be missing its most recent rows.

Requirements

VS Code built on Node 24 or newer, which is where node:sqlite became available without a command-line flag. On an older build the extension reports this and registers nothing, rather than failing later.

Features

  • Every table and view appears as a workbook-style bottom tab.
  • Explorer panel listing the database, its tables, views, and their columns.
  • SQL suggestions for keywords, types, SQLite's 172 built-in functions, tables, views, and columns, aware of the clause and of FROM aliases.
  • Virtualized rows and columns for large databases.
  • Column names and declared types remain visible while scrolling.
  • Repeating 16-color, color-blind-friendly column palette.
  • REAL columns show one consistent number of decimals so the decimal points line up, without the noise digits binary floating point prints.
  • Integers are exact at any size, including beyond 2^53.
  • BLOB columns are shown as a size and never decoded as text.
  • On-demand data profiles with key statistics, missing and exact unique counts, standard deviation, quartiles, numeric histograms, and categorical top values.
  • Column and row selection, cell copy, Focus Cell, auto-fit, and Excel-style freeze panes.
  • Session SQL editor with Ctrl/Cmd+Enter execution and cancellation, and syntax highlighting for keywords, types, strings, quoted identifiers, numbers, function calls, and comments.
  • One-click Prettify reformats the query into a consistent clause-per-line layout with indented subqueries.
  • A four-layer read-only guard, described below.
  • SQL history remains in memory for the current open-document session.
  • Selected history exports to a Python/JupySQL .ipynb notebook that needs no database driver installed.
  • Active tables and the active SQL query result can be exported as CSV. A query result export reruns the query so the file holds every row, not only the rows shown under the display limit.
  • Open databases reload after external changes, including changes that reach only the write-ahead log.
  • Works on databases held remotely — Remote - SSH, WSL, Dev Containers, Codespaces — and in virtual workspaces, which are read through VS Code rather than off the local disk.

The database, its -wal, and its -journal are never modified.

Read-only, and how

Viewing must never change a database, so the guarantee is enforced four times over rather than once:

  1. The connection is opened read-only. INSERT, CREATE, and DROP fail inside SQLite itself, below any code of ours.
  2. An authorizer allows only reads. This is a security control, not just a correctness one: a read-only SQLite connection can still ATTACH another database and read it, so without this the SQL box would be an arbitrary-file reader. Everything outside a read allowlist is denied, so a future SQLite release cannot introduce a write-capable action that quietly passes.
  3. Defensive mode is on and extension loading is never enabled.
  4. Exactly one statement, and it must return rows. SQLite's prepare() silently ignores anything after the first statement, so a second one is reported rather than dropped.

SELECT, WITH, VALUES, EXPLAIN, and read-only PRAGMA calls are accepted. INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, ATTACH, DETACH, VACUUM, REINDEX, ANALYZE, transaction control, and pragma assignments are all refused.

Row counts

SQLite has no stored row count — count(*) reads every row — so the grid never waits for one. The first page appears immediately and the status bar shows … rows until the count arrives. Above pkSqlite.exactRowCountLimit (five million by default) the count is reported as ≈ N from max(rowid), which is an upper bound that can overcount after deletions; its tooltip says so.

Deep scrolling in a very large table slows down linearly, because SQLite still visits the rows an OFFSET skips.

Freeze panes

Select a cell and click Freeze panes. Everything above and to the left of it stays put while the rest of the grid scrolls, exactly as in Excel — so selecting the cell in row 3, column C pins the first two rows and the first two columns.

The button then reads Unfreeze; clicking it again removes the split. It is also available from the command palette as PK SQLite: Freeze or Unfreeze Panes at Active Cell, which makes it a single keybinding if you want one.

To move a split, unfreeze first and then freeze at the new cell. Selecting the very first cell freezes nothing, since there is nothing above or to its left, and a split always leaves at least one row and one column free, so the grid can never be pinned solid.

Each table remembers its own split, so switching tabs and coming back keeps it.

One difference from Excel: columns you scroll past slide underneath the frozen ones rather than stopping beside them. Freezing the leftmost columns to keep an identifier in view works as expected; freezing many columns and then scrolling far right will hide some behind the frozen block.

Number display

REAL columns are formatted for reading. Every row in a column gets the same number of decimals, so the decimal points line up:

Stored value Shown
1499.95, 20, 3.5 1499.95, 20.00, 3.50
0.30000000000000004 0.3
0.0000012345678 0.000001235

Trailing digits like those in 0.1 + 0.2 are an artifact of binary floating point rather than your data, and are always dropped. Genuine precision beyond that is capped by pkSqlite.maxDecimalDigits, which defaults to 4. A column whose values are too small for the cap widens instead of rounding to zero, and scientific notation is never used.

Integers are never reformatted, at any size. A value beyond 2^53 keeps every digit, in the grid, in the tooltip, on copy, and in CSV.

Formatting is display only. Ctrl/Cmd+C copies the exact stored value, hovering a cell shows it, and CSV export is unaffected.

Types, and values that disagree with them

SQLite is dynamically typed: a declared column type is an affinity, and any row may store any type. Two consequences are visible in the grid.

A column with no declared type, and every computed expression, reports no type at all. The viewer infers one from the first values it loads and marks it with a trailing ? in a dimmed style — INTEGER? is a guess, INTEGER is a declaration.

A column whose values disagree with its declared affinity is legal and is not flagged. Text in a REAL column is simply shown as text.

BLOB columns

A BLOB cell shows ‹BLOB 1,024 bytes› and is never decoded as text.

Blobs of 1 KB or less travel to the viewer whole, so hovering shows a complete x'…' literal and Ctrl/Cmd+C copies one that pastes straight back into a query. Above that, only the first pkSqlite.blobPreviewBytes (32 by default) are sent, the tooltip says they are leading bytes, and copying yields the size label instead of a partial value that would look complete.

CSV export always writes every byte, whatever the size, because it re-reads the value rather than using the copy the grid holds.

Remote and virtual workspaces

The viewer supports databases opened through VS Code Remote - SSH, WSL, Dev Containers, Codespaces, and desktop virtual workspaces such as GitHub Remote Repositories. Install the extension in the location offered by VS Code, then open the database normally or use Open With.

What decides the behavior is whether the extension is running on the same machine as the database:

  • Installed on the remote — with Install in SSH: …, or in the container or Codespace — the database is an ordinary local file and is opened directly. Nothing is copied.
  • Installed locally against a remote workspace, or in a virtual workspace where no file exists anywhere, the extension reads the resource through VS Code and opens a disposable local snapshot instead. The snapshot is refreshed when the source changes and removed when the viewer closes.

Either way the viewer works. Read-only repositories still support viewing, SQL, profiles, and CSV export to a separate writable location. VS Code offers the install location when you open the database; taking the remote one avoids the copy, and with it the caveat below.

A snapshot copies the database and its sidecars, but a write-ahead log is not always readable that way. So a snapshotted database is the one case that can show stale rows: if it has an un-checkpointed -wal, commits made since the last checkpoint may be missing, and the viewer says so once on opening. Where the file is opened directly there is no such limitation — a database another process is actively writing opens fine and shows that writer's committed rows.

Notebook export is the one feature that needs a directly-opened file rather than a snapshot, because the exported notebook has to reopen the database by path, outside VS Code. It is therefore available on a remote host when the extension is installed there, and unavailable in a virtual workspace.

Explorer

Click Explorer in the viewer toolbar to show or hide the tree of the database, its tables, views, and columns. Selecting a table or view opens it in the grid and highlights its bottom tab, so the tree and the tabs stay in step.

The tree is read from SQLite's schema, so expanding a table never scans it, however large it is. Tables and views are grouped separately; relations whose names begin with sqlite_ are internal and hidden.

Click Data profile in the viewer toolbar to show or hide profiling cards for the active table. Profiles are calculated lazily and cached until the database changes. The Query Result tab is also profileable: its successful SELECT is rerun to calculate statistics over the full result rather than only the displayed row limit.

SQLite has no approximate-distinct function, so unique counts are exact — and exact means a full scan per column. Above pkSqlite.exactDistinctLimit (one million rows by default) they are skipped, the card says so, and a Compute anyway link runs them on request. The rest of the profile is unaffected.

SQL and notebook export

Click SQL in the viewer toolbar, enter one read-only query, and select Run or press Ctrl/Cmd+Enter. The editor shows line numbers, and the panel is resized by dragging its bottom edge.

Because SQLite offers no way to interrupt a running statement, Cancel and the pkSqlite.queryTimeoutSeconds timeout stop a query by destroying the thread running it and starting a fresh one. This is safe precisely because nothing is being written, and it cannot disturb the grid, the tabs, or the explorer, which are served by a separate worker.

Suggestions appear as you type and can be requested with Ctrl+Space. What is offered first depends on the clause: relations after FROM and JOIN, columns after SELECT, WHERE, ON, GROUP BY, and ORDER BY, and keywords at the start of a statement. Typing alias. narrows to that relation's columns, and main. lists the database's relations. Use ↑ and ↓ to move, Enter or Tab to accept, and Escape to dismiss; Ctrl/Cmd+Enter still runs the query. Names that need quoting are inserted quoted. Set pkSqlite.sqlSuggestions to false to turn the popup off.

Prettify

Prettify in the SQL panel, Shift+Alt+F in the editor, right-click in the editor, or PK SQLite: Prettify SQL reformats the query in place:

SELECT prefs.purchase_purpose,
  prefs.preference,
  prefs.rating
FROM (
  SELECT b.purchase_purpose,
    p.preference,
    p.rating,
    RANK() OVER (PARTITION BY b.purchase_purpose ORDER BY p.rating DESC) AS rank
  FROM buyers AS b
  JOIN prefs AS p
  ON b.buyer_id = p.buyer_id
) AS prefs
WHERE prefs.rank <= 5
ORDER BY prefs.purchase_purpose,
  prefs.rating DESC;

Each clause starts a line. The first item stays on the clause's line and later items — separated by a comma, or by AND or OR — wrap to one extra level of indentation. A subquery's parentheses open an indent level and its closing parenthesis returns to the clause indent, so ) AS prefs reads as one line. Parentheses holding an expression never break, which keeps a window specification such as OVER (PARTITION BY x ORDER BY y) intact.

Keywords and type names are uppercased. Identifiers, quoted identifiers, string literals, function names, and comments keep the spelling you gave them, and the caret stays with the token it was on.

Right-clicking the SQL editor opens a menu with Prettify SQL and Run SQL alongside Cut, Copy, Paste, and Select All. Each entry shows its keyboard shortcut, which remains available if your platform refuses clipboard access to the viewer.

The History panel records each command, status, duration, and displayed row count until the document closes. Export Notebook creates a JupySQL notebook that reopens the database read-only through a SQLite URI. Python's sqlite3 is in the standard library, so the notebook runs without installing a database driver.

Commands

  • PK SQLite: Toggle Explorer
  • PK SQLite: Toggle SQL Editor
  • PK SQLite: Run SQL
  • PK SQLite: Cancel SQL
  • PK SQLite: Prettify SQL
  • PK SQLite: Show SQL History
  • PK SQLite: Export SQL History as Jupyter Notebook
  • PK SQLite: Clear SQL History
  • PK SQLite: Export Active Table or Query Result as CSV
  • PK SQLite: Auto-fit All Columns
  • PK SQLite: Freeze or Unfreeze Panes at Active Cell
  • PK SQLite: Open File as SQLite Database

Not supported

Editing anything; sorting, filtering, or charting; encrypted databases (SQLCipher, SEE); opening a database over HTTP or an object store; and FTS5 or R*Tree shadow tables presented as first-class relations. Parquet, CSV, and Excel are a different product — see DuckDB sidekick.

Contributing

Building the extension from source, running tests, and packaging a release are covered in DEV.md.

License

MIT

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