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 | Комментарий |
|---|---|---|---|
| DML | SELECT, INSERT, UPDATE, DELETE | Доступно | Полная поддержка |
| DDL | CREATE/ALTER/DROP | Доступно | Широкие возможности |
| Транзакции | BEGIN TRAN, COMMIT, ROLLBACK, SAVE TRAN | Доступно | Полный контроль транзакций |
| Права | CREATE LOGIN/USER, GRANT, REVOKE | Доступно | Гранулярная модель прав |
| Server-side логика | PROCEDURE, FUNCTION, TRIGGER | Доступно | Основа бизнес-логики в БД |
| Upsert | MERGE или паттерн 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, библиотеки, классы и функции
C# — Microsoft.Data.SqlClient
Библиотека
Microsoft.Data.SqlClient
Ключевые классы
SqlConnectionSqlCommandSqlTransactionSqlDataReaderSqlParameter
Свойства и методы
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)
Ключевые классы
ConnectionCursor
Методы
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
Ключевые классы
ConnectionPreparedStatementResultSetDriverManager
Методы
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::sessionsoci::statementsoci::rowsoci::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/sqlgithub.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
Ключевые классы
ConnectionPreparedStatementResultSet
Методы
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-клиент)
Ключевые типы
ClientConfigRow
Методы
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
Ключевые классы/объекты
ConnectionPoolRequestTransaction
Методы
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.
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Вот SQL как раз обеспечивает такую связь и это главное отличие реляционных БД - реляции (relations), что означает связи. Знакомимся с языком - ставим программы, запускаем, выполняем первые запросы. От файлового хранения к реляционной и современной мультимодельной СУБД — термины, причины появления SQL и базовая классификация систем. Домены, атрибуты, кортежи и отношения — свойства реляционных таблиц и ограничения целостности при проектировании схемы. Функциональные зависимости, нормальные формы 1НФ–3НФ, аномалии обновления и осознанная денормализация при проектировании схемы. Метаданные СУБД через information_schema и pg_catalog — запросы к структуре таблиц, ключей и индексов в PostgreSQL. Логическое и физическое резервное копирование, pg_dump, pg_restore, WAL и восстановление на точку во времени (PITR). Логический порядок выполнения SELECT, проекция, WHERE, DISTINCT, ORDER BY и правила читаемого форматирования запросов. Скалярные и коррелированные подзапросы, EXISTS против IN, особенности NULL и выбор между подзапросом и JOIN. AND, OR, NOT, приоритет операторов, NULL и UNKNOWN, IS NULL, NOT IN и IS DISTINCT FROM в PostgreSQL. MVCC, уровни блокировок таблиц, FOR UPDATE, SKIP LOCKED, взаимоблокировки и диагностика через pg_locks. Учебная схема интернет-магазина для PostgreSQL — DDL и примеры запросов по темам курса SQL.SQL - язык структурированных запросов
Первые шаги с SQL
Эволюция систем хранения данных
Реляционная модель данных
Нормализация данных
Словарь данных и системные каталоги
Резервное копирование и восстановление PostgreSQL
Оператор SELECT — синтаксис и стиль
Подзапросы, EXISTS и IN
Фильтрация и трёхзначная логика
Блокировки и конкурентный доступ в PostgreSQL
Практикум shop_data