A DuckDB extension for connecting to Microsoft SQL Server databases using native TDS protocol - no ODBC, JDBC, or external drivers required.
π Interactive chart β queried live in your browser with DuckDB-Wasm.
Regenerated weekly and served from GitHub Pages, so it stays current without a commit. Counts are a Cloudflare estimate of
INSTALL mssql FROM communityevents, aggregated across DuckDB versions and platforms. Source: DuckDB Community Extensions download metrics.
Experimental: This extension is under active development. APIs and behavior may change between releases. We welcome contributions, bug reports, and testing feedback!
Full documentation lives at hugr-lab.github.io/mssql-extension β connections and authentication (SQL, Azure AD / Entra ID, Kerberos, Windows SSPI), catalog integration, query pushdown, bulk loading over BCP, DML, transactions, the complete settings reference, and performance tuning.
Quick pointers:
| Getting Started | install, ATTACH, first queries |
| Connections & Auth | connection strings, secrets, Azure AD, Kerberos |
| Writing Data | COPY (bulk load), CTAS, INSERT/UPDATE/DELETE |
| Settings Reference | every mssql_* setting with defaults |
| Troubleshooting | common errors and limitations |
| Articles | Medium deep dives on design and performance |
Contributor docs stay in the repository: DATAMODEL.md (layered architecture), docs/ (internals), docs/TESTING.md, CLAUDE.md (development guidelines).
- Native TDS protocol implementation (no external dependencies)
- Stream query results directly into DuckDB without buffering
- Full DuckDB catalog integration with three-part naming and lazy metadata loading
- Filter pushdown:
WHEREclauses are translated to T-SQL and evaluated by SQL Server, including mapped functions (year,lower,LIKEpatterns, arithmetic). Anything the translator declines is applied locally instead β with the string-comparison caveat below - Remote pushdown (on by default): a SELECT over one attached database with a join, an aggregate,
DISTINCT,ORDER BYorLIMITβ joins, aggregates,GROUP BY/HAVING, window functions andQUALIFY, subqueries, CTEs,ORDER BY/LIMITβ runs on SQL Server as one T-SQL statement, so only its result crosses the wire;EXPLAINshows the T-SQL. What has no exact T-SQL form stays in DuckDB. StringGROUP BY/DISTINCT/ join keys then follow the column's collation β see the note below - Row-count estimates reported to the DuckDB optimizer, so join order around an MSSQL scan is planned rather than guessed
- Row identity (
rowid) for tables with a primary key or a usable unique index, which is whatUPDATE/DELETEtarget rows by - Connection pooling with configurable limits and automatic session reset
- TLS with the server certificate verified by default;
Encrypt,TrustServerCertificateandHostNameInCertificatemean what they mean in the Microsoft drivers - Full DML support: INSERT (with RETURNING), UPDATE, DELETE β every statement atomic; an INSERT above 1000 rows loads through the BCP protocol
- CREATE TABLE AS SELECT (CTAS) with streaming and type mapping
- High-performance COPY TO via TDS BulkLoadBCP protocol
- Transaction support: BEGIN/COMMIT/ROLLBACK with connection pinning
- Multi-statement SQL batches via
mssql_scan()(e.g., temp table workflows) - DuckDB secret management for secure credential storage
- Azure AD authentication (service principal, CLI, interactive device code flow)
- Kerberos / Windows SSPI integrated authentication β POSIX (
kinit/ keytab / raw credentials) and Windows (current logon session viasecur32.dll) - Custom
Application Namepropagated to SQL ServerAPP_NAME()/sys.dm_exec_sessions.program_name - ATTACH-time credential validation (opt-out via
lazy_validation true) - Experimental: ORDER BY pushdown to SQL Server (opt-in via
mssql_order_pushdownsetting)
A note on string comparisons. A pushed predicate is evaluated by SQL Server, so it follows the column's collation, not DuckDB's byte comparison: on a case-insensitive collation
WHERE name = 'abc'matches'ABC'β the same answer SSMS gives. With remote pushdown (on by default) the same holds forGROUP BY,DISTINCT,count(DISTINCT β¦), join keys,PARTITION BYand a nestedUNION's deduplication, which used to run in DuckDB: onSQL_Latin1_General_CP1_CI_AS, SQL Server's installation default,'a'and'A'are one group.SET mssql_remote_pushdown = false;beforeATTACH, or the ATTACH optionremote_pushdown false, keeps DuckDB's equality for those. The predicate rule applies toUPDATEandDELETEtoo, where it changes which rows are modified. It also means a predicate that pushes and the same predicate evaluated locally can disagree on a case-insensitive column (#272). See Remote Pushdown and String comparisons and collation.
- DuckDB v1.4.1 or later (minimum supported version)
- SQL Server 2019 or later accessible on network
INSTALL mssql FROM community;
LOAD mssql;CREATE SECRET my_sqlserver (
TYPE mssql,
host 'localhost',
port 1433,
database 'master',
user 'sa',
password 'YourPassword123',
trust_server_certificate true -- a self-signed certificate (the docker image); drop it for a trusted one
);
ATTACH '' AS sqlserver (TYPE mssql, SECRET my_sqlserver);ATTACH 'Server=localhost,1433;Database=master;User Id=sa;Password=YourPassword123;TrustServerCertificate=yes'
AS sqlserver (TYPE mssql);-- List schemas
SELECT schema_name FROM duckdb_schemas() WHERE database_name = 'sqlserver';
-- List tables in dbo schema
SELECT table_name FROM duckdb_tables() WHERE database_name = 'sqlserver' AND schema_name = 'dbo';
-- Query a table
FROM sqlserver.dbo.my_table LIMIT 10;DETACH sqlserver;
DROP SECRET my_sqlserver;MSSQL Extension is an open-source DuckDB extension maintained in spare time.
If it helps you or your organization, consider sponsoring its development through GitHub Sponsors.
Your support helps fund maintenance, bug fixes, testing, and new features.
Issues and pull requests are welcome. Build and test instructions: Development Β· docs/TESTING.md.
The hugr-lab/mssql-extension release binaries statically link the following third-party components:
- OpenSSL (TLS / cryptography), licensed under the Apache
License, Version 2.0. Β© The OpenSSL Project Authors and
contributors. Version pinned via
vcpkg.json. License text: LICENSES/openssl-LICENSE.txt - The simdutf library (Unicode transcoding via SIMD), used under the MIT License option of its dual Apache-2.0/MIT licensing. Β© Daniel Lemire and simdutf contributors. License text: LICENSES/simdutf-LICENSE-MIT.txt
This project is licensed under the MIT License. See the LICENSE file for details.