Database

Microsoft SQL Server

Overview

Microsoft SQL Server is an enterprise relational database management system developed and provided by Microsoft. It features high integration with Windows environments, powerful integrated development environments, and comprehensive business intelligence capabilities, widely used from small businesses to large enterprises.

Details

SQL Server was first released in 1989 and through continuous evolution has become an integrated data platform with the following characteristics:

Key Features

  • Always On Availability Groups: High availability and disaster recovery
  • In-Memory Technologies: In-Memory OLTP (Hekaton) and columnstore indexes
  • Intelligent Query Processing: AI-driven query optimization
  • Azure Integration: Hybrid cloud capabilities and Azure SQL Database
  • Stretch Database: Automatic tiering of hot and cold data
  • PolyBase: Integration with external data sources
  • JSON Support: Native JSON support
  • R and Python Integration: Advanced analytics and ML capabilities
  • Graph Database: Support for graph data models

Editions

  • Express: Lightweight and free development edition (10GB limit)
  • Standard: Standard feature version for small to medium enterprises
  • Enterprise: Full-featured version for enterprises
  • Developer: Free version for developers (with Enterprise features)
  • Web: For web applications
  • Azure SQL Database: Fully managed cloud version

Integrated Components

  • SQL Server Reporting Services (SSRS): Report creation and distribution
  • SQL Server Integration Services (SSIS): ETL/data integration
  • SQL Server Analysis Services (SSAS): OLAP and data mining
  • SQL Server Master Data Services (MDS): Master data management

Advantages and Disadvantages

Advantages

  • Windows Integration: Active Directory authentication, Windows Services integration
  • Rich Development Tools: SQL Server Management Studio (SSMS), Visual Studio integration
  • Comprehensive BI Features: Complete BI solution with SSRS, SSIS, SSAS
  • High Availability: Always On, failover clustering
  • Azure Integration: Seamless cloud migration and hybrid configuration
  • Strong Security: Row-level security, dynamic data masking
  • Excellent Performance: In-Memory technology and automatic tuning
  • Microsoft Support: Comprehensive technical support and documentation

Disadvantages

  • Windows Dependency: Linux support available but Windows-centric design
  • License Cost: Expensive core-based licensing structure
  • Resource Consumption: Requires large amounts of memory and CPU
  • Vendor Lock-in: Dependency on Microsoft technology ecosystem
  • Learning Cost: Need to learn T-SQL specific features
  • Virtualization Restrictions: Some editions have virtualization constraints

Key Links

Code Examples

Installation & Setup

# Download and install SQL Server 2022 Express
# https://www.microsoft.com/sql-server/sql-server-downloads

# Silent installation example
.\SQLEXPR_x64_ENU.exe /ACTION=Install /FEATURES=SQL /INSTANCENAME=SQLEXPRESS /SECURITYMODE=SQL /SAPWD="StrongPassword123!" /IAcceptSQLServerLicenseTerms

# Docker Linux container
docker pull mcr.microsoft.com/mssql/server:2022-latest
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=StrongPassword123!" \
  -p 1433:1433 --name sql-server \
  mcr.microsoft.com/mssql/server:2022-latest

# Service verification
Get-Service MSSQLSERVER
net start MSSQLSERVER

# SQL Server Configuration Manager
# Services → SQL Server (MSSQLSERVER) → Properties

Basic Operations (CRUD)

-- Create database
CREATE DATABASE CompanyDB
ON (
    NAME = 'CompanyDB',
    FILENAME = 'C:\Data\CompanyDB.mdf',
    SIZE = 100MB,
    MAXSIZE = 1GB,
    FILEGROWTH = 10MB
)
LOG ON (
    NAME = 'CompanyDB_Log',
    FILENAME = 'C:\Data\CompanyDB.ldf',
    SIZE = 10MB,
    FILEGROWTH = 10%
);

USE CompanyDB;

-- Create table
CREATE TABLE Employees (
    EmployeeID INT IDENTITY(1,1) PRIMARY KEY,
    FirstName NVARCHAR(50) NOT NULL,
    LastName NVARCHAR(50) NOT NULL,
    Email NVARCHAR(100) UNIQUE,
    HireDate DATETIME2 DEFAULT GETDATE(),
    Salary DECIMAL(10,2),
    DepartmentID INT,
    IsActive BIT DEFAULT 1
);

-- Insert data
INSERT INTO Employees (FirstName, LastName, Email, Salary, DepartmentID)
VALUES 
    ('John', 'Doe', '[email protected]', 75000.00, 1),
    ('Jane', 'Smith', '[email protected]', 65000.00, 2);

-- Select data
SELECT 
    EmployeeID,
    FirstName + ' ' + LastName AS FullName,
    Email,
    FORMAT(HireDate, 'yyyy/MM/dd') AS HireDateFormatted,
    FORMAT(Salary, 'C', 'en-US') AS SalaryFormatted
FROM Employees
WHERE IsActive = 1;

-- Update data
UPDATE Employees 
SET Salary = Salary * 1.1 
WHERE HireDate < DATEADD(YEAR, -1, GETDATE());

-- Delete data (logical deletion)
UPDATE Employees SET IsActive = 0 WHERE EmployeeID = 2;

Data Modeling

-- Table design with foreign key constraints
CREATE TABLE Departments (
    DepartmentID INT IDENTITY(1,1) PRIMARY KEY,
    DepartmentName NVARCHAR(100) NOT NULL,
    ManagerID INT,
    Budget MONEY DEFAULT 0
);

ALTER TABLE Employees
ADD CONSTRAINT FK_Employees_Department
FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID);

-- Using JSON columns
CREATE TABLE CustomerProfiles (
    CustomerID INT IDENTITY(1,1) PRIMARY KEY,
    CustomerName NVARCHAR(100),
    ProfileData NVARCHAR(MAX) CHECK (ISJSON(ProfileData) = 1),
    Preferences NVARCHAR(MAX) CHECK (ISJSON(Preferences) = 1)
);

INSERT INTO CustomerProfiles (CustomerName, ProfileData, Preferences)
VALUES (
    'John Doe',
    N'{"age": 30, "city": "New York", "skills": ["C#", "SQL Server"]}',
    N'{"newsletter": true, "language": "en"}'
);

-- Computed columns and indexes
ALTER TABLE CustomerProfiles
ADD Age AS JSON_VALUE(ProfileData, '$.age');

CREATE INDEX IX_CustomerProfiles_Age ON CustomerProfiles(Age);

-- Temporal tables (history management)
CREATE TABLE Products (
    ProductID INT IDENTITY(1,1) PRIMARY KEY,
    ProductName NVARCHAR(100) NOT NULL,
    Price MONEY,
    SysStartTime DATETIME2 GENERATED ALWAYS AS ROW START,
    SysEndTime DATETIME2 GENERATED ALWAYS AS ROW END,
    PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime)
) WITH (SYSTEM_VERSIONING = ON);

Indexing & Optimization

-- Create indexes
CREATE NONCLUSTERED INDEX IX_Employees_Department 
ON Employees(DepartmentID) INCLUDE (FirstName, LastName);

CREATE NONCLUSTERED INDEX IX_Employees_Email 
ON Employees(Email) WHERE IsActive = 1;

-- Columnstore index
CREATE NONCLUSTERED COLUMNSTORE INDEX IX_Sales_Columnstore
ON Sales (ProductID, CustomerID, SaleDate, Amount);

-- Full-text index
CREATE FULLTEXT CATALOG EmployeeFullTextCatalog;

CREATE FULLTEXT INDEX ON Employees(FirstName, LastName)
KEY INDEX PK__Employee__7AD04F11A11A1A1A
ON EmployeeFullTextCatalog;

SELECT * FROM Employees 
WHERE CONTAINS((FirstName, LastName), '"John*"');

-- Execution plan analysis
SET STATISTICS IO ON;
SET STATISTICS TIME ON;

-- Show actual execution plan
SET SHOWPLAN_ALL ON;
SELECT * FROM Employees WHERE DepartmentID = 1;
SET SHOWPLAN_ALL OFF;

-- Index usage statistics
SELECT 
    t.name AS TableName,
    i.name AS IndexName,
    s.user_seeks, s.user_scans, s.user_lookups,
    s.user_updates
FROM sys.dm_db_index_usage_stats s
INNER JOIN sys.indexes i ON s.object_id = i.object_id AND s.index_id = i.index_id
INNER JOIN sys.tables t ON i.object_id = t.object_id;

Practical Examples

-- Stored procedure (T-SQL)
CREATE PROCEDURE sp_CalculateBonus
    @DepartmentID INT,
    @BonusRate DECIMAL(5,4) = 0.10
AS
BEGIN
    SET NOCOUNT ON;
    
    DECLARE @TotalBonus MONEY = 0;
    
    UPDATE Employees 
    SET Bonus = Salary * @BonusRate
    WHERE DepartmentID = @DepartmentID AND IsActive = 1;
    
    SELECT @TotalBonus = SUM(Bonus)
    FROM Employees 
    WHERE DepartmentID = @DepartmentID AND IsActive = 1;
    
    PRINT 'Total bonus allocated: ' + FORMAT(@TotalBonus, 'C', 'en-US');
    
    SELECT 
        EmployeeID, 
        FirstName + ' ' + LastName AS FullName,
        FORMAT(Salary, 'C', 'en-US') AS Salary,
        FORMAT(Bonus, 'C', 'en-US') AS Bonus
    FROM Employees 
    WHERE DepartmentID = @DepartmentID AND IsActive = 1;
END;

EXEC sp_CalculateBonus @DepartmentID = 1, @BonusRate = 0.15;

-- User-defined function
CREATE FUNCTION dbo.GetEmployeeAge(@BirthDate DATE)
RETURNS INT
AS
BEGIN
    RETURN DATEDIFF(YEAR, @BirthDate, GETDATE()) - 
           CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, @BirthDate, GETDATE()), @BirthDate) > GETDATE()
                THEN 1 ELSE 0 END;
END;

-- Trigger
CREATE TRIGGER tr_EmployeeAudit
ON Employees
AFTER UPDATE
AS
BEGIN
    INSERT INTO EmployeeAudit (
        EmployeeID, ChangeDate, OldSalary, NewSalary, ChangedBy
    )
    SELECT 
        i.EmployeeID, 
        GETDATE(), 
        d.Salary, 
        i.Salary, 
        SUSER_SNAME()
    FROM inserted i
    INNER JOIN deleted d ON i.EmployeeID = d.EmployeeID
    WHERE i.Salary <> d.Salary;
END;

-- Common Table Expression (CTE)
WITH DepartmentStats AS (
    SELECT 
        d.DepartmentName,
        COUNT(e.EmployeeID) AS EmployeeCount,
        AVG(e.Salary) AS AvgSalary,
        MAX(e.Salary) AS MaxSalary
    FROM Departments d
    LEFT JOIN Employees e ON d.DepartmentID = e.DepartmentID
    WHERE e.IsActive = 1
    GROUP BY d.DepartmentID, d.DepartmentName
)
SELECT * FROM DepartmentStats
WHERE EmployeeCount > 0
ORDER BY AvgSalary DESC;

Best Practices

-- Security settings
-- Row-level security
CREATE FUNCTION dbo.fn_securitypredicate(@DepartmentID INT)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_securitypredicate_result
WHERE @DepartmentID = CAST(SESSION_CONTEXT(N'DepartmentID') AS INT);

CREATE SECURITY POLICY DepartmentSecurityPolicy
ADD FILTER PREDICATE dbo.fn_securitypredicate(DepartmentID) ON dbo.Employees
WITH (STATE = ON);

-- Dynamic data masking
ALTER TABLE Employees
ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()');

-- Transparent Data Encryption (TDE)
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDECert;

ALTER DATABASE CompanyDB SET ENCRYPTION ON;

-- Backup and restore
-- Full backup
BACKUP DATABASE CompanyDB 
TO DISK = 'C:\Backups\CompanyDB_Full.bak'
WITH FORMAT, 
     NAME = 'CompanyDB Full Backup',
     DESCRIPTION = 'Full backup of CompanyDB';

-- Transaction log backup
BACKUP LOG CompanyDB 
TO DISK = 'C:\Backups\CompanyDB_Log.trn';

-- Restore
RESTORE DATABASE CompanyDB_Test
FROM DISK = 'C:\Backups\CompanyDB_Full.bak'
WITH MOVE 'CompanyDB' TO 'C:\Data\CompanyDB_Test.mdf',
     MOVE 'CompanyDB_Log' TO 'C:\Data\CompanyDB_Test.ldf',
     REPLACE;

-- Always On Availability Groups
-- (Requires Windows Server Failover Clustering setup)
CREATE AVAILABILITY GROUP AG_CompanyDB
WITH (AUTOMATED_BACKUP_PREFERENCE = SECONDARY)
FOR DATABASE CompanyDB
REPLICA ON 
N'SQL-NODE1' WITH (ENDPOINT_URL = N'TCP://SQL-NODE1:5022',
                   AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
                   FAILOVER_MODE = AUTOMATIC),
N'SQL-NODE2' WITH (ENDPOINT_URL = N'TCP://SQL-NODE2:5022',
                   AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
                   FAILOVER_MODE = AUTOMATIC);

-- Monitoring and maintenance
-- Index fragmentation check
SELECT 
    OBJECT_NAME(ips.object_id) AS TableName,
    i.name AS IndexName,
    ips.avg_fragmentation_in_percent,
    ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') ips
INNER JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.avg_fragmentation_in_percent > 30;

-- Update statistics
UPDATE STATISTICS Employees WITH FULLSCAN;