Connect Go to an existing TDS listener
Use go-mssqldb over TLS. Build its URL safely so special characters in credentials are encoded.
Before you run it: Keep certificate validation on. The driver-bound @p1 parameter is not a general T-SQL variable.
Load the invoice sample first. Add the github.com/microsoft/go-mssqldb driver to your Go module. A DSN is the connection address plus settings; net/url encodes its credential fields safely. The four environment variables identify the existing host, database, user and password.
- Load the invoice sampleUse the existing preview listener and test database.
- Build the connection URLUse net/url to encode credentials and keep TLS verification.
- Open and pingCheck connectivity before issuing an application request.
- Run the bound queryPass the value through @p1 and inspect the invoices.
Follow the example
- Confirm the existing preview listener is available.
- Build the DSN with net/url.
- Open the handle and call Ping.
- Run the bound-parameter query.
Run the example
package main
import (
"database/sql"
"fmt"
"net/url"
"os"
_ "github.com/microsoft/go-mssqldb"
)
func dsn() string {
q := url.Values{}
q.Set("database", os.Getenv("OC_DATABASE"))
q.Set("encrypt", "true") // mandatory - the only way in
q.Set("TrustServerCertificate", "false") // validate the chain
q.Set("dial timeout", "30")
u := url.URL{
Scheme: "sqlserver",
// url.UserPassword escapes for you. Never build this by hand.
User: url.UserPassword(os.Getenv("OC_DB_USER"), os.Getenv("OC_DB_PASSWORD")),
Host: os.Getenv("OC_SQL_HOST") + ":1433",
RawQuery: q.Encode(),
}
return u.String()
}
func main() {
db, err := sql.Open("sqlserver", dsn())
if err != nil {
panic(err)
}
defer db.Close()
// sql.Open is lazy. Ping is the first thing that actually connects.
if err := db.Ping(); err != nil {
panic(err)
}
rows, err := db.Query(
"SELECT TOP 5 id, customer_ref, amount_cents"+
" FROM invoices WHERE status = @p1 ORDER BY amount_cents DESC",
"open")
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var id, cents int
var ref string
if err := rows.Scan(&id, &ref, ¢s); err != nil {
panic(err)
}
fmt.Printf("%d %-12s %d\n", id, ref, cents)
}
if err := rows.Err(); err != nil {
panic(err)
}
}Check the result
Ping checks the connection because sql.Open alone may not connect.
4101 ACME-77 129900
4088 ACME-12 98450
4077 ORBIT-3 61000
4051 ACME-77 44900
4020 ORBIT-9 12750Important details
sql.Opendoes not connect. If a listener is missing or a certificate is unloadable you will not learn it untilPingor the first query, so callPingat start-up rather than discovering it inside a request.- This driver names parameters
@p1,@p2, and so on. That is the driver's placeholder syntax and it is fine — it is rewritten to a positional bind before the statement reaches the engine. It is not the same thing as a T-SQL@variable, which is refused. - Leave
TrustServerCertificateatfalse. Turning it on does not make a broken listener work — there is no listener to reach when the certificate is the problem — it only stops you noticing who you are talking to.
Microsoft, SQL Server and T-SQL are trademarks of the Microsoft group of companies; go-mssqldb is Microsoft's own driver. Named here only to describe protocol compatibility and to identify the version it was measured against. OriginChainDB is not affiliated with, endorsed by, or sponsored by Microsoft, and does not distribute Microsoft software.
Recorded driver check: microsoft/go-mssqldb 1.11.0, 21 of 21 checks, on 2026-09-07. This is a historical test record.