<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luis kentt</title>
    <description>The latest articles on DEV Community by Luis kentt (@luis_kentt_a7a069a09be26d).</description>
    <link>https://dev.to/luis_kentt_a7a069a09be26d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3593262%2F30a36b8a-b7f2-471b-91c2-ea0902b0fd4d.png</url>
      <title>DEV Community: Luis kentt</title>
      <link>https://dev.to/luis_kentt_a7a069a09be26d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luis_kentt_a7a069a09be26d"/>
    <language>en</language>
    <item>
      <title>Beyond SSMS Modern SQL Server Management for Developers</title>
      <dc:creator>Luis kentt</dc:creator>
      <pubDate>Sun, 02 Nov 2025 16:29:38 +0000</pubDate>
      <link>https://dev.to/luis_kentt_a7a069a09be26d/beyond-ssms-modern-sql-server-management-for-developers-4734</link>
      <guid>https://dev.to/luis_kentt_a7a069a09be26d/beyond-ssms-modern-sql-server-management-for-developers-4734</guid>
      <description>&lt;p&gt;Hey database warriors! &lt;/p&gt;

&lt;p&gt;If you're working with SQL Server, you've probably used SQL Server Management Studio (SSMS). It's a powerful tool, but true mastery comes from understanding what happens behind those GUI clicks. Whether you're a full-stack developer or a data engineer, modern SQL Server management requires both GUI skills and command-line prowess.&lt;/p&gt;

&lt;p&gt;Let's dive into essential SQL Server management techniques that will make you more effective and prepared for DevOps environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.indiatoday.in/india/story/ed-arrests-ias-officer-chhattisgarh-bl-agarwal-disproportionate-assets-case-1739893-2020-11-10" rel="noopener noreferrer"&gt;Link to read&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 1: The Foundation - Essential Administrative Queries&lt;/strong&gt;&lt;br&gt;
Before we automate, we need to understand. These queries are your "first responders" when checking database health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Checking Database Space Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-- Check database file sizes and space usage&lt;br&gt;
SELECT &lt;br&gt;
    name AS [Database Name],&lt;br&gt;
    type_desc AS [File Type],&lt;br&gt;
    physical_name AS [Physical File Path],&lt;br&gt;
    size/128.0 AS [Current Size MB],&lt;br&gt;
    size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS INT)/128.0 AS [Free Space MB]&lt;br&gt;
FROM sys.database_files;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When to use: Before deployments, when you're running low on disk, or when performance slows down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Finding Your Largest Tables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-- Identify space-hogging tables&lt;br&gt;
SELECT &lt;br&gt;
    t.NAME AS TableName,&lt;br&gt;
    p.rows AS RowCounts,&lt;br&gt;
    SUM(a.total_pages) * 8 AS TotalSpaceKB,&lt;br&gt;
    SUM(a.used_pages) * 8 AS UsedSpaceKB,&lt;br&gt;
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB&lt;br&gt;
FROM sys.tables t&lt;br&gt;
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id&lt;br&gt;
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id&lt;br&gt;
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id&lt;br&gt;
WHERE t.NAME NOT LIKE 'dt%' AND i.OBJECT_ID &amp;gt; 255 AND i.index_id &amp;lt;= 1&lt;br&gt;
GROUP BY t.NAME, p.rows&lt;br&gt;
ORDER BY TotalSpaceKB DESC;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Performance tuning, identifying candidates for archiving or partitioning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Monitoring Active Connections and Blocking&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;-- Check current activity and blocking&lt;br&gt;
SELECT &lt;br&gt;
    es.session_id,&lt;br&gt;
    es.login_name,&lt;br&gt;
    es.host_name,&lt;br&gt;
    est.text AS [Query Text],&lt;br&gt;
    er.blocking_session_id,&lt;br&gt;
    er.wait_type,&lt;br&gt;
    er.wait_time&lt;br&gt;
FROM sys.dm_exec_sessions es&lt;br&gt;
LEFT JOIN sys.dm_exec_requests er ON es.session_id = er.session_id&lt;br&gt;
OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) est&lt;br&gt;
WHERE es.is_user_process = 1&lt;br&gt;
ORDER BY er.wait_time DESC;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2: Modern Deployment Strategies&lt;/strong&gt;&lt;br&gt;
Gone are the days of manually running scripts in production. Here's how to manage deployments like a pro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using SQLCMD Mode for Script Automation&lt;/strong&gt;&lt;br&gt;
Save this as deploy_script.sql and run it from command line or in your CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;`-- This script demonstrates environment-aware deployment&lt;br&gt;
:setvar DatabaseName "MyApp"&lt;br&gt;
:setvar Environment "DEV"&lt;/p&gt;

&lt;p&gt;USE [$(DatabaseName)];&lt;/p&gt;

&lt;p&gt;PRINT 'Deploying to $(Environment) environment...';&lt;/p&gt;

&lt;p&gt;-- Conditionally apply changes based on environment&lt;br&gt;
IF '$(Environment)' = 'PROD'&lt;br&gt;
BEGIN&lt;br&gt;
    PRINT 'Creating backup before schema changes...';&lt;br&gt;
    -- Backup logic would go here&lt;br&gt;
END&lt;/p&gt;

&lt;p&gt;-- Add new column if it doesn't exist&lt;br&gt;
IF NOT EXISTS(&lt;br&gt;
    SELECT 1 FROM sys.columns &lt;br&gt;
    WHERE object_id = OBJECT_ID('dbo.Users') AND name = 'LastLoginDate'&lt;br&gt;
)&lt;br&gt;
BEGIN&lt;br&gt;
    PRINT 'Adding LastLoginDate column...';&lt;br&gt;
    ALTER TABLE dbo.Users ADD LastLoginDate DATETIME2 NULL;&lt;br&gt;
END&lt;br&gt;
ELSE&lt;br&gt;
BEGIN&lt;br&gt;
    PRINT 'LastLoginDate column already exists.';&lt;br&gt;
END&lt;/p&gt;

&lt;p&gt;-- Always update the version table&lt;br&gt;
MERGE dbo.DatabaseVersion AS target&lt;br&gt;
USING (SELECT '1.2.0' AS VersionNumber, GETDATE() AS DeployDate) AS source&lt;br&gt;
ON target.VersionNumber = source.VersionNumber&lt;br&gt;
WHEN NOT MATCHED THEN&lt;br&gt;
    INSERT (VersionNumber, DeployDate) &lt;br&gt;
    VALUES (source.VersionNumber, source.DeployDate);`&lt;/p&gt;

&lt;p&gt;Run from command line:&lt;br&gt;
&lt;code&gt;sqlcmd -S localhost -i deploy_script.sql -v DatabaseName="MyApp" Environment="PROD"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database Projects and DACPACs&lt;/strong&gt;&lt;br&gt;
The modern approach: treat your database as code.&lt;/p&gt;

&lt;p&gt;`-- In your Visual Studio Database Project&lt;br&gt;
-- Scripts/PostDeployment/DataSeed.sql&lt;/p&gt;

&lt;p&gt;PRINT 'Seeding reference data...';&lt;/p&gt;

&lt;p&gt;-- Idempotent data seeding&lt;br&gt;
MERGE dbo.ProductCategories AS Target&lt;br&gt;
USING (VALUES &lt;br&gt;
    (1, 'Electronics'),&lt;br&gt;
    (2, 'Books'),&lt;br&gt;
    (3, 'Clothing')&lt;br&gt;
) AS Source (CategoryId, CategoryName)&lt;br&gt;
ON Target.CategoryId = Source.CategoryId&lt;br&gt;
WHEN NOT MATCHED BY TARGET THEN&lt;br&gt;
    INSERT (CategoryId, CategoryName) VALUES (CategoryId, CategoryName)&lt;br&gt;
WHEN NOT MATCHED BY SOURCE THEN&lt;br&gt;
    DELETE;&lt;code&gt;&lt;br&gt;
**Deploy using SQLPackage:**&lt;br&gt;
&lt;/code&gt;sqlpackage /Action:Publish /SourceFile:MyDatabase.dacpac /TargetServerName:localhost /TargetDatabaseName:MyApp`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 3: Performance and Maintenance Automation&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Creating Smart Index Maintenance&lt;/strong&gt;&lt;br&gt;
Instead of blindly rebuilding all indexes, be intelligent about it.&lt;br&gt;
`-- Smart index maintenance procedure&lt;br&gt;
CREATE OR ALTER PROCEDURE dbo.usp_SmartIndexMaintenance&lt;br&gt;
    @FragmentationThreshold LOW = 15.0,&lt;br&gt;
    @FragmentationThreshold HIGH = 30.0&lt;br&gt;
AS&lt;br&gt;
BEGIN&lt;br&gt;
    SET NOCOUNT ON;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Get fragmented indexes
SELECT 
    OBJECT_NAME(ips.object_id) AS TableName,
    si.name AS IndexName,
    ips.avg_fragmentation_in_percent AS Fragmentation
INTO #FragmentedIndexes
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
INNER JOIN sys.indexes si ON ips.object_id = si.object_id AND ips.index_id = si.index_id
WHERE ips.avg_fragmentation_in_percent &amp;gt; @FragmentationThresholdLow
    AND si.name IS NOT NULL -- Exclude heaps
    AND ips.page_count &amp;gt; 1000; -- Only indexes with meaningful size

-- Reorganize moderately fragmented indexes (15-30%)
DECLARE @ReorganizeSQL NVARCHAR(MAX);
SELECT @ReorganizeSQL = COALESCE(@ReorganizeSQL + CHAR(13), '') +
    'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(TableName) + ' REORGANIZE;'
FROM #FragmentedIndexes
WHERE Fragmentation BETWEEN @FragmentationThresholdLow AND @FragmentationThresholdHigh;

-- Rebuild highly fragmented indexes (&amp;gt;30%)
DECLARE @RebuildSQL NVARCHAR(MAX);
SELECT @RebuildSQL = COALESCE(@RebuildSQL + CHAR(13), '') +
    'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(TableName) + ' REBUILD;'
FROM #FragmentedIndexes
WHERE Fragmentation &amp;gt; @FragmentationThresholdHigh;

-- Execute the maintenance
IF @ReorganizeSQL IS NOT NULL
BEGIN
    PRINT 'Reorganizing indexes...';
    EXEC sp_executesql @ReorganizeSQL;
END

IF @RebuildSQL IS NOT NULL
BEGIN
    PRINT 'Rebuilding indexes...';
    EXEC sp_executesql @RebuildSQL;
END

DROP TABLE #FragmentedIndexes;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;END;&lt;code&gt;&lt;br&gt;
**Schedule this in SQL Server Agent:**&lt;br&gt;
&lt;/code&gt;-- Schedule for off-hours&lt;br&gt;
EXEC dbo.usp_SmartIndexMaintenance &lt;br&gt;
    @FragmentationThresholdLow = 15.0,&lt;br&gt;
    @FragmentationThresholdHigh = 30.0;`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 4: Security and Compliance&lt;/strong&gt;&lt;br&gt;
Implementing Column-Level Encryption&lt;/p&gt;

&lt;p&gt;`-- Always Encrypted demonstration&lt;br&gt;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'StrongMasterKeyPassword123!';&lt;/p&gt;

&lt;p&gt;CREATE CERTIFICATE MyColumnCert&lt;br&gt;&lt;br&gt;
WITH SUBJECT = 'Column Encryption Certificate';&lt;/p&gt;

&lt;p&gt;CREATE COLUMN ENCRYPTION KEY MyColumnEncryptionKey&lt;br&gt;&lt;br&gt;
WITH VALUES&lt;br&gt;&lt;br&gt;
(&lt;br&gt;&lt;br&gt;
    COLUMN_MASTER_KEY = MyColumnCert,&lt;br&gt;&lt;br&gt;
    ALGORITHM = 'RSA_OAEP',&lt;br&gt;&lt;br&gt;
    ENCRYPTED_VALUE = 0x01700000016C006F00630061006C0068006F0073007400... -- Your encrypted value&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;-- Table with encrypted columns&lt;br&gt;
CREATE TABLE dbo.Customers&lt;br&gt;
(&lt;br&gt;
    CustomerId INT PRIMARY KEY,&lt;br&gt;
    FirstName NVARCHAR(50) COLLATE Latin1_General_BIN2 &lt;br&gt;
        ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, &lt;br&gt;
                       ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', &lt;br&gt;
                       COLUMN_ENCRYPTION_KEY = MyColumnEncryptionKey) NULL,&lt;br&gt;
    Email NVARCHAR(100) COLLATE Latin1_General_BIN2 &lt;br&gt;
        ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED, &lt;br&gt;
                       ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', &lt;br&gt;
                       COLUMN_ENCRYPTION_KEY = MyColumnEncryptionKey) NULL,&lt;br&gt;
    CreditCardNumber NVARCHAR(20) COLLATE Latin1_General_BIN2 &lt;br&gt;
        ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, &lt;br&gt;
                       ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', &lt;br&gt;
                       COLUMN_ENCRYPTION_KEY = MyColumnEncryptionKey) NULL&lt;br&gt;
);`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auditing User Access&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;`-- Create server audit&lt;br&gt;
CREATE SERVER AUDIT AppDBAudit&lt;br&gt;&lt;br&gt;
TO FILE (FILEPATH = 'C:\Audits\')&lt;br&gt;
WITH (ON_FAILURE = CONTINUE);&lt;/p&gt;

&lt;p&gt;-- Database audit specification&lt;br&gt;
CREATE DATABASE AUDIT SPECIFICATION AppDBAuditSpec&lt;br&gt;&lt;br&gt;
FOR SERVER AUDIT AppDBAudit&lt;br&gt;&lt;br&gt;
ADD (SELECT, INSERT, UPDATE, DELETE ON SCHEMA::dbo BY PUBLIC),&lt;br&gt;
ADD (EXECUTE ON SCHEMA::dbo BY PUBLIC);&lt;/p&gt;

&lt;p&gt;ALTER SERVER AUDIT AppDBAudit WITH (STATE = ON);&lt;br&gt;
ALTER DATABASE AUDIT SPECIFICATION AppDBAuditSpec WITH (STATE = ON);`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 5: Modern Tooling - PowerShell for SQL Server&lt;/strong&gt;&lt;br&gt;
`# Automated database refresh from production to development&lt;br&gt;
param(&lt;br&gt;
    [string]$SourceServer = "PROD-SQL-01",&lt;br&gt;
    [string]$DestinationServer = "DEV-SQL-01",&lt;br&gt;
    [string]$DatabaseName = "MyApp"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;Import-Module SqlServer&lt;/p&gt;

&lt;p&gt;try {&lt;br&gt;
    Write-Host "Starting database refresh process..." -ForegroundColor Green&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Backup production database
$backupFile = "\\backup\share\$DatabaseName-$(Get-Date -Format 'yyyyMMdd-HHmmss').bak"
Write-Host "Creating backup from production..." -ForegroundColor Yellow
Backup-SqlDatabase -ServerInstance $SourceServer -Database $DatabaseName -BackupFile $backupFile

# Restore to development
Write-Host "Restoring to development environment..." -ForegroundColor Yellow
Restore-SqlDatabase -ServerInstance $DestinationServer -Database $DatabaseName -BackupFile $backupFile -ReplaceDatabase

# Post-restore steps
Write-Host "Running post-restore scripts..." -ForegroundColor Yellow
Invoke-SqlCmd -ServerInstance $DestinationServer -Database $DatabaseName -Query "
    EXEC sp_change_users_login 'Auto_Fix', 'AppUser';
    UPDATE dbo.Configuration SET Environment = 'DEV';
"

Write-Host "Database refresh completed successfully!" -ForegroundColor Green
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
catch {&lt;br&gt;
    Write-Error "Database refresh failed: $($_.Exception.Message)"&lt;br&gt;
    throw&lt;br&gt;
}`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: From ClickOps to CodeOps&lt;/strong&gt;&lt;br&gt;
Modern SQL Server management is evolving:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From manual SSMS clicks&lt;/strong&gt; → To automated scripts and DevOps pipelines&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From reactive firefighting&lt;/strong&gt; → To proactive monitoring and maintenance&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From individual knowledge&lt;/strong&gt; → To documented, version-controlled processes&lt;/p&gt;

&lt;p&gt;From "it works on my machine" → To consistent environments with DACPACs&lt;/p&gt;

&lt;p&gt;The most effective database professionals today blend deep SQL knowledge with automation skills. They treat database management as code and infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your Action Plan:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start by documenting your next SSMS task as a script&lt;/p&gt;

&lt;p&gt;Implement one maintenance automation this week&lt;/p&gt;

&lt;p&gt;Try a database project for your next schema change&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;What's your favorite SQL Server management tip or trick? Have you moved from manual processes to automation? Share your experiences and favorite scripts in the comments below!&lt;br&gt;
*&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>sqlserver</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
