SQL Server 在国内互联网公司不多见,但在传统企业和外企是主流选择。微软的技术栈、完善的工具链、企业级支持,让它在大型系统中占有一席之地。
go get -u gorm.io/driver/sqlserver
底层使用 github.com/microsoft/go-mssqldb,这是微软官方维护的 Go 驱动。
package main
import (
"fmt"
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
)
func main() {
dsn := "sqlserver://sa:Password123@localhost:1433?database=master"
db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})
if err != nil {
panic("连接失败")
}
fmt.Println("连接成功")
}
SQL Server 的 DSN 使用 URL 格式:
sqlserver://username:password@host:port?database=dbname
完整参数示例:
sqlserver://sa:Password123@192.168.1.100:1433?database=myapp&encrypt=disable
| 参数 | 说明 | 默认值 |
|---|---|---|
| database | 数据库名 | master |
| encrypt | 是否加密连接 | disable |
| trustservercertificate | 是否信任服务器证书 | false |
| connection+timeout | 连接超时秒数 | 30 |
| dial+timeout | 拨号超时秒数 | 15 |
encrypt
生产环境建议启用加密:
sqlserver://user:pass@host:1433?database=db&encrypt=true
trustservercertificate
开发环境可以跳过证书验证:
encrypt=true&trustservercertificate=true
import "gorm.io/driver/sqlserver"
mssqlConfig := sqlserver.Config{
DSN: dsn,
DefaultStringSize: 256,
DefaultDatetimePrecision: 3,
}
db, err := gorm.Open(&mssqlConfig, &gorm.Config{})
DefaultStringSize
字符串默认长度。SQL Server 的 NVARCHAR 需要指定长度,默认 256。
DefaultDatetimePrecision
时间精度。SQL Server 的 DATETIME2 支持最高 7 位小数秒。
SQL Server 认证
最常用的方式,用户名密码在 DSN 中指定:
dsn := "sqlserver://sa:Password123@localhost:1433?database=myapp"
Windows 认证
使用当前 Windows 用户凭据:
dsn := "sqlserver://localhost:1433?database=myapp&trusted_connection=yes"
需要驱动支持,且只能在 Windows 上运行。
SQL Server 的 Schema 概念和 PostgreSQL 类似:
type User struct {
ID uint
Name string
}
db.Table("myapp.dbo.users").Create(&user)
默认连接到 dbo schema,可以显式指定:
dsn := "sqlserver://sa:Password123@localhost:1433?database=myapp&schema=myschema"
SQL Server 使用 IDENTITY 实现自增:
type User struct {
ID uint `gorm:"primaryKey;autoIncrement"`
Name string
}
生成的 SQL:
CREATE TABLE "users" ("id" INT IDENTITY(1,1), "name" NVARCHAR(256))
指定起始值和步长:
type User struct {
ID uint `gorm:"primaryKey;autoIncrement;autoIncrementIncrement:100"`
}
SQL Server 使用 NEWID() 或 NEWSEQUENTIALID():
import "github.com/google/uuid"
type User struct {
ID uuid.UUID `gorm:"primaryKey;default:NEWID()"`
Name string
}
NEWSEQUENTIALID() 性能更好,适合索引:
ID uuid.UUID `gorm:"primaryKey;default:NEWSEQUENTIALID()"`
SQL Server 有多种时间类型:
| Go 类型 | SQL Server 类型 |
|---|---|
| time.Time | DATETIME |
| time.Time | DATETIME2 |
| time.Time | DATE |
| time.Time | TIME |
GORM 默认使用 DATETIME2,精度更高:
type Event struct {
ID uint
CreatedAt time.Time
DateOnly time.Time `gorm:"type:date"`
}
SQL Server 的字符串类型选择:
| 类型 | 说明 |
|---|---|
| CHAR | 定长,ASCII |
| VARCHAR | 变长,ASCII |
| NCHAR | 定长,Unicode |
| NVARCHAR | 变长,Unicode |
推荐使用 NVARCHAR,支持中文:
type User struct {
Name string `gorm:"type:nvarchar(100)"`
}
SQL Server 的分页语法和 MySQL 不同:
var users []User
db.Offset(10).Limit(10).Find(&users)
GORM 会生成正确的 OFFSET FETCH 语法:
SELECT * FROM "users" ORDER BY "id" OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
注意:SQL Server 要求分页查询必须有 ORDER BY。
sqlDB, _ := db.DB()
sqlDB.SetMaxOpenConns(50)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetConnMaxLifetime(time.Hour)
SQL Server 默认最大连接数较高,但仍需合理配置连接池。
import (
"database/sql"
"gorm.io/driver/sqlserver"
)
func ConnectFromExisting(sqlDB *sql.DB) (*gorm.DB, error) {
return gorm.Open(sqlserver.New(sqlserver.Config{
Conn: sqlDB,
}), &gorm.Config{})
}
登录失败
Login failed for user 'sa'
检查用户名密码,确认 SQL Server 允许 SQL 认证。默认安装可能只允许 Windows 认证。
连接超时
A network-related or instance-specific error occurred
检查:
数据库不存在
Cannot open database "myapp" requested by the login
先创建数据库:
CREATE DATABASE myapp;
证书错误
A connection was successfully established with the server, but then an error occurred during the login process
开发环境可以禁用加密或信任证书:
encrypt=true&trustservercertificate=true
从 MySQL 迁移到 SQL Server,注意这些差异:
| 特性 | MySQL | SQL Server |
|---|---|---|
| 字符串引号 | 单引号或双引号 | 单引号 |
| 标识符引号 | 反引号 ` | 方括号 [] |
| 布尔类型 | TINYINT(1) | BIT |
| 自增 | AUTO_INCREMENT | IDENTITY |
| 字符串连接 | CONCAT() | + |
| 分页 | LIMIT offset, size | OFFSET FETCH |
GORM 会处理大部分差异,原生 SQL 需要适配。
索引优化
SQL Server 的索引功能强大,合理使用:
CREATE INDEX idx_user_name ON users(name);
CREATE CLUSTERED INDEX idx_user_id ON users(id);
存储过程
复杂业务逻辑可以封装成存储过程:
db.Exec("EXEC sp_update_user_stats @user_id = ?", userID)
批量操作
大批量数据用 BULK INSERT:
db.Exec("BULK INSERT users FROM '/data/users.csv'")
SQL Server 在企业级场景有独特优势,但配置和使用习惯和开源数据库有差异。理解这些差异,迁移和开发会更顺畅。下一章看连接池配置。