SQLAlchemy dialect for SQL Server linked servers (reflection via INFORMATION_SCHEMA)
Project description
linked-sqlserver-dialect
SQLAlchemy dialect for SQL Server linked servers where reflection must use
INFORMATION_SCHEMA (no sp_tables / sp_columns access).
Requirements
- Python >= 3.11
- SQLAlchemy >= 2.0
pyodbc- Microsoft ODBC Driver 17+ for SQL Server
Install
pip install linked-sqlserver-dialect
For local development from a git checkout:
pip install -e .
Usage
Provide linked server metadata via URL query parameters:
from sqlalchemy import create_engine, inspect
engine = create_engine(
"linked_mssql+pyodbc://user:pass@host/db"
"?driver=ODBC+Driver+17+for+SQL+Server"
"&linked_server=MyLinkedServer"
"&database=RemoteDb"
"&schema=dbo"
)
insp = inspect(engine)
print(insp.get_table_names()) # uses INFORMATION_SCHEMA.TABLES
print(insp.get_columns("MyTable")) # uses INFORMATION_SCHEMA.COLUMNS
Note: if you're running from a source checkout without installing the package,
add import linked_sqlserver_dialect once before create_engine(...) so the
dialect gets registered.
Or via connect_args:
engine = create_engine(/.
"linked_mssql+pyodbc://user:pass@host/db?driver=ODBC+Driver+17+for+SQL+Server",
connect_args={"linked_server": "MyLinkedServer", "database": "RemoteDb", "schema": "dbo"},
)
Scope / Limitations (by design)
This first release is intentionally minimal (KISS/YAGNI):
- Tables:
get_table_names() - Columns:
get_columns() - Views:
get_view_names() - No PK/FK/index reflection yet
Primary keys (missing PKs)
Many linked-server scenarios expose tables/views without primary key metadata. SQLAlchemy can still reflect them, but ORM mapping typically needs a primary key.
You can provide primary key overrides in a few ways:
-
URL query param (string format):
pk_overrides=dbo.example_table=id;dbo.other=col1,col2
-
connect_args(dict or string):connect_args={"pk_overrides": {"dbo.example_table": ["id"]}}connect_args={"pk_overrides": "dbo.example_table=id;dbo.other=col1,col2"}
-
Advanced (runtime mutation): if you already created an engine and want to inject overrides programmatically:
engine.dialect._pk_overrides[("dbo", "example_table")] = ["id"]
Smoke test
Run a real end-to-end check against your environment:
export LINKED_MSSQL_URL='linked_mssql+pyodbc://user:pass@host/db?driver=ODBC+Driver+17+for+SQL+Server&linked_server=MyLinkedServer&database=RemoteDb&schema=dbo'
python scripts/smoke_test.py --table MyTable
Local devcontainer + linked-server sandbox (recommended for manual testing)
This repo includes a local-only Docker Compose setup with:
sql1: primary SQL Server (your app connects here)sql2: remote SQL Server (hosts the schema/data)init: seedssql2and creates a linked server onsql1
Start it
From the repo root:
docker compose up -d --build
Run a real reflection check against the sandbox
From your host (uses published port 14331):
export LINKED_MSSQL_URL='linked_mssql+pyodbc://sa:YourStrong(!)Password1@localhost:14331/master?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes&linked_server=LS_REMOTE&database=RemoteDb&schema=dbo'
python scripts/smoke_test.py --table example_table
From inside the devcontainer (service DNS name sql1):
export LINKED_MSSQL_URL='linked_mssql+pyodbc://sa:YourStrong(!)Password1@sql1/master?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes&linked_server=LS_REMOTE&database=RemoteDb&schema=dbo'
python scripts/smoke_test.py --table example_table
Notes / troubleshooting
- If using ODBC Driver 18, encryption is enabled by default;
TrustServerCertificate=yesis the simplest local-dev setting. - On macOS, you can install the Microsoft driver via Homebrew tap:
brew tap microsoft/mssql-releasebrew install microsoft/mssql-release/msodbcsql18 microsoft/mssql-release/mssql-tools18
- Linked server provider support in SQL Server Linux images can vary. If
initfails while runningsp_addlinkedserver, check theinitcontainer logs and we can adjust the provider/options. - Passwords are hard-coded for local dev only. Change them before sharing this setup.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file linked_sqlserver_dialect-0.2.1.tar.gz.
File metadata
- Download URL: linked_sqlserver_dialect-0.2.1.tar.gz
- Upload date:
- Size: 10.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c48063fb3fbe6335aaacca3ac146588fe3d7907ba19d487dc0c31062d6fae214
|
|
| MD5 |
c14c89fb48e7cf3671390a2d5607d141
|
|
| BLAKE2b-256 |
6ee3faccf8047c11a6d2682298872f34c6c5c19630240068c876843260aed7c6
|
File details
Details for the file linked_sqlserver_dialect-0.2.1-py3-none-any.whl.
File metadata
- Download URL: linked_sqlserver_dialect-0.2.1-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8011caa9eef2fb5a3f5eda0d8828f2feb5eb8b5435046c08df286dc6a53cc0c
|
|
| MD5 |
78ab36411fde91c69b99e480121f73a1
|
|
| BLAKE2b-256 |
b94c89b689d1b20bbeb8e84542987fbc4abc93e6834de96971e0a0eafae19cab
|