DBA Tooling · 2026

sqmSQLTool

The DBA toolbox

87 functions. One module. From backup to automatic AlwaysOn repair.

PowerShell 5.1 dbatools 2.x Pester tests 6 domains 🇦🇪 DE  |  🇧🇳 EN v2.x

Uwe Janke · Senior SQL Server DBA · dtcSoftware

Windows PowerShell 5.1 — sqmSQLTool v2.x

# AlwaysOn repair - fully automatic

PS> Repair-sqmAlwaysOnDatabases -SqlInstance 'SQL01' -Auto

[OK] Finance - removed, reseeded, joined AG

[OK] Controlling - removed, reseeded, joined AG

 

# AG-aware backup - preferred node only

PS> Invoke-sqmUserDatabaseBackup -SqlInstance 'SQL01' -All -CheckPreferredReplica

 

# Health check + security

PS> Get-sqmDatabaseHealth -SqlInstance 'SQL01' | Format-Table

PS> Invoke-sqmSaObfuscation -SqlInstance 'SQL01'

 

# Inventory - generate an HTML report

PS> Invoke-sqmInstanceInventory -SqlInstance 'SQL01' -OutputPath 'C:\Reports'

Report saved: C:\Reports\SQL01_Inventory_20260520.html

Motivation

The Problem

🔥

AG database out of sync

Manual intervention: remove DB, clean up the secondary, backup, restore, add back to AG. 30-90 minutes. At 3am.

⏱️

Backup job runs on the wrong node

The AG preferred replica isn't checked. Primary backs up instead of secondary. An I/O spike in production.

🔍

Inventory? Excel.

Who has sysadmin? Which DBs have no backup? Which instance is on which patch level? - Manual queries, always incomplete.

📋

No compliance evidence

Auditors ask concrete questions: when was the last CHECKDB? Is SA still active? Is there a login audit? - No central report.

🐛

A deadlock happened - nobody knows when

Set up Extended Events by hand, parse the trace file. By the time the analysis is done, the problem is forgotten.

🔧

No consistent DBA processes

Every DBA has their own scripts. No standard, no traceability, no Pester tests.

Business Value

The Value

87
functions

One module - no tool zoo

30-90 min
AlwaysOn repair

automatic instead of manual

0
manual interventions

for an overnight AG failure

SituationBeforeWith sqmSQLTool
AG DB out of syncManual repair, 30-90 min. Automatic repair job (hourly)
Backup auditAn Excel list, out of date Get-sqmDatabaseHealth - a report per click
Deadlock analysisExtended Events by hand Get-sqmDeadlockReport - instantly
SA account activeOften overlooked Invoke-sqmSaObfuscation - 1 command
Patch levelAd-hoc query Invoke-sqmPatchAnalysis - every instance
✓ Every function is Pester-tested and production-proven on SQL Server 2019/2022/2025

Overview

6 Functional Domains

87 functions - 6 topic areas. Each area complete on its own.

🇦🇪 DE  |  🇧🇳 EN  —  sqmSQLTool is bilingual. Every output (logs, messages, HTML reports, mail notifications) appears in the configured language. Switch it: Set-sqmConfig -Language 'en-US' or 'de-DE'.
🔴

AlwaysOn & HA

Repair, sync, failover, seeding, AG add/remove, repair job - the full AG lifecycle

💾

Backup & integrity

Backup with AG-aware logic, the backup exclude table, integrity checks, restore, Ola jobs

📊

Health & diagnostics

Database health, wait stats, blocking, autogrowth, VLF count, long-running queries, missing indexes

🔐

Security & compliance

SA obfuscation, login audit, sysadmin report, AD account status, SPN report, certificates

Performance

PerfBaseline, PerfCounters, index fragmentation, missing indexes, Query Store, wait statistics

📋

Inventory & docs

Instance inventory, database documentation, server configuration compare, patch analysis

Eye-Catcher · AlwaysOn & HA

Automatic AlwaysOn Repair

An AG database loses sync - the tool detects it, repairs it fully automatically, and writes to the Windows Event Log.

1
Detection

Checks the SynchronizationState of every AG database. Anything other than HEALTHY or SYNCHRONIZED is a candidate.

2
Confirm automatic seeding

Invoke-sqmSqlAlwaysOnAutoseeding on every replica - a prerequisite for autoseed repair.

3
Remove from the AG

Remove-DbaAgDatabase - clean, via dbatools.

4
Clean up secondaries

Delete the DB on every secondary - no orphaned state.

5
Check the recovery mode

Sets it to FULL if it drifted - otherwise the add fails.

6
Add with autoseed

Add-DbaAgDatabase -SeedingMode Automatic - no backup/restore needed.

7
Event Log + logging

EventId 1000/1001/1002 in the Windows Application Log. Invoke-sqmLogging for the file log.

# Call it manually:
Repair-sqmAlwaysOnDatabases

# Set it up as an hourly Agent job:
New-sqmAlwaysOnRepairJob -Schedule "FREQ=HOURLY;INTERVAL=1"

# Test with no changes:
Repair-sqmAlwaysOnDatabases -WhatIf

# Output:
# SqlInstance  DatabaseName  AvailabilityGroup  Status
# -----------  ------------  -----------------  ------
# SQLNODE01    SalesDB       AG_PROD_01         RepairSuccess
# SQLNODE01    HRDB          AG_PROD_01         RepairSuccess
✓ New-sqmAlwaysOnRepairJob automatically creates a SQL Agent job - hourly monitoring with no DBA intervention

Eye-Catcher · Backup & Integrity

AG-Aware Backup

Invoke-sqmUserDatabaseBackup knows AlwaysOn. It checks sys.fn_hadr_backup_is_preferred_replica() and runs only on the right node.

⚠ The problem without this feature - the backup job runs on Primary AND Secondary. Double I/O. Redundant backup files. Unclear which one to restore from.
✓ With -CheckPreferredReplica - the job checks whether this node is the preferred backup node. If not: it stops immediately. No backup. No I/O.
1
-UseExcludeTable

Reads master.dbo.sqm_BackupExclude - databases that are deliberately excluded (Sync-sqmBackupExcludeTable maintains the table).

2
-MailTo / -MailOnSuccess

A backup report via Database Mail - by default only on failure or abort. -MailOnSuccess for every run.

3
Backup path from server properties

Reads BackupDirectory automatically from server properties. No hardcoded path in the job.

# Default: every user DB, AG-aware
Invoke-sqmUserDatabaseBackup -All -CheckPreferredReplica

# With the exclude table and a mail report
Invoke-sqmUserDatabaseBackup -All `
    -CheckPreferredReplica `
    -UseExcludeTable `
    -MailTo "dba-team@company.com"

# Set up as a backup maintenance job
New-sqmBackupMaintenanceJob `
    -SqlInstance "SQLNODE01" `
    -CheckPreferredReplica `
    -MailTo "dba-team@company.com"
ℹ Backup path rule - the path must end in 'User-Db' (from server properties or the -BackupPath parameter)

Deep Dive · Health & Diagnostics

Database Health - One Command

Get-sqmDatabaseHealth checks 8 dimensions per database. Result: a TXT report + CSV. Usable immediately.

CheckThreshold
Recovery modelWarning if not FULL
Last CHECKDBWarning if older than 14 days (configurable)
Last backup (full)Red if never / older than configured
Last backup (diff/log)Warning if none exists
Autogrowth eventsLast 30 days (configurable)
VLF countWarning from 200 (configurable)
Database sizeInformational
DB statusRed if not online
ℹ Pipeline-capable - Get-sqmDatabaseHealth -SqlInstance 'SQL01','SQL02','SQL03' checks multiple instances in one call
# A single instance
Get-sqmDatabaseHealth

# Multiple instances
Get-sqmDatabaseHealth `
    -SqlInstance "SQL01","SQL02" `
    -MaxCheckDbAgeDays 7 `
    -MaxVlfCount 100 `
    -OutputPath "D:\Reports"

# Output (excerpt):
# Database   Status  LastFull    VLFs  CheckDB   AutoGrowth
# --------   ------  --------    ----  -------   ----------
# SalesDB    ok      2026-05-19  48    ok        3 Events
# HRDB       WARN    2026-05-01  312   ok        0 Events
# ArchiveDB  ERROR   never       89    14d ago   0 Events

Deep Dive · Security & Compliance

Security Hardening - Audit-Ready

Auditors ask specific questions. sqmSQLTool delivers specific answers - and fixes weaknesses automatically.

1
SA obfuscation

Invoke-sqmSaObfuscation - renames it and sets a random 32-character password. Requires: an AD group already set as sysadmin. Returns the new name + password as an object.

2
Login audit

Invoke-sqmLoginAudit - every login, roles, last login time. Detects orphaned, disabled, and inactive accounts. Exportable to CSV.

3
Sysadmin report

Get-sqmSysadminAccounts - an instant overview of which accounts have sysadmin rights. For audit evidence.

Audit questionFunctionEffort
Is SA still active?Invoke-sqmSaObfuscation1 command
Who has sysadmin?Get-sqmSysadminAccounts1 command
Last CHECKDB?Get-sqmDatabaseHealthAutomatic report
Inactive logins?Invoke-sqmLoginAuditCSV export
SPNs correct?Get-sqmSpnReportAD vs. expected comparison
Certificates expiring?Get-sqmCertificateReportWarning at <30 days
⚡ Banking regulation (BAIT/MaRisk) requires regular evidence of privileged accounts. These functions deliver that evidence directly.

Deep Dive · Performance

Performance Analysis - From Slow to Solution

No more manual DMV digging. sqmSQLTool delivers prioritized recommendations.

1
Wait statistics - what's SQL Server waiting on?

Get-sqmWaitStatistics - top wait types, weighted. Instantly clear whether the problem is I/O, CPU, locking, or memory.

2
Missing indexes - what's missing?

Get-sqmMissingIndexes - from sys.dm_db_missing_index_details, prioritized by impact score. With a CREATE INDEX statement.

3
Long-running queries - what's taking too long?

Get-sqmLongRunningQueries - current + historical long-runners from DMVs, with a query text excerpt.

4
PerfBaseline - is this normal?

Invoke-sqmPerfBaseline - collects performance counters over a period, saves as a CSV baseline for comparison.

# Step 1: what's waiting right now?
Get-sqmWaitStatistics | Select-Object -First 5

# WaitType          WaitMs  Percentage
# --------          ------  ----------
# PAGEIOLATCH_SH    45823   38.2%
# LCK_M_S           12401   10.3%
# CXPACKET           9822    8.2%

# Step 2: which indexes are missing?
Get-sqmMissingIndexes -SqlInstance "SQL01" |
    Sort-Object ImpactScore -Descending |
    Select-Object -First 3

# Step 3: record a baseline (15 min.)
Invoke-sqmPerfBaseline -Duration 15 `
    -OutputPath "D:\Baseline"

Deep Dive · Inventory & Docs

Instance Inventory - One Command, Full Picture

Invoke-sqmInstanceInventory fully documents an instance: version, DBs, logins, jobs, AlwaysOn. TXT + CSV automatically.

1
Instance metadata

Version, edition, patch level, collation, max memory, CPU count, sp_configure values.

2
Databases

Name, status, recovery model, size, last backup, owner, collation - every user DB.

3
Logins & roles

Every login with type, status, server roles - ready for an audit immediately.

4
SQL Agent jobs

Every job with status, owner, schedule, last run, and result.

5
AlwaysOn

AGs, replicas, listener, sync status - only if configured.

✓ Pipeline-capable - 'SQL01','SQL02','SQL03' | Invoke-sqmInstanceInventory - fleet documentation with one click
# Document a single instance
Invoke-sqmInstanceInventory

# Multiple instances (fleet)
'SQL01','SQL02','SQL03' |
    Invoke-sqmInstanceInventory `
    -ContinueOnError `
    -OutputPath "\\srv\DBA-Reports\Inventory"

# Patch level of every instance
Invoke-sqmPatchAnalysis `
    -SqlInstance 'SQL01','SQL02','SQL03'

# Output:
# Instance  Version  CU       LatestCU  Status
# --------  -------  --       --------  ------
# SQL01     2022     CU14     CU16      WARN
# SQL02     2022     CU16     CU16      ok
# SQL03     2019     RTM      CU27      ERROR

Quality & Testability

Production-Grade - Pester-Tested

sqmSQLTool isn't a script collection. It's a PowerShell module with unit tests, structured logging, and consistent conventions.

Module structure

1
Public / Private

A clean split between the public API (87 functions) and internal helpers. Invoke-sqmLogging, Invoke-sqmHelpers are internal only.

2
Pester unit tests

Tests under /tests/Unit/ for every critical function. dbatools calls are mocked - no real SQL Server needed.

3
Consistent logging

Invoke-sqmLogging: file + event log + verbose. Every function logs consistently. A central OutputPath via Set-sqmConfig.

4
Install / update

Install.cmd / Install.ps1: auto-detects admin, AllUsers or CurrentUser. Robocopy without Zone.Identifier. Update.ps1 for upgrades.

PropertyValue
Public functions87
Pester test files~15
PowerShell version5.1 (PS 7 compatible)
Dependenciesdbatools ≥ 2.0
LoggingFile + Windows Event Log
ConfigurationSet-sqmConfig / Get-sqmConfig
Install scopeAuto-detects admin → AllUsers
ℹ Get-sqmConfig / Set-sqmConfig - central configuration: OutputPath, CentralPath, LogLevel. Set it once, every function uses it.

Toolchain

sqmSQLTool in the Toolchain

sqmSQLTool is the operational backbone. Every other tool builds on it.

1
SQLSetupTool
PostInstall: sqmSQLTool functions
2
AlwaysOnSetup
Endpoint, CONNECT, monitoring
3
sqmSQLTool
Day-to-day operations
4
DeadlockCollector
Uses sqmLogging
5
SSRSDeployment
Install-sqmSsrsReportServer
⚙️

SQLSetupTool → sqmSQLTool

PostInstall calls: Invoke-sqmNtfsSetup, Invoke-sqmSaObfuscation, Invoke-sqmMonitoringKey, Install-sqmOlaMaintenanceSolution, New-sqmOlaMaintenanceJobs

🔷

AlwaysOnSetup → sqmSQLTool

Endpoint configuration, monitoring key, SA check after AG setup

📦

dbatools

The foundation for every SQL operation. sqmSQLTool is a company-specific layer built on top of dbatools.

🪟

Windows Event Log

Repair-sqmAlwaysOnDatabases writes EventId 1000/1001/1002 - visible in a SIEM/Splunk

AlwaysOnSetup SQLSetupTool SQLMigration DeadlockCollector SSRSDeploymentTool

Boundaries

Scope & What's Next

TasksqmSQLTool?
AlwaysOn auto-repair✓ Yes - Repair-sqmAlwaysOnDatabases
AG-aware backup✓ Yes - Invoke-sqmUserDatabaseBackup
Instance inventory✓ Yes - Invoke-sqmInstanceInventory
SA hardening✓ Yes - Invoke-sqmSaObfuscation
Install SQL Server- No → SQLSetupTool
Set up AlwaysOn- No → AlwaysOnSetup
Migrate databases- No → SQLMigration
Deploy SSRS reports- No → SSRSDeploymentTool
Deadlock collection GUI- No → DeadlockCollector

What sqmSQLTool deliberately isn't

ℹ Not an installer tool - sqmSQLTool configures and monitors. Installation and setup are handled by SQLSetupTool and AlwaysOnSetup.
ℹ Not a monitoring system - sqmSQLTool provides data and reports. Splunk, SCOM, or your own monitoring consumes that data.
✓ Extensible - new company functions follow the sqm* pattern. Logging, config, Pester tests - the conventions are already established.

Reference

Quick Reference - The Commands That Matter Most

The commands a DBA needs daily or weekly.

Daily operations

TaskCommand
Check AG healthGet-sqmAgHealthReport
Check blockingGet-sqmBlockingReport
Long queriesGet-sqmLongRunningQueries
Disk spaceGet-sqmDiskSpaceReport
Instance checkGet-sqmSQLInstanceCheck
AG repairRepair-sqmAlwaysOnDatabases
User DB backupInvoke-sqmUserDatabaseBackup -All

Weekly / monthly

TaskCommand
DB health reportGet-sqmDatabaseHealth
Patch levelInvoke-sqmPatchAnalysis
Missing indexesGet-sqmMissingIndexes
VLF/autogrowthGet-sqmAutoGrowthReport
Login auditInvoke-sqmLoginAudit
Sysadmin checkGet-sqmSysadminAccounts
InventoryInvoke-sqmInstanceInventory

Summary

Summary & Next Steps

AlwaysOn repair, fully automatic

Repair-sqmAlwaysOnDatabases + New-sqmAlwaysOnRepairJob. An AG DB failure gets repaired automatically by an Agent job.

AG-aware backup

sys.fn_hadr_backup_is_preferred_replica checked. No more double backups on primary and secondary.

Audit-ready in minutes

SA obfuscation, login audit, sysadmin report, CHECKDB status - every compliance question answered.

Fleet management

Pipeline-capable functions: inventory, patch level, health report for N instances at once.

A company standard

87 functions, Pester tests, consistent logging - a module, not a script collection.

Installation

# Install from a share (recommended)
Install.cmd            # auto-detects admin -> AllUsers

# Manually as admin (AllUsers)
.\Install.ps1 -Scope AllUsers

# Manually, CurrentUser
.\Install.ps1 -Scope CurrentUser

# Set the configuration
Set-sqmConfig -OutputPath "D:\DBA-Reports"

Links & Resources

GitHubgithub.com/JankeUwe/sqmSQLTool
Websitewww.powershelldba.de
Import the moduleImport-Module sqmSQLTool
SQLSetupTool - Base install AlwaysOnSetup - HA configuration SQLMigration - Database migration DeadlockCollector - Deadlock capture ReportDeploymentTool - SSRS deployment