Skip to content

Connect to SQL Server

Engine setup

Connect AskDB to a SQL Server database and introspect it. You write one connection string, run askdb introspect, and fix the error a self-signed certificate causes. Then you connect your own mssql pool to run the SQL AskDB returns.

  • AskDB in your project, with a config for SQL Server. In a new project, npx askdb init --database sqlserver writes askdb.config.ts and installs the mssql driver. To add SQL Server to an existing project, see Switch engines.
  • A SQL Server login that can read the database’s catalog. Introspection only reads, so a read-only login is enough.

AskDB reads a SQL Server connection string in any of three formats:

FormatExample
mssql:// URLmssql://user:pass@localhost:1433/MyDb
Prisma sqlserver://sqlserver://localhost:1433;database=MyDb;user=user;password=pass
ADO.NET (Key=Value;)Server=localhost,1433;Database=MyDb;User Id=user;Password=pass;

Put it in .env as DATABASE_URL. The config that askdb init writes reads it from there:

askdb.config.ts
introspection: {
provider: "sqlserver",
providerConfig: {
sqlserver: {
databaseUrl: env("DATABASE_URL"),
},
},
outputDir: "./askdb",
},

If a value contains ;, wrap it in curly braces, as Prisma does: password={Pass:Word;} is the password Pass:Word;. The @askdb/sqlserver reference has the full rules for braces.

Read the database’s structure:

Terminal window
npx askdb introspect

It prints nothing when it succeeds, and writes askdb/schema.json. To try a connection string without editing .env, pass it for one run: npx askdb introspect --url "<connection string>".

Each table is listed under its SQL Server schema, such as dbo.orders. By default AskDB reads every schema except the system ones (sys, INFORMATION_SCHEMA, guest and the db_* role schemas). To read only some, set introspection.schemas, such as schemas: ["dbo", "sales"].

If introspection fails with self-signed certificate, go to step 3.

SQL Server encrypts connections by default. When the server’s certificate is self-signed, as on many development servers, Node.js rejects it:

Failed to connect to localhost:1433 - self-signed certificate

On Node 24 and newer, the message goes on: ; if the root CA is installed locally, try running Node.js with --use-system-ca.

In development, trust the server’s certificate. Add the option for your format:

# mssql:// URL
mssql://user:pass@localhost:1433/MyDb?trustServerCertificate=true
# Prisma sqlserver://
sqlserver://localhost:1433;database=MyDb;user=user;password=pass;trustServerCertificate=true
# ADO.NET
Server=localhost,1433;Database=MyDb;User Id=user;Password=pass;TrustServerCertificate=True;

In both URL forms, yes and 1 work as well as true; the @askdb/sqlserver README lists every value AskDB reads.

AskDB also reads the key with spaces, Trust Server Certificate=True, which VS Code’s mssql extension writes, but your own mssql pool reads it only without spaces. The SQL Server hint in the .env.example from askdb init leaves the key out, so the certificate is checked by default, and its comment says to add TrustServerCertificate=True; for a development server.

In production, keep the check and give Node.js the certificate authority (CA) that signed the server’s certificate:

Terminal window
NODE_EXTRA_CA_CERTS=/path/to/ca.pem npx askdb introspect

If that CA is already in your operating system’s trust store, tell Node.js to use the store instead:

Terminal window
NODE_OPTIONS=--use-system-ca npx askdb introspect

AskDB returns SQL and never runs it: your app does. The mssql driver reads fewer connection strings than AskDB does:

  • It reads an ADO.NET string or a config object. It doesn’t read mssql:// or sqlserver:// URLs.
  • It reads TrustServerCertificate=True only without spaces. With spaces, it ignores the key, and the certificate error comes back.

A config object avoids both:

import mssql from "mssql";
const pool = await mssql.connect({
server: "localhost",
port: 1433,
database: "MyDb",
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
options: { trustServerCertificate: true }, // development only, as in step 3
});
const { recordset } = await pool.request().query(sql);

To share one DATABASE_URL between AskDB and your pool, write it in ADO.NET form with TrustServerCertificate=True. Both read that form.

Give this pool a read-only login too. Run safely in production covers the database role, timeouts and row limits.