Перейти к основному содержимому

Microsoft SQL Server — практическая работа и API

Разработчику Аналитику Инженеру

Другие СУБД в этом цикле: SQLite · PostgreSQL · MySQL · SQL — о разделе.

Microsoft SQL Server — серверная реляционная СУБД от Microsoft. Используется в корпоративных системах, BI-сценариях, интеграционных проектах и крупных транзакционных приложениях.


Как работает SQL Server

  • Запускается как сервис (sqlservr).
  • Подключения идут по TDS-протоколу (обычно порт 1433).
  • Данные и логи хранятся в файлах (.mdf, .ndf, .ldf).
  • Поддерживает транзакции, уровни изоляции и блокировки.
  • Есть Always On, репликация и развитые админ-инструменты.
SELECT @@VERSION;
SELECT SERVERPROPERTY('Edition') AS edition, SERVERPROPERTY('ProductVersion') AS version;

Подключение и запуск

SQLCMD

sqlcmd -S localhost -U sa -P "Secret123!" -d app_db

Строка подключения

Server=localhost,1433;Database=app_db;User Id=app_user;Password=secret;Encrypt=True;TrustServerCertificate=True;

Базовая настройка

CREATE LOGIN app_login WITH PASSWORD = 'Secret123!';
CREATE DATABASE app_db;
USE app_db;
CREATE USER app_user FOR LOGIN app_login;
ALTER ROLE db_datareader ADD MEMBER app_user;
ALTER ROLE db_datawriter ADD MEMBER app_user;

Типы данных и синтаксис

Ключевые типы SQL Server:

  • Числовые: tinyint, smallint, int, bigint, decimal, float, real
  • Строковые: char, varchar, nchar, nvarchar, text/ntext (legacy)
  • Дата/время: date, datetime, datetime2, datetimeoffset, time
  • Бинарные: binary, varbinary, varbinary(max)
  • Специальные: uniqueidentifier, xml, sql_variant
CREATE TABLE dbo.Users (
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Email NVARCHAR(320) NOT NULL UNIQUE,
Profile NVARCHAR(MAX) NULL,
CreatedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
);

Возможности SQL Server

  • T-SQL диалект с мощными возможностями администрирования и аналитики
  • Транзакции, savepoints, блокировки и snapshot-изоляция
  • Хранимые процедуры, функции, триггеры
  • CTE, оконные функции, MERGE, OUTPUT
  • JSON-функции (OPENJSON, JSON_VALUE, JSON_QUERY)
  • Columnstore и advanced indexing
  • SQL Agent Jobs, Integration Services, Reporting Services

Доступные и недоступные команды

КатегорияКоманда / конструкцияСтатус в SQL ServerКомментарий
DMLSELECT, INSERT, UPDATE, DELETEДоступноПолная поддержка
DDLCREATE/ALTER/DROPДоступноШирокие возможности
ТранзакцииBEGIN TRAN, COMMIT, ROLLBACK, SAVE TRANДоступноПолный контроль транзакций
ПраваCREATE LOGIN/USER, GRANT, REVOKEДоступноГранулярная модель прав
Server-side логикаPROCEDURE, FUNCTION, TRIGGERДоступноОснова бизнес-логики в БД
UpsertMERGE или паттерн UPDATE + INSERTДоступноИспользуется по контексту
RETURNING как в PostgreSQLНедоступноИспользуют OUTPUT INSERTED/DELETED
LIMITНедоступноИспользуют TOP или OFFSET ... FETCH
ILIKEНедоступноИспользуют collation/LOWER(...) LIKE
Материализованные view как отдельный типЧастичноИспользуют indexed views с ограничениями

Практика SQL в SQL Server

CRUD

CREATE TABLE dbo.Tasks (
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Title NVARCHAR(255) NOT NULL,
Done BIT NOT NULL DEFAULT 0
);

INSERT INTO dbo.Tasks(Title) VALUES (N'Пройти SQL Server');
SELECT Id, Title, Done FROM dbo.Tasks ORDER BY Id;
UPDATE dbo.Tasks SET Done = 1 WHERE Id = 1;
DELETE FROM dbo.Tasks WHERE Id = 1;

Upsert через MERGE

MERGE dbo.Tasks AS target
USING (SELECT 1 AS Id, N'Обновлённая задача' AS Title, CAST(0 AS BIT) AS Done) AS source
ON target.Id = source.Id
WHEN MATCHED THEN
UPDATE SET Title = source.Title, Done = source.Done
WHEN NOT MATCHED THEN
INSERT (Title, Done) VALUES (source.Title, source.Done);

Транзакция

BEGIN TRAN;
INSERT INTO dbo.Tasks(Title) VALUES (N'A');
INSERT INTO dbo.Tasks(Title) VALUES (N'B');
COMMIT TRAN;

Возврат затронутых строк через OUTPUT

INSERT INTO dbo.Tasks(Title)
OUTPUT INSERTED.Id, INSERTED.Title
VALUES (N'C');

Клиенты и инструменты

  • SQL Server Management Studio (SSMS)
  • Azure Data Studio
  • sqlcmd
  • DBeaver
  • DataGrip
  • Visual Studio SQL tools
  • VS Code + MSSQL extension

API по языкам — подключение, CRUD, библиотеки, классы и функции

Как читать блоки API
В каждом блоке указаны библиотека, ключевые классы/типы, основные свойства и методы, затем минимальный рабочий пример подключения и CRUD.


C# — Microsoft.Data.SqlClient

Библиотека

  • Microsoft.Data.SqlClient

Ключевые классы

  • SqlConnection
  • SqlCommand
  • SqlTransaction
  • SqlDataReader
  • SqlParameter

Свойства и методы

  • Open(), BeginTransaction(), Close()
  • CommandText, Parameters.AddWithValue()
  • ExecuteNonQuery(), ExecuteScalar(), ExecuteReader()
  • Read(), GetInt64(), GetString()
using Microsoft.Data.SqlClient;

var cs = "Server=localhost,1433;Database=app_db;User Id=app_user;Password=secret;Encrypt=True;TrustServerCertificate=True;";
await using var conn = new SqlConnection(cs);
await conn.OpenAsync();

await using (var cmd = new SqlCommand("""
IF OBJECT_ID('dbo.Users', 'U') IS NULL
CREATE TABLE dbo.Users(
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(255) NOT NULL
);
""", conn))
{
await cmd.ExecuteNonQueryAsync();
}

await using (var ins = new SqlCommand("INSERT INTO dbo.Users(Name) VALUES (@name)", conn))
{
ins.Parameters.AddWithValue("@name", "Anna");
await ins.ExecuteNonQueryAsync();
}

await using (var sel = new SqlCommand("SELECT Id, Name FROM dbo.Users", conn))
await using (var reader = await sel.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
Console.WriteLine($"{reader.GetInt64(0)} {reader.GetString(1)}");
}

Python — pyodbc

Библиотека

  • pyodbc (через ODBC Driver for SQL Server)

Ключевые классы

  • Connection
  • Cursor

Методы

  • pyodbc.connect()
  • cursor(), execute(), executemany()
  • fetchone(), fetchall()
  • commit(), rollback(), close()
import pyodbc

conn = pyodbc.connect(
"Driver={ODBC Driver 18 for SQL Server};Server=localhost,1433;Database=app_db;UID=app_user;PWD=secret;Encrypt=yes;TrustServerCertificate=yes;"
)
cur = conn.cursor()

cur.execute("""
IF OBJECT_ID('dbo.Users','U') IS NULL
CREATE TABLE dbo.Users(
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(255) NOT NULL
)
""")

cur.execute("INSERT INTO dbo.Users(Name) VALUES (?)", ("Anna",))
conn.commit()

cur.execute("SELECT Id, Name FROM dbo.Users")
for row in cur.fetchall():
print(row[0], row[1])

cur.execute("UPDATE dbo.Users SET Name=? WHERE Id=?", ("Ann", 1))
cur.execute("DELETE FROM dbo.Users WHERE Id=?", (1,))
conn.commit()
conn.close()

Java — Microsoft JDBC Driver

Библиотека

  • com.microsoft.sqlserver:mssql-jdbc

Ключевые классы

  • Connection
  • PreparedStatement
  • ResultSet
  • DriverManager

Методы

  • DriverManager.getConnection("jdbc:sqlserver://...")
  • prepareStatement(), setAutoCommit(false), commit(), rollback()
  • setString(), executeUpdate(), executeQuery()
  • next(), getLong(), getString()
import java.sql.*;

try (Connection conn = DriverManager.getConnection(
"jdbc:sqlserver://localhost:1433;databaseName=app_db;user=app_user;password=secret;encrypt=true;trustServerCertificate=true;")) {

try (Statement st = conn.createStatement()) {
st.execute("""
IF OBJECT_ID('dbo.Users','U') IS NULL
CREATE TABLE dbo.Users(
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(255) NOT NULL
)
""");
}

try (PreparedStatement ins = conn.prepareStatement("INSERT INTO dbo.Users(Name) VALUES (?)")) {
ins.setString(1, "Anna");
ins.executeUpdate();
}

try (PreparedStatement sel = conn.prepareStatement("SELECT Id, Name FROM dbo.Users");
ResultSet rs = sel.executeQuery()) {
while (rs.next()) {
System.out.println(rs.getLong("Id") + " " + rs.getString("Name"));
}
}
}

C — ODBC API

Библиотека

  • ODBC (sql.h, sqlext.h)

Ключевые типы

  • SQLHENV, SQLHDBC, SQLHSTMT

Ключевые функции

  • SQLAllocHandle(), SQLDriverConnect(), SQLDisconnect()
  • SQLExecDirect(), SQLPrepare(), SQLBindParameter(), SQLExecute()
  • SQLFetch(), SQLGetData()
/* Структурный пример работы через ODBC:
1) SQLAllocHandle -> ENV/DBC/STMT
2) SQLDriverConnect с DSN/connection string
3) SQLExecDirect для DDL/DML
4) SQLFetch + SQLGetData для SELECT
*/

C++ — ODBC / SOCI

Библиотеки

  • ODBC C API (в C++-коде)
  • SOCI с backend ODBC/SQL Server

Ключевые объекты SOCI

  • soci::session
  • soci::statement
  • soci::row
  • soci::transaction

Методы

  • session.open(...)
  • sql << "..." для запросов
  • transaction для транзакций
// Примерная схема через SOCI:
// soci::session sql(soci::odbc, "Driver={ODBC Driver 18 for SQL Server};Server=...;");
// sql << "SELECT Id, Name FROM dbo.Users", soci::into(id), soci::into(name);

Go — go-mssqldb

Библиотеки

  • database/sql
  • github.com/microsoft/go-mssqldb

Ключевые типы

  • *sql.DB
  • *sql.Tx
  • *sql.Rows

Методы

  • sql.Open("sqlserver", connString)
  • Exec(), Query(), QueryRow()
  • Begin(), Commit(), Rollback()
package main

import (
"database/sql"
"fmt"
_ "github.com/microsoft/go-mssqldb"
)

func main() {
db, _ := sql.Open("sqlserver", "sqlserver://app_user:secret@localhost:1433?database=app_db&encrypt=disable")
defer db.Close()

db.Exec(`IF OBJECT_ID('dbo.Users','U') IS NULL CREATE TABLE dbo.Users(Id BIGINT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(255) NOT NULL)`)
db.Exec(`INSERT INTO dbo.Users(Name) VALUES (@p1)`, "Anna")

rows, _ := db.Query(`SELECT Id, Name FROM dbo.Users`)
defer rows.Close()
for rows.Next() {
var id int64
var name string
rows.Scan(&id, &name)
fmt.Println(id, name)
}
}

PHP — sqlsrv и PDO_SQLSRV

Библиотеки

  • sqlsrv
  • PDO sqlsrv

Ключевые функции / классы

  • sqlsrv_connect(), sqlsrv_query(), sqlsrv_fetch_array()
  • PDO("sqlsrv:Server=...;Database=..."), prepare(), execute()
<?php
$pdo = new PDO("sqlsrv:Server=localhost,1433;Database=app_db", "app_user", "secret");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$pdo->exec("
IF OBJECT_ID('dbo.Users','U') IS NULL
CREATE TABLE dbo.Users(
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(255) NOT NULL
)");

$stmt = $pdo->prepare("INSERT INTO dbo.Users(Name) VALUES (:name)");
$stmt->execute([':name' => 'Anna']);

$rows = $pdo->query("SELECT Id, Name FROM dbo.Users")->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
echo $row['Id'] . " " . $row['Name'] . PHP_EOL;
}

Kotlin — JDBC (SQL Server)

Библиотека

  • JDBC + Microsoft SQL Server Driver

Ключевые классы

  • Connection
  • PreparedStatement
  • ResultSet

Методы

  • DriverManager.getConnection()
  • prepareStatement(), executeUpdate(), executeQuery()
  • setString(), next(), getLong(), getString()
import java.sql.DriverManager

fun main() {
DriverManager.getConnection(
"jdbc:sqlserver://localhost:1433;databaseName=app_db;user=app_user;password=secret;encrypt=true;trustServerCertificate=true;"
).use { conn ->
conn.createStatement().use { st ->
st.execute(
"IF OBJECT_ID('dbo.Users','U') IS NULL CREATE TABLE dbo.Users(Id BIGINT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(255) NOT NULL)"
)
}
conn.prepareStatement("INSERT INTO dbo.Users(Name) VALUES (?)").use { ps ->
ps.setString(1, "Anna")
ps.executeUpdate()
}
conn.prepareStatement("SELECT Id, Name FROM dbo.Users").use { ps ->
ps.executeQuery().use { rs ->
while (rs.next()) println("${rs.getLong("Id")} ${rs.getString("Name")}")
}
}
}
}

Rust — tiberius

Библиотека

  • tiberius (TDS-клиент)

Ключевые типы

  • Client
  • Config
  • Row

Методы

  • Config::from_ado_string(...)
  • Client::connect(...)
  • query(), execute()
// Схема подключения в tiberius:
// 1) Сконфигурировать Config (host, port, auth, database, trust cert)
// 2) Открыть TCP-соединение
// 3) Client::connect(...)
// 4) Выполнять query/execute с параметрами

JavaScript — mssql

Библиотека

  • mssql

Ключевые классы/объекты

  • ConnectionPool
  • Request
  • Transaction

Методы

  • sql.connect(config)
  • request().input(...).query(...)
  • transaction.begin(), commit(), rollback()
import sql from "mssql";

const pool = await sql.connect({
user: "app_user",
password: "secret",
server: "localhost",
port: 1433,
database: "app_db",
options: { encrypt: true, trustServerCertificate: true },
});

await pool.request().query(`
IF OBJECT_ID('dbo.Users','U') IS NULL
CREATE TABLE dbo.Users(
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(255) NOT NULL
)`);

await pool.request().input("name", sql.NVarChar, "Anna")
.query("INSERT INTO dbo.Users(Name) VALUES (@name)");

const result = await pool.request().query("SELECT Id, Name FROM dbo.Users");
for (const row of result.recordset) {
console.log(row.Id, row.Name);
}

await pool.close();

Минимальный шаблон безопасной работы

  • Применяйте параметризованные запросы.
  • Используйте отдельные логины для приложений и админов.
  • Ограничивайте роли и права до нужного минимума.
  • Контролируйте таймауты и блокировки.
  • Отделяйте миграции схемы от runtime-запросов приложения.
SET LOCK_TIMEOUT 5000;
SET XACT_ABORT ON;
SELECT transaction_isolation_level FROM sys.dm_exec_sessions WHERE session_id = @@SPID;

Когда SQL Server подходит и когда выбрать другой путь

SQL Server подходит:

  • корпоративные решения на Microsoft-стеке;
  • системы с развитой отчётностью и BI;
  • проекты, где нужны зрелые инструменты администрирования и интеграции.

Другой путь выбирают:

  • для лёгкого локального хранилища внутри приложения удобнее SQLite;
  • для open-source-first экосистемы и некоторых advanced SQL-сценариев часто выбирают PostgreSQL;
  • для простых веб-сервисов с минимальной операционной сложностью часто берут MySQL.

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").