Editing Keyless Legacy Tables in DBeaver Without Touching the Schema
When a legacy table has no primary key, DBeaver locks the Data Editor. A virtual unique key fixes that client-side — no ALTER TABLE, no schema privileges required.
11 Dec 2025, 02:28 UTC

The grid is locked, and you can't add a key
You point DBeaver at a vendor-owned legacy table — say legacy.customer_notes — and the Data Editor shows a lock icon. No cell will edit. The table has no primary key, and you have no ALTER privilege, or the vendor's support terms forbid schema changes entirely.
DBeaver refuses to edit for a defensible reason: to save a cell change it must generate an UPDATE that targets exactly one row, and without a key it has no safe way to write the WHERE clause. Rather than guess and touch the wrong rows, it marks the grid read-only.
The fix is client-side. DBeaver lets you declare a virtual unique key — a column or column combination you vouch for as unique — inside its own metadata layer. No DDL is sent to the server. Once the key exists, the Data Editor can address rows deterministically and the grid becomes writable.
Defining a virtual unique key, step by step
Assume customer_notes has columns note_id, customer_code, note_text, and created_at, and that note_id is de facto unique but was never declared as a key. The steps below reflect recent DBeaver Community Edition releases; dialog placement has shifted between versions, so treat this as a map rather than a transcript and verify against your build.
- In the Database Navigator, right-click the table and choose
Edit Table. On connections where you lack DDL rights, the same dialog may appear asView Table— the virtual key options remain available, because nothing is sent to the server. - In the table editor, locate the section for virtual definitions (virtual unique keys, virtual foreign keys, and virtual columns live together there in recent versions).
- Add a virtual unique key on
note_id. - Save the table editor, then reopen the table's Data Editor. The lock icon should be gone and cells should accept edits.
Conceptually, saving an inline edit now produces a statement like:
UPDATE legacy.customer_notes
SET note_text = ?
WHERE note_id = ?;That WHERE clause is only as safe as your uniqueness claim. Before committing to a key, check the candidate with a plain query in the SQL editor — it needs nothing beyond SELECT privileges:
SELECT note_id, COUNT(*)
FROM legacy.customer_notes
GROUP BY note_id
HAVING COUNT(*) > 1;An empty result means note_id is unique in the current data. If no single column qualifies, test a combination the same way:
SELECT customer_code, created_at, COUNT(*)
FROM legacy.customer_notes
GROUP BY customer_code, created_at
HAVING COUNT(*) > 1;A composite virtual key on (customer_code, created_at) is far more defensible than a single non-unique column — but you are vouching for the data, not constraining it. If duplicates appear later, a single cell edit can silently become a bulk update.
Virtual columns and virtual foreign keys: the rest of the toolkit
The same metadata layer hosts two related features that help on exactly these schemas, where cryptic column names and undeclared relationships tend to travel together:
- Virtual columns — display-only additions defined locally. Typical uses are giving an opaque column a readable name or surfacing a computed value, without
ALTER TABLEor a server-side view. - Virtual foreign keys — manually declared relationships that enable navigation between tables, such as jumping from a row to its related rows. This is a navigation aid only; it enforces nothing anywhere.
What a virtual key is not
Every virtual definition lives in DBeaver's local workspace metadata, and that has concrete consequences:
| Aspect | Physical key | DBeaver virtual key |
|---|---|---|
| Where it's stored | Server schema | Local workspace metadata |
| Who sees it | Every client and application | Only this DBeaver workspace |
| Enforces uniqueness | Yes — server rejects duplicates | No — you vouch for the data |
| Requires ALTER privilege | Yes | No |
| Unlocks Data Editor editing | Yes | Yes |
Note the boundary of what a virtual key fixes: it removes the client-side "no key" blocker. It does not grant write access. If your database user lacks UPDATE/DELETE on the table, or the connection itself is configured read-only, the grid stays locked for a different reason — check your grants before blaming the missing key.
Removing a virtual key is a local edit in the same table editor dialog. Nothing on the server changes at any point in this workflow, so there is no schema rollback to plan for.
Verify before you trust it
Because a virtual key is an assertion about data rather than a constraint on it, verify the setup end to end:
- Before defining the key, open the table in the Data Editor and confirm the read-only lock — this establishes the missing key as the cause.
- Run the
GROUP BY ... HAVINGcheck on your chosen key columns. - After defining the key, enable statement preview or confirmation in Preferences under the data editor settings (the exact label varies by version) so you can inspect each generated statement before it commits.
- Edit one low-risk cell, read the generated
UPDATE, and confirm theWHEREclause matches exactly one row before saving.
Then document what you defined and why. Teammates connecting with their own workspaces will not inherit your virtual keys, and a future duplicate in the data can quietly invalidate your uniqueness claim. A short note — which table, which columns, when the check last ran — keeps a client-side convenience from turning into a silent data hazard.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.