AI‐Powered SQL Server DBA: Automating Your Work with GitHub Copilot (Fourth Edition) - Ahsan-Research/Dev GitHub Wiki
Author: Ahsan Kabir
(Fourth Edition – 2026)
AI‐Powered SQL Server DBA: Automating Your Work with GitHub Copilot
Fourth Edition – 2026
Copyright © 2026 by Ahsan Kabir / Country Formation Inc. All rights reserved.
No part of this publication may be reproduced, distributed, or transmitted in any form or by any means, including photocopying, recording, or other electronic or mechanical methods, without the prior written permission of the publisher, except in the case of brief quotations embodied in critical reviews and certain other noncommercial uses permitted by copyright law.
For permission requests, contact the author via the official GitHub repository or professional channels.
© 2026 Ahsan Kabir, Country Formation Inc. All rights reserved.
This training material is intended for professional development purposes.
Always test AI-generated code in non-production environments before deployment.
Fourth Edition – October 2026
This edition is written for senior SQL Server DBAs, platform engineers, and data architects working in regulated US and European enterprises. It reflects:
- SQL Server 2025 (Compatibility Level 170), Vector Search, and In-Database AI capabilities
- Latest GitHub Copilot Agent Mode, workspace agents, and enterprise policy controls
- Updated safety practices for GDPR, HIPAA, SOX, and SOC 2 environments
- A complete 30-day hands-on training path with human-in-the-loop verification
What Changed in the Fourth Edition
- Strengthened career and strategic framing for AI-era DBAs
- Added the full 7-Step AI SQL Verification Pipeline as a core survival manual
- Expanded coverage of autonomic agents, Medallion architecture, and multi-agent workflows
- Cleaner structure, professional TOC, and expanded Appendix (Glossary, Prompt Cheat Sheet, Keyword Index)
- Explicit Sandbox-vs-Production policy and SQL Server 2025 Vector examples
- Copyright Page
- Dedication
- Foreword
- Preface: Why This Book Exists
- Introduction: How to Use This Book
- Acknowledgments
- Chapter 1: SQL Server Careers in the Age of AI — Risk, Reinvention, or Growth?
- Chapter 2: From SQL Server Data to Autonomic DBA Agents
- Stop Letting AI Nuke Your Production Server: The 7-Step AI SQL Verification Pipeline
-
Day 1: Setting Up the AI Workbench
- Theory · Copilot Focus · LAB 1
-
Day 2: System Prompting & Enterprise Guidelines
- Theory · Copilot Focus · LAB 2
-
Day 3: Schema RAG & Context Injection
- Theory · Copilot Focus · LAB 3
-
Day 4: Converting Business Requirements into Data Models
- Theory · Copilot Focus · LAB 4
-
Day 5: Understanding Index Mechanics with AI
- Theory · Copilot Focus · LAB 5
-
Day 6: Unit Testing T-SQL Code
- Theory · Copilot Focus · LAB 6
-
Day 7: Weekly Review & Retrospective
- Theory · Copilot Focus · LAB 7
- Day 8: Non-SARGable Query Refactoring
- Day 9: Cursor Removal & Set-Based Refactoring
- Day 10: Parsing Execution Plan XMLs
- Day 11: Deciphering Deadlock XML Graphs
- Day 12: TempDB Contention & Allocation Bottlenecks
- Day 13: Parameter Sniffing & Query Store Analysis
- Day 14: Dynamic Management View (DMV) Deep Dive
- Day 15: Performance Tuning Milestone & Benchmark
- Day 16: Automated Index Maintenance Scaffolding
- Day 17: PowerShell & dbatools Integration
- Day 18: Automated Disaster Recovery (DR) Readiness Checks
- Day 19: Security Auditing & Permission Automation
- Day 20: Automated Partitioning & Data Archiving
- Day 21: Always On Availability Groups (AG) Health Monitoring
- Day 22: SQL Server Agent Job Automation
- Day 23: Introduction to Multi-Agent Architectures (HAMS)
- Day 24: Least-Privilege AI Authentication Architectures
- Day 25: Automated Pre-Deployment CI/CD Guardrails
- Day 26: Building an Automated Migration Pipeline
- Day 27: Self-Healing Incident Management
- Day 28: FinOps & Cloud Compute Cost Optimization
- Day 29: Taking the Backlog to Zero
- Day 30: Final Capstone Project & Certification
- LAB 1: The Foundation — Setting Up Your AI Co-Pilot in SSMS & Azure Data Studio
- LAB 2: The Query Whisperer — Real-Time Execution Plan Analysis & Tuning
- LAB 3: The Legacy Surgeon — Refactoring 1,000-Line Cursor Nightmares
- LAB 4: The Automation Architect — Generating Production-Ready PowerShell & dbatools Scripts
- LAB 5: The HA/DR Commander — Always On AG Troubleshooting & Runbooks
- LAB 6: The Security Sentinel — Automating Audits & Least-Privilege Remediation
- LAB 7: The 10x Orchestrator — Large-Scale Migrations & Multi-Agent Workflows
- Standardized Authoring Framework for Individual Articles
- The AI DBA Guardrail Checklist (Production Safety Standard)
- Conclusion
- A. Glossary of AI + SQL Server Terms
- B. GitHub Copilot Prompt Cheat Sheet for DBAs
- C. References and Further Reading
- D. About the Author – Ahsan Kabir
AI generates.
The SQL Server engine validates.
The human DBA governs.Never trust a suggestion blindly.
Always verify the target server and database.
Always read the SQL before it runs.
Always keep production behind real change control.
GitHub Copilot Business / Enterprise Features (2026)
Prefer Copilot Business or Enterprise over individual plans for any regulated environment.
Key capabilities relevant to this book:
- Workspace agents and multi-file edit confidence
- Enterprise policy controls and content exclusion
.copilotignoreand organization-level data protection- Auditability and admin governance
Individual plans may retain code for model training — avoid them for production schema or sensitive environments.
Primary Audience
- Experienced SQL Server DBAs (on-premises, hybrid, and Azure SQL)
- Database developers and data engineers moving deeper into operations
- Platform owners and team leads introducing AI tools responsibly
- IT / Security leaders evaluating GitHub Copilot Business or Enterprise
What You Will Learn
- How to use GitHub Copilot Agent Mode safely under real change control
- A complete 7-Step Verification Pipeline that prevents AI from nuking production
- A practical 30-day skill migration path from Traditional Operator to AI Orchestrator
- Schema-aware prompting, RAG, multi-agent workflows, and least-privilege AI authentication
- How to keep humans in the approval loop while dramatically increasing output
Prerequisites
- Solid T-SQL, indexing, and execution-plan knowledge
- Familiarity with SQL Server security and high availability concepts
- Access to a sandbox SQL Server 2019+ (2022/2025 preferred) instance
- GitHub Copilot Business or Enterprise license (strongly recommended)
Let me start with a question that makes half the room shift uncomfortably in their seats.
How many of you have quietly wondered, in the last twelve months:
“Is AI going to make my job disappear?”
Be honest. I’ve asked this question in rooms full of senior DBAs, principal engineers, and architects. The silence is always longer than people expect.
Here’s the truth most conference speakers are too polite to say out loud:
AI is not coming for your job. But the version of your job that only writes T-SQL and stares at execution plans is under serious pressure.
The comfortable middle is disappearing. The people who treat AI as a threat will feel the squeeze. The people who treat AI as a force multiplier will accelerate faster than they ever thought possible.
Today is not a fear session. Today is a clarity session.
By the time we finish, you will leave with a clear-eyed view of:
- What is actually at risk
- What is becoming more valuable
- How to reinvent your positioning
- And a practical skill stack for the next three to five years
The biggest mistake I see is people asking the wrong question.
They ask: “Will AI write better T-SQL than me?”
The better question is: “Will AI make the routine parts of my job so cheap and fast that the market no longer pays premium rates for them?”
The answer is already becoming yes.
What is genuinely at risk:
- Writing straightforward SELECT, INSERT, UPDATE, DELETE statements
- Generating basic stored procedures and views
- Creating first-draft documentation
- Producing simple migration scripts
- Answering “how do I write this query?” questions for the hundredth time
These tasks are being compressed. Dramatically.
I have watched junior and mid-level developers who used to spend four hours writing and debugging a moderately complex procedure now get a strong first draft in eight minutes. The market will eventually notice.
But here’s the critical distinction most people miss:
AI is excellent at generating code. It is still terrible at owning outcomes.
It does not get paged at 2:15 a.m. It does not sit in the war room when the CEO is asking why the order system is down. It does not carry the political capital (or the scars) of having made a production change that went wrong.
That ownership layer is still human. And it is becoming more valuable, not less.
Every technological shift creates a temporary window where the people who adapt early capture disproportionate advantage.
We saw it with:
- The move from on-prem to virtualization
- The shift to the cloud
- The rise of DevOps and infrastructure-as-code
- The explosion of data engineering
AI is the next one. And for SQL Server professionals, the window is still open — but it is not infinite.
The new high-value work is moving upstream
The market is beginning to pay for people who can:
- Design systems that are safe with AI in the loop
- Build verification pipelines so AI-generated code doesn’t nuke production
- Translate business problems into data architecture that AI tools can actually help with
- Own the reliability, security, and performance outcomes of AI-assisted systems
- Mentor teams on when to trust the model and when to ignore it
In short: the people who become AI-fluent system thinkers are pulling away from the people who remain pure syntax generators.
I am watching three distinct trajectories form in the market.
Path 1: The Declining Path
“I just want to keep writing T-SQL the way I always have.”
These professionals are not being fired tomorrow. But their leverage is quietly eroding. Over time, the work they do becomes easier to outsource, automate, or assign to more junior people armed with strong AI tools.
Path 2: The Reinvention Path (Most Recommended)
“I will become the person who makes AI safe and productive in a SQL Server environment.”
These professionals are learning:
- Prompt engineering specific to SQL Server workloads
- Execution plan analysis with AI as a sparring partner
- Building internal AI assistants grounded on their company’s schema, standards, and runbooks
- Governance, least privilege, and audit trails for AI-generated changes
- Measuring real impact (logical reads, MTTR, regression rates) instead of vanity metrics
This path turns AI from a threat into a career accelerator.
Path 3: The Growth Path
“I will move upstream into architecture, platform engineering, and AI-augmented data systems.”
These people are combining deep SQL Server expertise with:
- Vector search and hybrid relational + semantic architectures (SQL Server 2025)
- Designing RAG systems that sit on top of operational databases
- Building internal developer platforms and AI-assisted tooling
- Reliability engineering and chaos practices for data platforms
- Cross-functional influence (working closely with product, security, and AI teams)
This is where the highest leverage and compensation growth is currently appearing.
If I were mentoring a senior DBA or developer today, this is the stack I would push them to build:
Layer 1 – Core SQL Server Mastery (Still Non-Negotiable)
- Deep understanding of the query optimizer, statistics, and cardinality estimation
- Locking, blocking, isolation levels, and the new optimized locking features
- Query Store, Extended Events, and wait analysis at a forensic level
- High availability, disaster recovery, and operational excellence
AI does not replace this. It amplifies people who already have it.
Layer 2 – AI Literacy for Database Professionals
- Prompt patterns that produce reliable T-SQL instead of hallucinated syntax
- Verification pipelines (the 7-step process many of you have heard me talk about)
- Understanding of embeddings, vector indexes, and when to use them
- Awareness of model limitations, context windows, and failure modes
Layer 3 – Systems Thinking & Governance
- Designing approval workflows for AI-generated changes
- Least-privilege models for AI agents
- Auditability and compliance in AI-assisted environments
- Measuring outcomes that the business actually cares about
Layer 4 – Influence & Communication
- Explaining complex database behavior to non-technical stakeholders
- Framing AI adoption in terms of risk reduction and business value
- Mentoring teams so the organization raises its collective floor
The professionals who stack all four layers are becoming extremely difficult to replace.
Talk is cheap. Here’s a concrete starting point that maps directly onto the 30-day hands-on roadmap in this book.
Days 1–10 → PHASE 1: Foundations & Prompt Engineering
- Track generation vs. judgment work
- Force every AI draft through the 7-Step Verification Pipeline
- Complete Days 1–7 (Workbench, System Prompts, Schema RAG, Indexing, Unit Testing, Prompt Bank)
- Document three wins and three near-misses
Days 11–20 → PHASE 2 + early PHASE 3: Performance & Automation
- Build your personal high-quality prompt library
- Practice execution-plan analysis with Copilot as sparring partner
- Work through Days 8–18 (SARGability, Cursors → Sets, Plans, Deadlocks, TempDB, Parameter Sniffing, DMVs, Index Maintenance, dbatools, DR checks)
- Create a team-ready AI code checklist
Days 21–30 → PHASE 3 + PHASE 4: Enterprise Guardrails & Capstone
- Complete Days 19–30 (Security Audits, Partitioning, AG Health, Agent Jobs, Multi-Agent HAMS, Least-Privilege AI, CI/CD Guardrails, Migration Pipeline, Self-Healing, FinOps, Backlog Zero, Capstone)
- Own one internal AI improvement (prompt library, verification checklist, or RAG experiment)
- Present a short internal session: “How we use AI safely with SQL Server”
- Move one area of your work from pure execution into design / platform thinking
Small, consistent moves compound faster than dramatic overnight transformations.
The most important change is not technical.
It is this:
Stop asking “Will AI take my job?”
Start asking “How do I become the person who makes AI work in this environment without creating new risks?”
The first question is passive and fear-based. The second question is active and agency-based.
In every technological transition I have lived through, the people who adopted the second question early ended up with more interesting work, more influence, and better compensation.
The people who stayed in the first question often spent years feeling anxious and under-leveraged.
SQL Server careers are not dying. They are being re-priced.
Routine syntax generation is becoming cheaper. Judgment, ownership, system design, and the ability to keep complex systems reliable in an AI-assisted world are becoming more expensive.
You get to choose which side of that equation you stand on.
You can treat AI as a threat and try to protect the old version of the job. Or you can treat it as the most powerful junior team member you’ve ever had — one that needs constant supervision, clear standards, and strong adult oversight — and use it to raise the ceiling of what you can deliver.
I know which path I’m betting on.
A Fantastic, Human Walkthrough of: From SQL Server Data to Autonomic DBA Agents
Empowering SQL Server 2025 Enterprise DBAs with GitHub Copilot
Author Credit: Ahsan Kabir
Mike is a Senior SQL Server DBA at a Fortune 500 logistics firm in Illinois. His Apple Watch vibrates like a taser.
Panic Duty: PROD-ORDERS — SEV 1 — Blocking — 400 sessions — Orders not moving
Mike has seen this movie. He VPNs in half-asleep, fires up SSMS, runs sp_WhoIsActive, finds the lead blocker — a rogue reporting query from the finance team — kills it, rebuilds a fragmented index on Orders.Status, and prays to the SQL Gods.
By 4 AM it’s green. By 9 AM his VP wants a 5-whys RCA. By Friday, it’s a different query, same chaos.
Mike is brilliant. But Mike is not a scale-out service. He can’t watch 47 servers, 800 databases, and 3 Always On Availability Groups 24/7/365.
This chapter is Mike’s resignation letter from 2 AM calls. It’s how we turn Mike from a Human Alert System into a Manager of a Fleet of DBA Agents.
Let’s walk the journey left-to-right, like the data actually flows.
Panel: SQL Server 2025 DBA Data Sources
Before AI can be smart, it has to be a professional hoarder. For years our data lived like tools in a messy garage — Query Store here, a DMV that resets on restart there, and that file named final_final_log_2019_REALLY_FINAL.txt on a file share.
SQL Server 2025 says: Enough. Bring it all to one dock.
- OLTP Databases: The money-makers. The actual orders, claims, trades.
- Always On Replicas: Your safety net. Is it really in sync, or is it 14 seconds behind and lying to you on the dashboard?
-
SQL Server Audit Logs: Your security camera. Who gave
db_ownerto an intern last Tuesday? - Query Store Data: The black-box flight recorder. It remembers that query that went from 50ms to 5 seconds after that deployment.
-
DMVs & Perf Counters: The vitals —
sys.dm_os_wait_stats,sys.dm_exec_query_stats. This is how SQL Server says “I’m choking on memory.” - SQL Agent Jobs: Did last night’s index maintenance actually run or did it fail silently at 2%?
- OS & Cluster Metrics: Because sometimes it’s not SQL. It’s Windows. It’s VMware. It’s the SAN your storage team swears is “fine.”
-
T-SQL & Schema Scripts: That 400-line
usp_ProcessOrdersmonster proc nobody dares to touch.
For my USA Enterprise folks: SOX, HIPAA, PCI — auditors don’t want a good story. They want proof. If you didn’t collect it, it didn’t happen. This left panel is your audit-proof collection layer.
Panel: Medallion Data Architecture (DBA Knowledge Lake) — Storage & Processing
This is the heart. Borrowed from the lakehouse world and it’s genius. Think of it as a three-star Michelin kitchen.
BRONZE — Raw DBA Data
We dump everything exactly as it is. No judgment. We keep historical baselines.
Bronze is like your teenager’s bedroom. Everything is in there. Good luck finding your car keys.
- Ingest performance, logs, trace files in native formats
- Keep historical baseline records — So you can say “Whoa, this wait type was 2% last quarter, now it’s 60%”
SILVER — Cleaned & Structured
Now Gordon Ramsay walks in. We wash, chop, normalize.
- Parse audit & error logs — Turn “Error: 1205” into “Deadlock: OrderInsert vs. InventoryUpdate”
- Normalize metrics & DMV datasets — Make CPU from 3 sources speak the same language
- Map wait stats & query plans — Connect the “I’M WAITING” to the “HERE’S WHY”
- Identify anomalies & patterns — “Houston, we have a pattern: Every month-end close, tempdb explodes”
This is where junior DBAs become senior. You stop staring at one number and start seeing the movie.
GOLD — Refined Enterprise DBA Insights
The Chef’s Table. The only table the CIO is allowed to see. Single source of truth.
- Curate active alerts & performance baselines — No more 5,000 email alerts. Only “this actually matters”
- Structure optimization & index maps — “You have 127 duplicate indexes. Yes, really. 127.”
- Build troubleshooting playbooks — That runbook Mike scribbled at 2 AM is now executable code
- Consolidated DBA single source of truth
Pro Tip: Gold is what you show in the QBR. It translates DBA nerd-speak to dollars: “Risk of P1 outage due to index fragmentation down 73%.”
Bottom Bars: SQL Server 2025 In-Memory & Vector Engines + T-SQL, DMV Analytics & Agent Platform
Look at that glowing pipeline at the bottom. That’s the secret sauce.
Old SQL Server was a brilliant accountant. Amazing at counting rows. New SQL Server 2025 is an AI-native brain.
How? Vector Search.
Vectors let SQL Server understand meaning, not just LIKE '%slow%'. You can ask “Find me queries that behave like this bad blocking query” — even if table names are different. That’s semantic search, inside the engine.
And those four pillars at the very bottom:
- Local & Hybrid Deployments: Dallas data center or Azure — works. No forced cloud religion.
- Always On Availability Groups: Because HA isn’t optional when you process $2M of orders an hour.
- AI-Ready DB Engine & Vector Search: Your database is now also a vector database.
- In-Database AI / ML Services: Stop moving 2TB to Python. Bring the model to the data. Faster, cheaper, secure.
See that green real-time data arrow looping back? It’s not a nightly ETL. It’s streaming. The second Query Store logs a bad plan, it flows Bronze → Silver → Gold in seconds.
Panel: Semantic / Context Layer (In-Database & MCP)
This is what separates a dangerous AI from a trusted enterprise DBA.
Imagine a super-smart intern who knows every T-SQL trick but doesn’t know your rules. He drops a prod index because “it looked unused.” You’re fired. He’s fired. Everyone’s fired.
The Semantic Layer is the bouncer, the safety manual, and the wise old mentor:
- Schema & Metadata: “That Orders table is 800M rows. Don’t you dare SELECT *.”
- Wait Stats & Performance Metrics: Contextualized — “CXPACKET is high, but in OUR shop that’s normal with MAXDOP 8”
- Security & Permission Models: “Agent can suggest GRANT, but can never execute it without human approval”
- Index & Query Plans: Historical wisdom — what worked last time
- Backup & Restore History / Disaster Recovery Status: “Last successful restore test was 22 days ago. We are out of SOX compliance, boss”
- T-SQL Best Practices & Guardrails: Your company’s Thou Shalt Nots — No heaps, no cursors, no SHRINKDATABASE like it’s 2005
- DBA Agent Rules & Workflows: “Any schema change on PROD-ORDERS needs 2 approvals + ServiceNow CHG ticket”
For USA experts: This layer is where you enforce SOX controls. AI doesn’t bypass compliance. It enforces it better than humans.
Panel: GitHub Copilot DBA Agents (Consume Context via SQL Agent & MCP)
Now the stars. That glowing purple panel on the far right.
Not generic ChatGPT wrappers. These live where you live:
- GitHub Copilot Agent: Your chat buddy
- SQL Server DBA Agent: The specialist who actually passed the 70-764
- GitHub Copilot for VS Code / SSMS 22: Right inside SSMS 22. Highlight slow query, right-click → “Explain and Tune This”
And the checklist that will make every DBA cry happy tears:
- ✅ Auto-Tune Queries: Not just “add index.” Rewrite query, test vs. Query Store, show before/after plan with cost
- ✅ Resolve Blocking & Deadlocks: Finds the root blocker, not just the victim
- ✅ Manage Backups & DR: “Your RPO for Finance DB is at risk. Last log backup was 47 mins ago” — before audit fails
- ✅ Optimize Index & Statistics: Deletes that index you created 3 years ago for a one-time report that has been burning writes ever since
- ✅ Deploy Schema Changes Safely: Checks for 3-hour long transaction that will block your ALTER TABLE. Suggests resumable online.
Panel: Self-Healing, Autonomous DBA Actions + Enterprise DBA Agent MCP
MCP — Model Context Protocol is just a fancy, secure handshake. It lets Copilot ask SQL Server for context in a locked-down, auditable way.
So at 2:13 AM:
- Real-time data flows in
- Silver recognizes: “Same pattern as last month-end”
- Semantic Layer says: “Approved playbook — you may auto-kill reporting query X after 60s blocking on PROD-ORDERS”
- Agent executes, logs, and Slacks Mike: “Hey Mike — Handled blocking at 2:13 AM by killing session 87 (Report_X). Root cause: missing index on Orders.Status. Recommendation created in GitHub. Go back to sleep, champ.”
- Mike sleeps. His wife is happy. His CIO is happy.
Old World: Data → Alerts → Human DBA at 2 AM → Manual Fix → Docs (maybe)
New World: Data → Knowledge Lake (Bronze/Silver/Gold) + Guardrails → Autonomous Agents → Human DBA as Reviewer & Strategist
You don’t lose your job. You lose the soul-crushing parts of it. You gain your nights, your weekends, and your seat at the strategy table.
Mike is no longer fixing blocking. He’s presenting to the board how his agent fleet saved $400k in downtime.
Welcome to SQL Server 2025. Your weekends are waiting.
Listen up. Grab a coffee. No — grab a real coffee. The kind that could strip paint. Pull up a chair. We need to have a serious talk about your shiny new favorite coworker: AI.
Whether you’re using GitHub Copilot, ChatGPT, Claude, or that shiny new agent that promises to “optimize everything while you sleep,” you’ve probably noticed something.
AI is basically a wildly overconfident junior developer who just mainlined three Red Bulls, read every Stack Overflow answer ever written, and somehow still thinks LIMIT 10 is valid T-SQL.
It writes beautiful, perfectly indented, highly confident T-SQL at the speed of light. It’s polite. It never complains. It never rolls its eyes when you ask the same question for the third time.
And if you blindly paste its code into SSMS at 2:15 AM during a Sev-1 incident… it will absolutely, unequivocally, nuke your production server.
I once watched a perfectly formatted, AI-generated query take down a core logistics pipeline on a Tuesday night. The query looked gorgeous. Indentation was perfect. Comments were thoughtful. The AI even said “This should perform well under load.”
What it didn’t understand was our data skew. It decided a nested loop join was a fantastic idea for a 40-million-row table that lived on the wrong side of a statistical nightmare. The resulting PAGEIOLATCH_SH storm was so bad the monitoring tools started looking like a Christmas tree. The CTO’s Slack messages went from polite concern to pure uppercase rage in under four minutes.
Here is the golden rule of the modern data estate:
AI generates. The DBA verifies. The database proves.
If you want to survive the AI era without frantically updating your résumé at 3 a.m., you need a rigid, non-negotiable gauntlet for every single query your bot spits out.
Welcome to the 7-Step AI SQL Verification Pipeline. Treat this as your daily survival manual. Laminate it. Tattoo it. Whisper it to junior developers like a sacred oath.
(aka “Did AI Forget Which Planet We’re On?”)
AI consumes the entire internet. That means it suffers from a severe case of multiple-personality disorder when it comes to SQL dialects.
If I had a dollar for every time Copilot confidently handed me a SQL Server query containing LIMIT 10, I could buy a small island and retire. AI loves PostgreSQL and MySQL. It frequently tries to force their syntax into Microsoft SQL Server like a toddler trying to jam a square peg into a round hole while smiling and saying “This is fine.”
Real-life war story: A junior developer once deployed an AI-generated script that used STRING_AGG on a SQL Server 2016 instance that only understood FOR XML PATH. The error message was long. The silence on the team call was longer. The AI had cheerfully used a function that didn’t exist on the target version because nobody told it the compatibility level was still stuck in 2016.
What you must do:
- Check the dialect immediately. Did it use
LIMITinstead ofTOP? - Check compatibility level. AI adores shiny new functions (
GREATEST,LEAST,GENERATE_SERIES, etc.) that your older instances will violently reject. - Explicitly tell the AI the target in every prompt:
-- Target: Microsoft SQL Server 2025, Compatibility Level 170
-- Edition: Enterprise
-- Do NOT use PostgreSQL, MySQL, or Oracle syntaxMake the AI play by your rules. It will still try to cheat. Catch it early.
(The Lie Detector)
AI doesn’t look at execution plans. It looks at syntax and vibes. It has absolutely no idea that the elegant JOIN it just wrote is about to request 40 GB of memory grant and then spill to tempdb like a drunk uncle at a wedding.
You take that shiny AI query, highlight it, and hit Ctrl + M (Include Actual Execution Plan). Then you stare at the truth.
What you’re hunting for (the Silent Killers):
- Fat arrows thicker than a redwood tree → millions of rows being shoved around
- Unintended scans hiding behind an innocent-looking WHERE clause
- Key Lookups caused by the AI’s favorite hobby:
SELECT *when it only needed three columns - Implicit conversions — AI loves comparing a VARCHAR column to an NVARCHAR parameter. That little yellow warning triangle is the database’s way of saying “I’m about to set your CPU on fire for fun.”
War story: I once watched an AI rewrite a report query that looked 40% faster in the developer’s test database (which had 2% of production data). The actual plan in production showed a key lookup storm so severe that the server started rejecting new connections. The AI had been very proud of its “clean” code. The production server was less impressed.
Never trust a pretty plan. Force the actual one.
(Kiss Your Indexes Goodbye)
“SARGable” means Search ARGument ABLE. In plain English: “Did you write this so SQL Server can actually use the damn index?”
AI is notoriously terrible at this.
Imagine looking for someone named “Smith” in a phone book. Easy. Now imagine looking for someone whose last name reversed is “htimS.” You have to read the entire book. That is exactly what a non-SARGable predicate does.
Classic AI crime:
-- Straight to DBA jail
WHERE YEAR(OrderDate) = 2026The grown-up version:
WHERE OrderDate >= '20260101'
AND OrderDate < '20270101'Audit every WHERE and JOIN the AI writes. If a column is trapped inside YEAR(), LEFT(), ISNULL(), DATEDIFF(), or any other function, rewrite it before it kills your seeks.
I’ve seen AI wrap indexed columns in functions so enthusiastically that a query that should have been a 3-millisecond seek turned into a 12-second scan. The AI still thought it was being helpful.
(The Two-Faced Query)
AI assumes data is perfectly distributed — like a beautiful, even, textbook histogram.
Veteran DBAs know real-world data looks like a Jackson Pollock painting that got into a fight with a random number generator.
When SQL Server compiles a procedure, it “sniffs” the first parameter and builds a plan for that value.
Your AI query tests perfectly with CustomerID = 1 (Bob’s Bakery, three orders). SQL builds a lightning-fast Nested Loop plan.
Then at 9:07 AM the same cached plan gets reused for CustomerID = 900000 (MegaCorp, 45 million rows). The server starts making sounds no database should ever make.
What you must do: Test the candidate query against both sparse and dense values. Force different parameter values. Watch the plan flip. If it flips wildly, intervene with OPTION (RECOMPILE), OPTIMIZE FOR UNKNOWN, local variable masking, or a proper plan guide.
I once spent an entire night chasing a query that was fast for 99% of customers and a complete disaster for the top 1%. The AI had never met our top 1%. Real data has opinions. Listen to them.
(The 2:00 PM Traffic Jam)
AI does not care about your blocking chains.
Ask it to “update the status of all shipped orders” and it will cheerfully hand you one giant UPDATE statement that escalates to an exclusive table lock the moment it hits production during business hours.
Your web app freezes. Your order-entry system starts timing out. Your CTO starts typing in all caps. Your phone starts vibrating like it’s possessed.
What you must do:
- Never update millions of rows in one transaction.
- Force the AI to rewrite large modifications as batched updates (
WHILE+UPDATE TOP (5000)or similar). - Check isolation levels. Prefer RCSI or SQL Server 2025’s Lock After Qualification (LAQ) when appropriate.
- Keep transactions short and boring.
I once watched an AI-generated overnight “cleanup” job take exclusive locks that blocked the morning sales team for 47 minutes. The AI had been very proud of its “efficient set-based solution.” The sales team had other words for it.
(Don’t Be “That” DBA)
Did Copilot just hardcode a password? Did ChatGPT write dynamic SQL that is wide open to SQL injection?
Yes. Yes it did. And it did it with a smile.
AI will happily concatenate strings to build dynamic SQL. This is how “Little Bobby Tables” drops your student database (and your career).
Non-negotiables:
- Never allow
EXEC(@SQL)with raw input. Forcesp_executesqlwith proper parameters. - Scan every generated script for secrets, connection strings, and unmasked credentials.
- Use a strict
.copilotignore(or equivalent) so your IDE doesn’t accidentally beam production connection strings and backup files to the mothership. - Treat every AI-generated dynamic SQL statement as guilty until proven parameterized.
I once saw a developer paste an AI-generated migration script that contained a clear-text SA password in a comment “for convenience.” The security team’s reaction was… educational.
(The Ultimate Truth)
Never look at a query, nod thoughtfully, and deploy it because “the code looks optimized.”
We deal in facts, not feelings.
Before you approve any AI code, wrap it with the holy grail:
SET STATISTICS IO ON;
SET STATISTICS TIME ON;Then look at the Messages tab like your job depends on it (because it does).
You’re looking for:
- Logical reads (the real currency of query cost)
- Physical reads
- CPU time
- Elapsed time
- Whether the numbers actually improved versus the previous version
If the logical reads didn’t drop meaningfully, the AI did not fix the problem — it just rearranged the deck chairs on the Titanic and called it optimization.
I have rejected more “optimized” AI queries than I can count because the logical reads stayed exactly the same (or got worse). The numbers never lie. Pretty code does.
AI is an incredible tool. I use it every single day. It takes the grueling, repetitive grunt work out of our lives and lets us focus on the hard problems.
But remember this:
A copilot is there to assist the pilot. It is not supposed to fly the plane while you take a nap in first class and hope for the best.
Use this 7-step pipeline every single time.
Validate the syntax. Check the actual execution plan. Enforce SARGability. Test for parameter sniffing. Respect concurrency. Guard the security perimeter. Measure the real impact.
Do that, and you’ll look like a wizard who somehow always has the answers.
Skip it… and you’ll be updating your résumé while the CTO is still typing in all caps.
Happy tuning. And for the love of all that is holy — keep the coffee hot and the execution plans open.
ils | Single-handed ticket execution | Orchestrating Writer/Auditor Multi-Agent teams |
This book is designed as a complete instructor-led or self-paced training handbook for US and European enterprise DBAs.
Recommended Order
- Read Part I (Chapters 1–2 + the 7-Step Verification Pipeline) first. This gives you the mindset and the non-negotiable safety rules.
- Follow the 30-Day Roadmap (PHASE 1 → PHASE 4) sequentially. Each day has Theory, Copilot Focus, and a hands-on LAB.
- Use PHASE 5 as standalone production-grade labs for workshops or internal training.
- Keep the Appendix (Glossary, Prompt Cheat Sheet, Keyword Index) open while you work.
Time Estimates
- Part I (strategic + verification pipeline): 4–6 hours
- Each Day module: 3–4 hours (Theory 60–90 min + Lab 90–120 min)
- Full 30-day path: roughly 90–120 hours of focused work
- Capstone (Day 30): 4–6 hours
Sandbox Requirements (Non-Negotiable)
- A dedicated non-production SQL Server instance (Developer Edition, Azure SQL, or restored copy)
- Never connect Copilot Agent Mode to a production server on day one
- Always keep a human approval gate before any schema or data-changing statement
Sandbox vs Production Policy
Sandbox = Experiment freely, break things, measure impact.
Production = Only after the full 7-Step Verification Pipeline + change ticket + peer review.
Treat every AI-generated script as untrusted until you have proven it against real data volumes, real concurrency, and real business rules.
Standard Day Module Template (used throughout the detailed labs)
Every major hands-on day follows this consistent structure for clarity and safety:
| Block | Purpose |
|---|---|
| Learning Objectives | What you will be able to do by the end of the session |
| Prerequisites | Tools, permissions, and prior knowledge required |
| Estimated Time | Typical duration for theory + lab |
| Safety Checkpoint | Non-negotiable rules before running any AI-generated code |
Treat the Safety Checkpoint as a hard stop. Do not skip it.
SQL Server 2025 introduces native vector support and deeper in-database AI capabilities. These features let you keep semantic search and AI workloads close to the data.
Example 1 – Creating a vector column and index
-- Target: SQL Server 2025, Compatibility Level 170
ALTER TABLE dbo.SupportTickets
ADD Embedding VECTOR(1536); -- dimension matches your embedding model
CREATE VECTOR INDEX IX_SupportTickets_Embedding
ON dbo.SupportTickets (Embedding)
WITH (METRIC = 'cosine', TYPE = 'DiskANN');Example 2 – Semantic similarity search prompt for Copilot
@workspace Using the SupportTickets table that has a VECTOR(1536) column named Embedding,
write a T-SQL query that finds the 5 most similar open tickets to a given ticket ID
using VECTOR_DISTANCE with cosine metric. Include TicketID, Title, and Distance.
Target: SQL Server 2025 only. Do not invent functions.
Example 3 – Safety rule for Vector + AI agents
- Never let an agent automatically create or drop vector indexes on production tables without a change ticket.
- Always test VECTOR_DISTANCE queries against realistic data volumes.
- Keep embedding generation outside the critical transaction path.
Treat these examples the same way you treat any other AI-generated code: run them through the 7-Step Verification Pipeline.
- Theory: Understand how GitHub Copilot, Copilot Chat, and LLMs interact with IDEs (Azure Data Studio, VS Code, and SSMS extensions). Understand token limits and context windows.
-
Copilot Focus: Setting up workspace extensions, inline completions, and workspace context variables (
#file,@workspace). -
LAB 1:
- Install GitHub Copilot in SSMS 22 / Azure Data Studio (latest) or VS Code.
- Create a
.copilotignorefile to ensure sensitive configuration files and connection strings with explicit passwords are excluded from AI telemetry. - Verify inline completion in a
.sqlbuffer by typing a prompt comment:-- Write a T-SQL query to list top 10 databases by data file size on disk
-
Theory: AI without guardrails generates generic code that violates corporate standards. Learn system prompting to enforce strict coding style guides (explicit schema prefixes,
NOCOUNT ON, camelCase, standardized error handling). - Copilot Focus: Crafting reusable system prompt templates for enterprise database development.
-
LAB 2:
- Build a custom prompt file named
DBA_Rules.mdin your workspace repository. - Define rules: Always use
ANSI_NULLS ON, enforce camelCase column names, require explicit JOIN syntax, and always include schema names (dbo.). - Prompt Copilot Chat using the rules file to generate a multi-table schema for an order-processing engine.
- Build a custom prompt file named
- Theory: LLMs do not know your internal database schema unless provided with metadata. Learn how to extract schema-only DDL without exposing user PII or sensitive payload data.
- Copilot Focus: Feeding DDL context files into Copilot Chat for precise query generation.
-
LAB 3:
- Generate a schema-only DDL export of 3 related tables from a sample database (
AdventureWorksor custom). - Save the metadata as
schema_context.sql. - Open Copilot Chat and type:
"Referencing
#file:schema_context.sql, write a high-performance query joining Orders and Customers that calculates total spend per customer in 2026."
- Generate a schema-only DDL export of 3 related tables from a sample database (
- Theory: Conceptual to logical data modeling. Moving from high-level user stories to normalized physical relational models (3NF / Star Schema).
- Copilot Focus: Generating DDL statements, primary keys, foreign keys, and constraint checks from business descriptions.
-
LAB 4:
- Feed Copilot a raw enterprise requirement: "We need a multi-tenant subscription billing system supporting tiered pricing, mid-month upgrades, and refund audits."
- Ask Copilot to produce normalized
CREATE TABLEscripts with foreign key cascades and check constraints. - Validate table relationships using an ERD tool or Azure Data Studio schema designer.
- Theory: Clustered vs. Non-clustered indexes, Heap structures, B-Trees, and Fill Factor mechanics.
- Copilot Focus: Asking Copilot to analyze table access patterns and recommend index strategy (Filtered, Included columns, Partitioning).
-
LAB 5:
- Provide a table DDL containing 15 columns to Copilot.
- Provide a workload query pattern involving range filters on
CreatedDateand equality filters onStatusID. - Ask Copilot to design the optimal Non-Clustered Index with
INCLUDEcolumns to cover the query completely.
- Theory: Test-Driven Development (TDD) in database engineering using tSQLt or isolated testing scripts.
- Copilot Focus: Generating mock data insertion scripts and validation assertions.
-
LAB 6:
- Pick a stored procedure that calculates customer discount tiers.
- Ask Copilot Chat: "Generate a test harness using isolated temporary tables to test boundary conditions (0% discount, 100% discount, negative purchase amounts) for this procedure."
- Execute the tests and confirm edge-case handling.
- Theory: Evaluating AI response accuracy, identifying hallucinations, and measuring operational time savings.
- Copilot Focus: Refining prompt engineering strategies based on Week 1 learnings.
-
LAB 7:
- Review all code generated during Days 1–6 against internal DBA security baselines.
- Create a personal "Prompt Bank" Markdown file storing the top 5 most effective prompts discovered during the week.
-
Theory: Understanding SARGability (Search Argument Able). How implicit conversions, functions on indexed columns, and wildcard
LIKEoperators trigger full table scans. - Copilot Focus: Refactoring bad T-SQL predicates into SARGable equivalents.
-
LAB 8:
- Create a table with 100,000 rows and an index on
OrderDate(datetime). - Write a non-SARGable query:
SELECT * FROM Orders WHERE YEAR(OrderDate) = 2026. - Pass the query to Copilot Chat:
"Rewrite this query to be SARGable so SQL Server can perform an Index Seek on OrderDate."
- Compare IO statistics before and after using
SET STATISTICS IO ON.
- Create a table with 100,000 rows and an index on
-
Theory: Procedural loops (Cursors,
WHILEloops) vs. Declarative Set-Based T-SQL operations. Why cursors cause high tempdb allocations and resource contention. - Copilot Focus: Converting nested cursors into Set-Based queries, CTEs, or Window functions.
-
LAB 9:
- Create a script containing a nested cursor that updates row-by-row account balances.
- Prompt Copilot: "Convert this nested cursor into a single set-based UPDATE statement using a Common Table Expression (CTE) and window functions (
SUM() OVER)." - Measure execution speed improvement on a large test dataset.
- Theory: Identifying cost bottlenecks in Graphical and XML Execution Plans (Key Lookups, Hash Matches, Sort Warnings, Missing Index Spools).
- Copilot Focus: Feeding execution plan XML fragments to Copilot for diagnostic explanation.
-
LAB 10:
- Run a complex query and export the Actual Execution Plan XML (
Ctrl + Min SSMS). - Copy the XML node containing
<Warnings>or<IndexScan>and paste it into Copilot Chat. - Prompt: "Explain why SQL Server chose a Hash Match Join over a Nested Loop Join in this plan node and how to fix it."
- Run a complex query and export the Actual Execution Plan XML (
- Theory: Locking hierarchies, lock modes (Shared, Exclusive, Update), Victim selection, and concurrency management.
- Copilot Focus: Extracting deadlock XMLs from Extended Events and parsing them with AI.
-
LAB 11:
- Simulate a deadlock using two concurrent SSMS sessions updating swapped tables.
- Query
sys.fn_xe_file_target_read_fileto retrieve thexml_deadlock_report. - Paste the XML report into Copilot with the prompt:
"Identify the victim process, winning process, locked resources, and provide the T-SQL indexing script to prevent this deadlock."
- Theory: PFS (Page Free Space) and GAM/SGAM page contention in TempDB; worktables, workfiles, and spilled sorts.
-
Copilot Focus: Diagnosing
sys.dm_os_waiting_tasksoutput for TempDB page waits (2:1:1,2:1:2). -
LAB 12:
- Generate tempdb contention using multiple concurrent temporary table creations.
- Feed raw DMV output from
sys.dm_db_task_space_usageinto Copilot. - Ask Copilot to write a diagnostic T-SQL script that isolates which session is hogging tempdb space and generates a mitigation script using memory-optimized temp tables or inline table variables.
-
Theory: Compiled plans vs. Execution plans, variable sniffing,
OPTION(RECOMPILE),OPTIMIZE FOR, and Query Store hints. -
Copilot Focus: Analyzing Query Store DMVs (
sys.query_store_runtime_stats) with AI. -
LAB 13:
- Simulate parameter sniffing on a stored procedure with skewed data distribution.
- Provide the procedure definition and query store performance divergence data to Copilot.
- Ask Copilot to compare
OPTIMIZE FOR UNKNOWNvs. local variable reassignment and provide recommendations.
-
Theory: Extracting server health metrics from
sys.dm_exec_requests,sys.dm_os_wait_stats, andsys.dm_db_index_usage_stats. - Copilot Focus: Writing complex DMV aggregate queries using natural language.
-
LAB 14:
- Ask Copilot Chat:
"Write a comprehensive DMV query that correlates top 5 signal wait types with high-CPU sessions, showing full query text, wait time in ms, and blocking session ID."
- Test and execute the generated diagnostic query against your test instance.
- Ask Copilot Chat:
- Theory: Establishing performance baselines before deploying fixes to production.
- Copilot Focus: Generating benchmark comparison logs and executive performance summaries.
-
LAB 15:
- Aggregate all performance tuning fixes implemented during Days 8–14.
- Ask Copilot to generate a Markdown report summarizing total CPU, IO, and duration reductions across all tuned queries.
-
Theory: Fragmentation thresholds (
REORGANIZEat 5–30%,REBUILD> 30%), page counts, and online vs. offline index operations. - Copilot Focus: Generating dynamic, intelligent index maintenance scripts.
-
LAB 16:
- Prompt Copilot:
"Write a dynamic T-SQL script using
sys.dm_db_index_physical_statsthat loops through all user tables, checks fragmentation, skips indexes with under 1000 pages, and executesALTER INDEX ... REBUILD WITH (ONLINE = ON)during off-peak hours." - Review the script for safe exception handling and execute in a sandbox environment.
- Prompt Copilot:
-
Theory: Modern SQL Server administration using PowerShell and the community-standard
dbatoolsmodule. - Copilot Focus: Writing modular PowerShell scripts for multi-instance management.
-
LAB 17:
- Open VS Code with PowerShell extension and GitHub Copilot enabled.
- Prompt Copilot:
"Write a PowerShell script using
dbatoolsto query a list of SQL Servers from a CMS (Central Management Server), check for databases without a full backup in the last 24 hours, and output the result to a styled HTML report." - Run the script in a test domain/environment.
- Theory: Recovery Point Objective (RPO) and Recovery Time Objective (RTO) validation across backups and HADR environments.
- Copilot Focus: Building automated test scripts to verify backup headers and restore integrity.
-
LAB 18:
- Ask Copilot to write a PowerShell script that takes the latest
.bakfile for a specified database, executes aRESTORE HEADERONLYandRESTORE VERIFYONLY, and logs the outcome to a centralized SQL audit table. - Test the script against a simulated corrupt backup file to verify error capture.
- Ask Copilot to write a PowerShell script that takes the latest
- Theory: Principle of Least Privilege (PoLP), orphan users, elevated server role auditing, and dynamic permission granting.
- Copilot Focus: Generating security audit scripts and user permission mapping.
-
LAB 19:
- Prompt Copilot: "Write a T-SQL script to audit all users with
sysadmin,db_owner, orCONTROL SERVERrights across all databases, excluding system accounts." - Ask Copilot to generate the remediation script that revokes unnecessary explicit rights and replaces them with custom database roles.
- Prompt Copilot: "Write a T-SQL script to audit all users with
- Theory: Table partitioning, sliding window scenarios, boundary switching, and staging tables.
- Copilot Focus: Scaffolding partition maintenance routines.
-
LAB 20:
- Provide Copilot with a schema for an audit log table partitioned by month.
- Prompt Copilot: "Write a T-SQL stored procedure to perform a sliding window partition switch, moving the oldest month to an archive table and merging the empty boundary point."
- Validate the partition function and scheme states before and after execution.
-
Theory: Synchronous vs. Asynchronous commit modes, log send queue, redo queue, and HADR health DMVs (
sys.dm_hadr_database_replica_states). - Copilot Focus: Writing AG health checking scripts with alerting capability.
-
LAB 21:
- Ask Copilot to write a PowerShell script that queries Availability Group metrics, calculates sync lag in seconds, and triggers an alert if log send queue size exceeds 500 MB.
- Test the script against local or simulated AG metadata.
- Theory: Job scheduling, job steps, operator notifications, and failure recovery.
-
Copilot Focus: Generating programmatic T-SQL scripts (
sp_add_job,sp_add_jobstep) to deploy automated tasks. -
LAB 22:
- Take the PowerShell/T-SQL automation scripts built in Days 16–21.
- Ask Copilot to generate a single idempotent T-SQL deployment script using
msdb.dbo.sp_add_jobthat creates the SQL Agent job, attaches steps, sets retry attempts to 3, and sends notification emails on failure.
- Theory: Moving beyond single prompts to Hierarchical and Auditable Multi-Agent Systems (HAMS). Separating code creation (Writer Agent) from safety auditing (Auditor Agent).
- Copilot Focus: Designing agent role descriptions and interaction protocols.
-
LAB 23:
- Define two persona system prompts:
- Writer Agent: Focused on generating modern T-SQL code.
- Auditor Agent: Focused strictly on security, standards compliance, and performance risks.
- Pass a legacy T-SQL procedure through the Writer Agent to modernize it.
- Pass the resulting code to the Auditor Agent and observe how it catches missing safeguards or timing issues.
- Define two persona system prompts:
-
Theory: Securing AI access to database servers. Securing service accounts using read-only metadata views (
VIEW SERVER STATE,VIEW ANY DEFINITION). - Copilot Focus: Constructing security roles that restrict AI execution rights while permitting diagnostic visibility.
-
LAB 24:
- Write a T-SQL script to create a restricted server role
[AIRecoverabilityAuditor]. - Grant explicit metadata permissions without
SELECTrights on user tables (preventing data exfiltration/PII access). - Test Copilot Chat queries running under this restricted context to verify it can read server health without viewing sensitive customer records.
- Write a T-SQL script to create a restricted server role
- Theory: Integrating static code analysis and AI validation into CI/CD deployment pipelines (GitHub Actions / Azure DevOps).
- Copilot Focus: Creating workflow scripts that analyze database pull requests.
-
LAB 25:
- Create a GitHub Action workflow file (
.github/workflows/sql_audit.yml). - Configure a step that uses an LLM/Copilot CLI action to scan any incoming
.sqlfile in a Pull Request for prohibited statements (DROP TABLE,TRUNCATE TABLE,ALTER AUTHORIZATION). - Test the workflow by submitting a PR with a forbidden keyword and verifying that the build automatically fails.
- Create a GitHub Action workflow file (
- Theory: Orchestrating large-scale schema or stored procedure migrations across multiple environments.
- Copilot Focus: Batch processing legacy T-SQL files using multi-agent scripting.
-
LAB 26:
- Store 5 legacy stored procedures in a local project folder
/legacy. - Write a Python or PowerShell automation script that iterates through the folder, sends each procedure to Copilot API / Agent pipeline, checks the output with the Auditor Agent, and saves the refactored code to
/modernized. - Inspect the modernized files and verify structural consistency.
- Store 5 legacy stored procedures in a local project folder
- Theory: Event-driven automation: using SQL Server Alerts + Extended Events + Automated Remediation Scripts to handle transient failures.
- Copilot Focus: Generating self-healing remediation routines for common alerts (e.g., Error 1105 - Filegroup full).
-
LAB 27:
- Create a scenario where a database data file reaches capacity in a test environment.
- Use Copilot to write an automated PowerShell response script attached to a SQL Alert that checks available disk space, expands the file by a controlled increment, and alerts the team on Slack/Teams.
- Theory: Database FinOps: Right-sizing Azure SQL Databases / Managed Instances / AWS RDS instances based on DTU/vCore utilization patterns.
- Copilot Focus: Analyzing metric logs to identify over-provisioned database instances.
-
LAB 28:
- Feed 30 days of CPU, Memory, and IO utilization logs (CSV format) into Copilot.
- Ask Copilot to identify instances where peak utilization never exceeded 20% and calculate the estimated monthly cost savings of scaling down by one tier.
- Generate the automated
ALTER DATABASEsizing scripts.
- Theory: Systematically prioritizing and clearing chronic technical debt using AI-assisted analysis.
- Copilot Focus: Processing backlog tickets in bulk (Deadlocks, Missing Indexes, Slow SSRS Reports).
-
LAB 29:
- Gather 3 real or simulated backlog tickets from your queue (e.g., 1 slow report procedure, 1 deadlock XML, 1 missing index request).
- Apply the full AI Orchestrator workflow: Context Injection -> Writer Agent -> Auditor Agent -> Human Review.
- Track time elapsed per ticket and record performance/cost improvements.
- Theory: Demonstrating complete transformation from Query Operator to AI Data Architect.
- Copilot Focus: Orchestrating an end-to-end multi-agent deployment with zero manual code typing.
-
LAB 30:
- The Challenge: Receive a complex business requirement requiring 3 new tables, 2 stored procedures, 1 PowerShell health check script, and a GitHub CI/CD validation pipeline.
- The Execution: Use Copilot and Agent architectures exclusively to design, scaffold, audit, and generate the solution.
- Human Role: Act strictly as the Data Architect—defining parameters, reviewing AI Chain of Thought logs, testing in sandbox, and issuing final deployment approval.
- Outcome: Complete an entire system deployment in under 2 hours with zero manual syntax errors and 100% compliance with security guardrails.
When publishing each article in this series, follow this 6-part editorial structure to maximize reader engagement and trust:
- The Hook (The 2 AM Incident): Begin with a relatable operational scenario (e.g., a Sev-1 outage, a failed audit, or a blocked deployment).
- Prerequisites Matrix: List required software versions (e.g., SSMS 22 / Azure Data Studio (latest), Azure Data Studio, GitHub Copilot Business License, AdventureWorks2025 (or a restored sandbox copy)).
- The "Old Way" vs. "The Copilot Way": Contrast traditional manual execution times with AI-augmented workflows.
- Step-by-Step Lab Execution: Provide full prompts, expected AI outputs, and code blocks.
- The "Gotchas" & Safety Edge Cases: Detail where AI models fail (e.g., suggesting excessive index included columns or incorrect isolation levels). This builds credibility with senior engineering teams.
- Actionable Takeaway & Practical Assignment: End with a specific task readers can execute on their own test servers immediately.
Before executing any AI-generated T-SQL or PowerShell script in enterprise production environments, run through this mandatory safety checklist:
- Data Safety Audit: Has the code been verified to ensure no unhedged
DELETE,TRUNCATE, orDROPcommands exist? - Explicit Transaction Bounds: Are DML operations wrapped in explicit
BEGIN TRANSACTION,COMMIT TRANSACTION, andROLLBACK TRANSACTIONblocks with activeTRY...CATCHlogic? - SARGability Verification: Are all
WHEREandJOINpredicates free of scalar functions or implicit conversions on indexed columns? - Locking & Escalation Control: Do mass data updates process in controlled batches (
TOP (N)) to prevent table-level lock escalation (Xlocks)? - Maintenance Window Alignment: Are index rebuilds or heavy DDL alterations restricted to scheduled maintenance windows?
- Least-Privilege Context: Is the script executing under a restricted service account lacking unnecessary
sysadminelevation? - Chain of Thought Review: Has the DBA validated all hints (
RECOMPILE,FORCESCAN,MAXDOP) recommended by the AI model?
Transitioning from a traditional SQL Server DBA to an AI-Augmented Data Architect is not about working more hours—it is about elevating your role from a manual operator to an AI orchestrator. By mastering prompt engineering, metadata context injection, and multi-agent governance, you build a resilient, future-proof career at the top of the IT enterprise landscape.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA with expertise in Microsoft AI integrations, GitHub Copilot, and modern database tooling. Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Intermediate-to-Advanced SQL Server knowledge, basic familiarity with VS Code or Azure Data Studio Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Equip DBAs with the foundational knowledge and practical setup required to securely integrate GitHub Copilot and LLM capabilities into their daily administrative and development workflows.
By the end of this module, you will be able to:
- Articulate how Large Language Models (LLMs) interact with database IDEs through GitHub Copilot and Copilot Chat.
- Configure a secure, enterprise-ready AI workbench in SSMS 22 / Azure Data Studio (latest) or VS Code.
- Implement telemetry guardrails (
.copilotignore) to protect sensitive connection strings and credentials—critical for GDPR (EU) and SOC2/HIPAA/SOX (US) compliance. - Leverage inline completions and workspace context variables (
#file,@workspace) to generate contextually accurate T-SQL. - Validate your setup by generating a production-grade T-SQL query using only a natural language comment prompt.
Before beginning this lab, ensure you have the following:
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| GitHub Account | A GitHub account with an active Copilot subscription (Individual, Business, or Enterprise) |
| SQL Server Instance | Access to a SQL Server instance (2016+) for validation. A local Developer Edition or an Azure SQL Database is sufficient. |
| Network | Outbound HTTPS access to api.github.com and copilot-proxy.githubusercontent.com (confirm with your IT/Security team if behind a corporate proxy) |
| OS | Windows 10/11, macOS 12+, or Ubuntu 20.04+ |
🇪🇺 European Compliance Note (GDPR): If your organization operates under GDPR, confirm with your Data Protection Officer (DPO) that GitHub Copilot's data handling policies align with your internal data governance framework. GitHub Copilot for Business and Enterprise tiers offer enhanced data retention controls where code snippets are not retained or used for model training.
🇺🇸 US Compliance Note (SOC2/HIPAA/SOX): For organizations under SOC2, HIPAA, or SOX, GitHub Copilot Enterprise provides IP indemnification, audit logs, and strict privacy controls. Ensure your procurement team has selected the appropriate tier.
As experienced DBAs, you are accustomed to deterministic systems: you write a query, the optimizer produces a plan, and the engine executes it. AI-assisted development introduces a probabilistic layer on top of this deterministic foundation.
Here is how the components interact:
┌─────────────────────────────────────────────────────┐
│ YOUR IDE (ADS / VS Code) │
│ │
│ ┌──────────────┐ ┌───────────────────────────┐ │
│ │ .sql Buffer │───▶│ Copilot Extension │ │
│ │ (Your Code) │ │ (Context Collector) │ │
│ └──────────────┘ └──────────┬────────────────┘ │
│ │ │
│ ┌──────────────┐ ┌─────────▼────────────────┐ │
│ │ Open Files │───▶│ Context Window Builder │ │
│ │ #file refs │ │ (Tokenizes & Ranks) │ │
│ └──────────────┘ └──────────┬────────────────┘ │
└─────────────────────────────────┼───────────────────┘
│ HTTPS (TLS 1.2+)
▼
┌─────────────────────────────┐
│ GitHub Copilot Backend │
│ (LLM Inference Engine) │
│ │
│ • Prompt Construction │
│ • Model Inference │
│ • Response Filtering │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Inline Suggestion or │
│ Chat Response in IDE │
└─────────────────────────────┘
Key Insight: The Copilot extension does not send your entire codebase to the cloud. It constructs a contextual prompt from your current file, adjacent open files, and workspace context, then sends only that curated window to the LLM backend for inference.
This is where many DBAs get tripped up. An LLM does not "read" your code the way you do. It processes tokens—chunks of text that may be a word, a partial word, or a symbol.
| Concept | What It Means for You |
|---|---|
| Token | Roughly ¾ of an English word (approx. 4 characters). SELECT * FROM dbo.Orders is approximately 7 tokens. |
| Context Window | The maximum number of tokens the model can process in a single request (input + output). For GPT-4o, this is 128K tokens. For Copilot's inline model, the effective window is typically 2K–8K tokens of surrounding code. |
| Prompt Construction | Copilot prioritizes: (1) your current cursor position, (2) code above the cursor, (3) code below the cursor, (4) content from #file references, (5) other open tabs. |
Why This Matters for DBAs: If you paste a massive DDL script with thousands of tables into a single file and ask Copilot to refactor it, the model will rapidly consume token limits and lose context of the earlier definitions. The professional approach is to chunk your work and feed Copilot modular, specific context.
| Feature | GitHub Copilot (Inline) | Copilot Chat | Copilot in SSMS |
|---|---|---|---|
| Trigger | Automatic as you type | Manual (Ctrl+I or Chat panel) |
Manual (SSMS sidebar) |
| Context Window | ~2K–8K tokens | Up to 128K tokens | Varies by version |
| Best For | Rapidly writing boilerplate JOIN clauses or TRY...CATCH blocks |
Explaining undocumented legacy procedures, Q&A | T-SQL generation within the classic SSMS workflow |
| IDE | VS Code, Azure Data Studio | VS Code, Azure Data Studio | SQL Server Management Studio 20+ |
Professional Recommendation: For this training series, we will use Azure Data Studio as our primary IDE. DBAs are increasingly transitioning to ADS/VS Code for AI-assisted script authoring while retaining SSMS for legacy administrative dialogues.
Inline completions are Copilot's "ghost text" suggestions that predict your next lines of code based on immediate surrounding context.
-- Write a query to find all databases with auto-shrink enabled
-- Copilot generates:
SELECT name, is_auto_shrink_on
FROM sys.databases
WHERE is_auto_shrink_on = 1;Accepting suggestions:
-
Tab→ Accept the full suggestion -
Ctrl+Right Arrow→ Accept word-by-word -
Esc→ Dismiss
Context variables allow you to explicitly direct Copilot's attention, shifting it from a "smart autocomplete" to a context-aware assistant.
| Variable | Syntax | Use Case for DBAs |
|---|---|---|
#file |
#file:filename.sql |
Explicitly points Copilot to a specific file. "Write a query to insert data into #file:Customers.sql" ensures the AI knows exact column names. |
@workspace |
@workspace |
Commands Copilot to index and search all open files. "@workspace How is the User table referenced across all scripts?" |
#selection |
Highlight code, then ask | Analyze only the highlighted block. "Explain why this query is non-SARGable." |
This file tells Copilot which files and directories to exclude from AI telemetry. Think of it as the .gitignore for AI. DBAs frequently handle scripts containing sensitive connection strings, legacy passwords, or proprietary schema configurations. We must exclude these from ever traversing the network.
| Item | Detail |
|---|---|
| Goal | Install GitHub Copilot, implement security guardrails via .copilotignore, and validate inline T-SQL generation. |
| Time | 90 minutes |
| Deliverable | A working AI-augmented IDE that safely generates T-SQL from natural language prompts. |
- Download and install Azure Data Studio.
- Navigate to the Extensions panel (
Ctrl+Shift+X). - Search for and install both GitHub Copilot and GitHub Copilot Chat.
- Authenticate by clicking the sign-in prompt in the bottom right corner to authorize your GitHub account.
- In Azure Data Studio, click "New Connection".
- Enter your connection details (
localhostor server name). - Click Connect and verify the server appears in the Connections panel.
This is your security perimeter. Create this file at the root of your workspace folder to ensure sensitive configuration files and connection strings with explicit passwords are excluded.
- Go to File → Open Folder and select your
SQL-DBA-Workspacedirectory. - Create a new file named
.copilotignore. - Paste the following exact content (which includes critical legacy script exclusions):
# ============================================
# .copilotignore – AI Telemetry Exclusion File
# Purpose: Prevent sensitive DBA configuration
# files from being included in Copilot context
# ============================================
# Connection configuration files (may contain credentials)
*.json
!package.json
*connection*.config
# Environment files with secrets
.env
.env.*
*.env
# Legacy scripts with hardcoded credentials
/legacy_migrations/
*pwd*.sql
*password*.sql
# PowerShell credential files
*.xml
*.cred
*.pfx
*.p12
# Redgate / SQL Compare / SQL Prompt config
*.rgsettings
*.sqlprompt
# SSMS connection export files
*.ssms
*.regsrvr
# Any file explicitly marked as sensitive
**/sensitive/
**/credentials/
**/secrets/
# Backup and log files (may contain data samples)
*.bak
*.trn
*.log
*.csv
*.xlsx
# Git internals
.git/
- Save the file. GitHub Copilot will immediately cease providing completions or reading context from these matched files.
- Open Settings (
Ctrl+,). - Search for
copilotand ensureGitHub Copilot: Enableis checked. - Verify
Editor: Inline Suggest: Enabledis set totrue. - Ensure
sqlis listed underGitHub Copilot: Enable for Languages.
- Create a new SQL file in Azure Data Studio and set the language mode to SQL.
- Ensure you are connected to your instance.
- Type the following prompt comment exactly as written, press
Enter, and wait 1-2 seconds:
-- Write a T-SQL query to list top 10 databases by data file size on disk-
Observe: Copilot should generate ghost text suggesting a query utilizing
sys.master_files. -
Press
Tabto accept the suggestion. Check the code for accuracy (e.g., ensuring it filters bytype = 0ortype_desc = 'ROWS'to exclude log files). -
Execute the query (
F5) to validate results. -
Iterate: Type another comment below:
-- Now modify this to show total size per database (data + log), grouped and ordered by total size descending- Accept and execute the refined query.
- Open the Copilot Chat panel (
Ctrl+Alt+I). - Test the
@workspacecontext:@workspace I am a SQL Server DBA. Create a folder structure recommendation for organizing my DBA scripts by category (Performance, Security, Maintenance). - Test
#filecontext. Save your query from Step 5 asTopDatabasesBySize.sql. In Chat, type:#file:TopDatabasesBySize.sql Review this query for performance best practices. Are there any improvements for large-scale environments with 500+ databases?
| Issue | Cause | Resolution |
|---|---|---|
Copilot shows no suggestions in .sql files |
Language mode not set to SQL | Click the language indicator in the bottom status bar and select SQL |
| "GitHub Copilot could not connect" | Corporate proxy blocking outbound HTTPS | Work with IT to whitelist api.github.com and *.githubusercontent.com. |
| Suggestions are generic, not schema-aware | No context provided | Use #file and @workspace to provide schema context. |
| Copilot suggests deprecated syntax | LLM trained on older patterns | Add a comment at the top: -- Target: SQL Server 2025 (Compatibility Level 170). Use modern data types only.
|
.copilotignore not being respected |
File in wrong location/syntax error | Ensure it is at the workspace root and formatting matches standard .gitignore rules. |
- Azure Data Studio (or VS Code) installed with GitHub Copilot/Chat extensions
- Successfully authenticated to GitHub
- Connected to a SQL Server instance from the IDE
- Created and populated
.copilotignorewith security exclusions (including legacy credential patterns) - Verified that sensitive files are excluded from Copilot context
- Configured Copilot settings to enable inline suggestions for SQL
- Successfully generated a T-SQL query from a natural language comment using inline completion
- Executed and validated the AI-generated query against a live instance
- Used
@workspaceand#filecontext variables in Copilot Chat - Reviewed and understood token limits, context windows, and compliance boundaries (GDPR/HIPAA/SOX)
In Day 2: The Query Whisperer – Real-Time Execution Plan Analysis & Tuning, you will:
- Capture a live execution plan XML from a deliberately slow query
- Feed it to Copilot Chat for instant bottleneck identification
- Generate optimized T-SQL rewrites and
CREATE INDEXstatements - Compare before/after logical reads to quantify the AI's impact
Preparation for Day 2: Ensure you have the AdventureWorks sample database installed on your test instance.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA with expertise in Microsoft AI integrations, GitHub Copilot, and modern database tooling. Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Day 1 (Setting Up the AI Workbench), strong T-SQL foundation. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transition from using AI as a basic code completion tool to an enterprise-aware development partner. You will learn to build custom guardrails that force Large Language Models (LLMs) to strictly adhere to corporate database standards and architectural guidelines.
By the end of this module, you will be able to:
- Articulate the risks of "unguided" AI generation in enterprise database environments.
- Design and structure an effective "System Prompt" file for database development.
- Enforce strict T-SQL coding standards (e.g., schema prefixes, specific casing, mandatory settings like
NOCOUNT ON) using Copilot Chat context. - Utilize a central ruleset file (
DBA_Rules.md) to guide complex, multi-table schema generation. - Identify and correct AI hallucinations where the model attempts to deviate from established enterprise rules.
By default, Large Language Models are trained on a vast corpus of public repositories, forums, and tutorials. Because the quality and style of public SQL code vary wildly, an unguided LLM defaults to the "average" style.
If you ask Copilot to "create a customer table," it might generate:
- Primary keys named
idinstead ofCustomerId - Tables missing schema prefixes (creating them in the default user schema instead of
dbo.) - Undesirable data types (e.g.,
VARCHARinstead ofNVARCHAR, orDATETIMEinstead ofDATETIME2) - No standardized error handling or performance SET options (
SET NOCOUNT ON).
In an enterprise environment, this generic code introduces technical debt, violates CI/CD linting rules, and creates deployment bottlenecks.
System Prompting is the act of pre-conditioning the AI with a strict set of rules, personas, and constraints before issuing your actual request.
Instead of typing: "Create a script for processing orders."
You use System Prompting: "You are an Enterprise SQL Server 2025 DBA. Adhere strictly to the guidelines in #file:DBA_Rules.md. Now, create a script for processing orders."
A good AI rule must be explicit and deterministic. AI struggles with vague adjectives like "make it secure" or "write clean code."
Bad Rule: "Use good naming conventions." Good Rule: "All column names must use camelCase. Primary keys must be named {TableName}Id."
While Copilot Chat (in VS Code / Azure Data Studio) allows you to set custom instructions in the global settings, DBAs often work across multiple client environments or projects, each with different standards.
The most scalable method is to keep a DBA_Rules.md (or .github/copilot-instructions.md) file directly in the workspace repository.
When you engage with Copilot Chat to build new objects, you must explicitly bind the rules file to the conversation context.
-
The Context Anchor: Use
#file:DBA_Rules.mdat the very beginning of your prompt. - The Directive: Use strong imperative verbs ("Enforce", "Strictly follow", "Do not deviate").
- The Task: Define what you actually want built.
Occasionally, the LLM will "forget" a rule, especially if the conversation context gets too long. If the AI generates an implicit JOIN when you requested explicit JOINs, do not rewrite the code manually. Instead, correct the AI:
"You violated rule #3 in #file:DBA_Rules.md. Rewrite using explicit INNER JOIN syntax."
This reinforces the model's attention on the rules document.
| Item | Detail |
|---|---|
| Goal | Create a reusable enterprise rules template and force the AI to generate a complex, compliant order-processing schema. |
| Time | 90 minutes |
| Deliverable | A DBA_Rules.md file and a perfectly formatted, multi-table T-SQL schema script. |
- Open your
SQL-DBA-Workspacein Azure Data Studio (or VS Code). - At the root of the workspace, create a new file named
DBA_Rules.md. - Paste the following enterprise standards into the file and save it:
# Enterprise SQL Server Coding Standards
You are a Senior SQL Server Database Administrator. Whenever you generate or refactor T-SQL code, you MUST strictly adhere to the following rules:
## 1. Schema & Object Naming
- ALWAYS include explicit schema prefixes (e.g., `dbo.TableName`, `sales.OrderHeader`). Never assume the default schema.
- Table names must be PascalCase and singular (e.g., `dbo.Customer`, not `dbo.customers`).
- Column names must strictly use camelCase (e.g., `firstName`, `orderDate`).
## 2. Syntax & Structure
- ALWAYS use explicit `JOIN` syntax (`INNER JOIN`, `LEFT OUTER JOIN`). Never use comma-separated tables in the `FROM` clause.
- Keywords (SELECT, FROM, WHERE, JOIN) must be UPPERCASE.
- Every script must begin with:
`SET ANSI_NULLS ON;`
`SET QUOTED_IDENTIFIER ON;`
- Every Stored Procedure must include `SET NOCOUNT ON;` immediately after the `BEGIN` statement.
## 3. Data Types & Constraints
- Use modern data types: Prefer `DATETIME2` over `DATETIME`. Prefer `VARCHAR/NVARCHAR` over `CHAR/NCHAR` (unless the length is truly fixed).
- Every table MUST have a Primary Key constraint.
- Primary Key columns must be named identically to the Table Name, appended with 'Id' in PascalCase (e.g., Table `dbo.Order`, PK Column `OrderId`).
## 4. Error Handling
- Use structured `BEGIN TRY...END TRY / BEGIN CATCH...END CATCH` blocks for all DML operations.First, let's see what happens without our guardrails.
- Open Copilot Chat.
- Type the following generic prompt:
Create a SQL script for an order processing engine. I need tables for Customers, Orders, and Order Items. -
Observe the output: You will likely see plural table names (
Customers), missing schemas, basicDATETIMEtypes, oridused as a primary key. Do not save this code.
Now, we force Copilot to respect our engineering standards.
- Create a new empty file named
Create_OrderEngine.sql. - Open Copilot Chat.
- Type the following prompt, ensuring you use the
#filevariable to reference your rules:
Please read the guidelines in #file:DBA_Rules.md.
Acting as a Senior DBA and strictly adhering to those rules, generate a comprehensive multi-table schema for an order-processing engine.
Include the following entities:
1. Customer
2. Order
3. OrderLineItem
Ensure all foreign key relationships are properly established. Output only the T-SQL script.
-
Analyze the Response:
- Did it use
dbo.Customer? - Are the columns in camelCase (e.g.,
orderDate,customerEmail)? - Are the Primary Keys named correctly (e.g.,
CustomerId,OrderId)? - Did it include the
SEToptions at the top?
- Did it use
-
Click the "Insert at Cursor" button in the chat panel to place the generated code into
Create_OrderEngine.sql.
Let's test the AI's ability to maintain context and apply rules to modifications.
-
In the same Copilot Chat thread, type:
Write a stored procedure to insert a new Order and its associated OrderLineItems. Pass the items in as a JSON string. Make sure to follow the error handling and syntax rules in #file:DBA_Rules.md. -
Verify that the generated Stored Procedure:
- Has
SET NOCOUNT ON;afterBEGIN. - Utilizes a
TRY...CATCHblock. - Has upper-cased keywords.
- Has
-
If the AI missed a rule (for instance, it forgot
SET NOCOUNT ON), challenge it:You missed rule #2 from the rules file regarding stored procedures. Please correct it.
| Issue | Cause | Resolution |
|---|---|---|
| Copilot ignores the rules entirely | Context wasn't attached | Ensure you explicitly typed #file:DBA_Rules.md in the chat window and clicked the file when the dropdown appeared. |
| Copilot struggles with casing rules | Conflicting instructions | Ensure your rules don't contradict each other (e.g., asking for PascalCase tables but camelCase columns can occasionally confuse older models). Use explicit examples in your rules file as we did in Lab 2. |
| The rules apply to Chat but not Inline Suggestions | Inline scope limitations | Inline completions (ghost text) have a smaller context window. While they look at open tabs, strict adherence to a 2-page rule document is best handled via Copilot Chat. |
- Created the
DBA_Rules.mdfile in the workspace root. - Defined explicit rules for schema prefixes, naming conventions, and data types.
- Executed an unguided prompt to understand default AI behavior.
- Executed a guided prompt using
#file:DBA_Rules.md. - Validated that the resulting T-SQL strictly matched the requested camelCase, PascalCase, and schema requirements.
- Successfully instructed Copilot to generate a stored procedure incorporating the error-handling guardrails.
In Day 3: The Query Whisperer – Real-Time Execution Plan Analysis & Tuning, we will shift from code generation to performance optimization. You will learn how to:
- Capture a live execution plan XML from a deliberately slow query.
- Feed the XML to Copilot Chat for instant bottleneck identification (Key Lookups, Spools, Missing Indexes).
- Use AI to safely refactor legacy queries to eliminate non-SARGable predicates.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA with expertise in Microsoft AI integrations, GitHub Copilot, and modern database tooling. Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Day 1 and Day 2, strong T-SQL foundation, familiarity with schema generation. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Master the technique of Retrieval-Augmented Generation (RAG) in a database context. You will learn how to securely inject your proprietary database schema into the LLM's context window without exposing sensitive Personally Identifiable Information (PII) or protected corporate data.
By the end of this module, you will be able to:
- Understand why LLMs fail at proprietary query generation without explicit schema metadata.
- Differentiate between safe schema metadata (DDL) and unsafe payload data (DML/PII).
- Generate and sanitize schema-only definitions for AI context injection.
- Utilize context files (
schema_context.sql) to dramatically improve the accuracy and performance of AI-generated queries. - Leverage Copilot Chat to write complex aggregations against your specific business architecture.
Large Language Models are pre-trained on vast amounts of data, meaning they know how to write T-SQL perfectly. However, they are completely blind to your specific database. They do not know if your customer identifier is named CustID, CustomerID, or customer_guid.
If you ask an AI to "write a query to find our best customers," it will hallucinate column names and table structures, resulting in code that fails to execute.
Retrieval-Augmented Generation (RAG) is an AI framework where we retrieve relevant, factual information (in our case, the database schema) and provide it to the LLM alongside our prompt.
Instead of expecting the AI to guess the schema, we inject the DDL (Data Definition Language) as context.
When practicing RAG, security is the absolute highest priority.
-
Safe for AI (Metadata): Table definitions (
CREATE TABLE), column names, data types, primary/foreign keys, and indexes. -
UNSAFE for AI (Payload): Real customer names, SSNs, financial records, email addresses, or actual row data (
INSERT INTO... VALUES...).
Golden Rule: We only ever feed schema definitions (DDL) to the AI, never the actual data. This ensures compliance with GDPR (Europe) and SOC2/HIPAA (US).
To perform context injection efficiently, we must consider the AI's token limit (its context window).
Generating a schema script for an entire ERP database with 5,000 tables will overwhelm the token limit. Instead, DBAs must practice Micro-RAG: extracting only the DDL for the tables relevant to the immediate task. Furthermore, stripping out unnecessary noise (like extended properties or explicit permissions) saves tokens and focuses the AI's attention on relationships and data types.
We use the #file variable in Copilot Chat to inject our prepared schema.
-
The Setup: Save the extracted DDL into a file named
schema_context.sql. - The Injection: Ask Copilot Chat to reference that file when generating your query. Because the LLM can now "see" the exact table structures, keys, and relationships, it will generate a query that executes flawlessly on the first try.
| Item | Detail |
|---|---|
| Goal | Extract schema definitions for related tables, sanitize the output, and use it as injected context to generate a highly accurate, complex T-SQL query. |
| Time | 90 minutes |
| Deliverable | A reusable schema_context.sql file and an AI-generated, schema-accurate analytical query. |
You can use the AdventureWorks sample database or a test database of your choosing.
- Open Azure Data Studio or SSMS.
- Locate three related tables representing a standard sales flow (e.g.,
Sales.Customer,Sales.SalesOrderHeader, andSales.SalesOrderDetailin AdventureWorks). - Script out these tables as
CREATE TOstatements.- In SSMS: Right-click database -> Tasks -> Generate Scripts -> Select specific database objects -> Ensure "Types of data to script" is set to "Schema only".
- Ensure the script includes Primary Keys and Foreign Keys, as this helps the AI understand how to
JOINthem.
- In your
SQL-DBA-Workspacein Azure Data Studio/VS Code, create a new file namedschema_context.sql. - Paste the generated
CREATE TABLEscripts into this file. -
Optimize for Tokens: Manually delete (or use Find/Replace) any unnecessary bloat to save tokens. Remove
EXEC sys.sp_addextendedpropertystatements, storage alignments (ON [PRIMARY]), and identity seed details if they aren't relevant to writing a query. - Save the file. Your file should cleanly show the table structures, columns, types, and constraints.
Now we will ask the AI to perform a complex aggregation, forcing it to use our exact schema.
- Create a new, blank file named
CustomerSpendAnalysis.sql. - Open Copilot Chat.
- Type the following prompt exactly, ensuring you use the
#filetag to attach the context:
Referencing #file:schema_context.sql, write a high-performance query joining the Orders and Customers tables (use the exact table names from the schema).
Calculate the total spend per customer for the year 2026.
Include the customer's ID, Name, and format the total spend to two decimal places. Order the results by the highest spend first.
- Review the generated code in the chat window.
- Ask yourself:
- Did the AI use the exact schema and table names from your
schema_context.sqlfile? - Did it correctly infer the
JOINpredicates based on the Foreign Keys in your DDL? - Did it successfully apply the
WHEREclause for the year 2026?
- Did the AI use the exact schema and table names from your
- Click "Insert at Cursor" to place the code into
CustomerSpendAnalysis.sql. - Run the query against your database to verify execution.
| Issue | Cause | Resolution |
|---|---|---|
| Copilot hallucinated a column name | Ignored context or ambiguous prompt | Ensure #file:schema_context.sql was properly linked in the prompt. Make sure the requested columns (e.g., "Customer Name") actually exist in the provided DDL (e.g., FirstName, LastName). |
| Copilot Chat says "File too large" | Token limit exceeded | You exported too many tables or too much noise (extended properties). Trim the DDL to only the 3-5 tables strictly necessary for the query. |
| Accidental Data Leakage | Exported DML instead of DDL | ALWAYS verify your script only contains CREATE TABLE statements. Never include INSERT statements in your context file. |
- Successfully extracted schema-only (DDL) scripts for 3 related tables.
- Cleansed the DDL of unnecessary metadata to optimize token usage.
- Saved the clean DDL as
schema_context.sqlin the workspace. - Successfully prompted Copilot Chat using
#file:schema_context.sql. - Validated that the AI utilized the exact table and column names from the injected context.
- Understood the critical security distinction between sharing schema (safe) and sharing data (unsafe).
In Day 4: The Query Whisperer – Real-Time Execution Plan Analysis & Tuning, we will shift from writing code to optimizing it. You will learn how to:
- Capture a live execution plan XML from a deliberately slow, AI-generated query.
- Feed the XML to Copilot Chat for instant bottleneck identification (Key Lookups, Spools, Missing Indexes).
- Use AI to safely refactor legacy queries to eliminate non-SARGable predicates.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-3, strong grasp of 3NF, basic ERD reading skills.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Empower database architects to rapidly translate ambiguous business requirements into robust, normalized, and enterprise-compliant physical data models using AI, without sacrificing relational integrity or performance.
By the end of this module, you will be able to:
- Articulate the difference between how an LLM interprets flat conceptual requirements versus strict 3NF relational modeling.
- Construct precise, context-rich Copilot prompts that transform agile user stories into deployable physical schemas.
- Enforce enterprise constraints (foreign key cascades, check constraints, default values) consistently during AI-assisted DDL generation.
- Diagnose AI-generated schema hallucinations, specifically identifying missing non-clustered indexes on foreign keys and suboptimal data type selections.
- Validate AI-generated table relationships by reverse-engineering the DDL into an Entity-Relationship Diagram (ERD).
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2019+ or Azure SQL Database (needed for temporal table features) |
| Network | Outbound HTTPS to api.github.com (Standard Copilot endpoints) |
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): When feeding business requirements into Copilot, ensure you are not passing real customer data, actual proprietary pricing tiers, or un-anonymized user stories. While Copilot Enterprise does not train on your prompts, feeding raw PII into a prompt still violates data processor boundaries. Use synthetic requirement placeholders.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Financial billing schemas (like the one we are building today) fall strictly under SOX compliance. Ensure that AI-generated audit tables track
ModifiedByandModifiedDateaccurately to satisfy segregation of duties and audit logging requirements.
Welcome back, everyone. Take your seats. Today, we are tackling the most notoriously difficult translation job in IT: turning what the product managers say into what the database engine actually does.
Historically, this meant weeks of whiteboard sessions, arguing over composite keys, and slowly typing out CREATE TABLE scripts. Today, we are going to use AI to condense that cycle into minutes. But there is a catch.
Large Language Models (LLMs) are text predictors, not relational algebra engines. If you give an LLM a vague business requirement, its default behavior is to build a massive, flat spreadsheet. It will eagerly generate a single table with 45 columns because it fundamentally wants to group semantically related words together. Our job as DBAs is to force the LLM to think in Third Normal Form (3NF) or Star Schemas.
Here is how our workflow changes today:
┌─────────────────────────────────────────────────────────────┐
│ YOUR IDE (ADS / VS Code) │
│ │
│ ┌──────────────────┐ ┌───────────────────────────────┐ │
│ │ User Story / PRD │───▶│ System Rules (#file) │ │
│ │ (The "What") │ │ (The "How" - 3NF, Datatypes) │ │
│ └──────────────────┘ └──────────────┬────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────▼────────────────┐ │
│ │ Copilot Chat Context Window │ │
│ │ "Generate DDL enforcing 3NF, explicit schemas..." │ │
│ └──────────────────────────────────────┬────────────────┘ │
└─────────────────────────────────────────┼───────────────────┘
│ HTTPS
▼
┌─────────────────────────────┐
│ GitHub Copilot Backend │
│ (LLM Inference Engine) │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Raw T-SQL DDL Scripts │
│ (Tables, FKs, Constraints)│
└─────────────────────────────┘
When you execute a stored procedure, you get a deterministic result. When you ask Copilot to generate a schema, you get a probabilistic one. If I ask Copilot for a "Customer table" today, it might use INT for the primary key. Tomorrow, it might use UNIQUEIDENTIFIER.
To control this, we must manage the context window. If your Agile requirements document is 15 pages long, the LLM will hit token truncation and forget the constraints you specified on page 1. You must chunk your data modeling.
Field Note: Last year, I watched a junior developer use an LLM to design an inventory system. He blindly executed the generated DDL. The AI had decided to store the entire hierarchical product catalog as a massive
NVARCHAR(MAX)JSON string in a single column because the prompt said "products have variable attributes." It was a query performance bloodbath. We spent three days shredding that JSON back into a proper relational model. Never let the AI dictate your normalization strategy.
Today, we rely heavily on Copilot Chat, rather than inline completions. Generating an entire relational model requires the broader context window that Chat provides.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| System Rules Reference | #file:DBA_Rules.md |
Forcing Copilot to apply your corporate standards (e.g., Always use dbo., No cascading deletes, Use DATETIME2). |
| Iterative Prompting | "Now normalize this into 3NF" |
Correcting the AI when it generates a flat, denormalized table structure from a user story. |
| Constraint Generation | "Add CHECK constraints for..." |
Generating the tedious syntax for data integrity limits without looking up Books Online. |
Set up your workspace exactly like this before we start the lab. Notice how we separate the requirements from the output.
Billing-Project-Workspace/
├── .copilotignore <-- Telemetry block
├── Guidelines/
│ └── DBA_Rules.md <-- Corporate schema standards (From Day 2)
├── Requirements/
│ └── Billing_Epic_1.md <-- The raw business text
└── DDL/
└── 01_Billing_Schema_v1.sql <-- Where we will save AI output
Alright, let's get our hands dirty. The business just dropped a massive requirement on our desks for a new SaaS platform.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Translate a raw business requirement into a deployable, normalized T-SQL relational model. |
| Target Instance | Local Developer Edition or Azure SQL (tempdb or new sandbox DB) |
| Duration | 90 Minutes |
| Deliverables | Multi-table DDL script with FKs, default constraints, and check constraints. |
In your IDE, create a file called Billing_Epic.md and paste this exact text into it. This is what you got from the Product Manager:
"We need a multi-tenant subscription billing system supporting tiered pricing. A Tenant can have many Users, but only one Billing Profile. Subscriptions can be 'Basic', 'Pro', or 'Enterprise'. We need to track mid-month upgrades (proration), so we must know exactly when a subscription status changed. Finally, finance requires strict refund audits—every refund must be linked to an original invoice and include a reason code."
Open Copilot Chat (Ctrl+Alt+I / Cmd+Alt+I). We are going to feed it the requirement, but apply our DBA guardrails. Type this exactly:
"Act as an enterprise SQL Server Database Architect. Read #file:Billing_Epic.md. Generate the T-SQL DDL to create a fully normalized 3NF relational database schema for this requirement. Ensure all tables are in the
dboschema. UseINT IDENTITY(1,1)for surrogate primary keys. Output ONLY the SQL code."
Look at the output. You likely have tables for Tenant, User, BillingProfile, Subscription, Invoice, and Refund.
🔍 Pause & Inspect Checkpoint:
- Did the AI create a status history table for the "mid-month upgrades" requirement, or did it just put a
LastModifiedDateon the Subscription table? (If the latter, it failed the audit requirement).- Look at the Foreign Keys. Did it add
ON DELETE CASCADE? In a billing system, cascading deletes are illegal—we never delete invoices if a tenant leaves.- Raise your hand if your output has cascading deletes. We need to fix that.
In the same Copilot Chat thread, issue this correction:
"Good, but make the following enterprise adjustments: 1) Remove ALL cascading deletes. 2) Add a
SubscriptionHistorytable to satisfy the audit requirement for mid-month upgrades. 3) Add a CHECK constraint on theRefundtable ensuring the refund amount is greater than 0. 4) Generate non-clustered indexes for ALL foreign key columns."
Copy the final, refined T-SQL code. Create a new database named BillingSandbox, open a query window connected to it, and paste your code.
Before you hit execute... pause for 5 seconds. Read the script top to bottom. Does it look like code you would approve in a PR? If yes, hit F5.
⚡ Lab Micro-Challenge: For the faster folks in the room: Financial audits are strict. Ask Copilot to alter the generated
InvoiceandRefundtables to use SQL Server System-Versioned Temporal Tables. See how it handles adding theSysStartTimeandSysEndTimecolumns automatically.
Here is the reality of AI-generated schemas. They look beautiful at first glance, but they hide operational landmines.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Missing FK Indexes | LLMs generate logical relationships (the FK constraint) but often forget physical performance optimization (the index). | Explicitly prompt: "Generate non-clustered indexes for all foreign keys." |
| Cascading Delete Disasters | AI often assumes parent-child relationships should cascade, which violates financial retention rules. | Add to #file:DBA_Rules.md: "Never use ON DELETE CASCADE. Default to NO ACTION."
|
| Data Type Hallucinations | AI using VARCHAR(MAX) for simple text fields or MONEY (which has precision issues) instead of DECIMAL(19,4). |
Explicitly state in rules: "Use DECIMAL(18,4) for currency. Avoid MONEY data type." |
| Flat "God Tables" | AI merges Tenants, Billing, and Subscriptions into one 50-column table because it failed to normalize. | Tell Copilot Chat: "This is denormalized. Refactor this strictly into 3rd Normal Form." |
| Execution Error: Object already exists | Copilot rarely includes DROP TABLE IF EXISTS or checks for existence in its raw output. |
Prompt: "Make the script idempotent. Include DROP TABLE IF EXISTS in reverse dependency order." |
Let's make sure we hit our marks today. Check these off on your screens:
- I successfully passed a markdown business requirement into Copilot Chat.
- The generated schema correctly split the data into at least 5 distinct tables (3NF).
- I visually verified that no
ON DELETE CASCADEstatements exist in the final script. - I validated that Copilot generated non-clustered indexes for all foreign key columns after being prompted.
- I successfully executed the idempotent script against my local sandbox instance without errors.
You've built the schema. Now, the developers are going to write terrible queries against it.
In Day 5: The Query Whisperer – Real-Time Execution Plan Analysis & Tuning, we will dive into performance. You will learn how to extract an XML execution plan from a struggling query, feed it directly into the LLM, and have Copilot identify bookmark lookups, sort warnings, and suggest precise CREATE INDEX statements to drop your logical reads from 50,000 down to 5.
Bring your worst-performing queries tomorrow. Class dismissed!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-4, understanding of basic SQL Server storage engines.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Leverage AI to analyze query access patterns against table schemas to programmatically design optimal, high-performance indexing strategies without creating index bloat.
By the end of this module, you will be able to:
- Articulate the fundamental structural differences between Heaps, Clustered, and Non-Clustered B-Tree indexes to an AI model.
- Construct precise context prompts that combine both Table DDL and Query Workloads for accurate AI index generation.
-
Enforce best practices for covering indexes by guiding the AI to correctly separate key columns from
INCLUDEcolumns. - Diagnose suboptimal AI-suggested indexes, specifically correcting the order of equality vs. inequality predicate columns.
- Validate the proposed index strategy to ensure it minimizes logical reads without causing excessive write-latency overhead.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Database |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): When providing query workloads to Copilot for index analysis, ensure your sample queries do not contain live PII in the
WHEREclause predicates (e.g., useWHERE Email = '[email protected]'instead of a real user's email).🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): AI will frequently suggest indexing every column to "improve reads." In highly audited environments, remember that every new index adds write overhead. Modifying core financial tables with heavy indexes can impact transaction throughput, which must be documented in your change management system.
Welcome back, everyone. Today we tackle the DBA's bread and butter: Indexing.
Most developers guess when it comes to indexes. They see a slow query, right-click in SSMS, and just index whatever column is in the WHERE clause. This leads to tables with 25 overlapping indexes, massive write latency, and page splits.
When we use AI for index design, we run into the "Blind AI" problem again. The LLM knows how a B-Tree works, but it does not know your data distribution. To get Copilot to build a truly optimal Covering Index, you must feed it two distinct pieces of context simultaneously: the Data Model (DDL) and the Access Pattern (Query).
Here is the architectural flow for AI-assisted index design:
┌─────────────────────────────────────────────────────────────┐
│ YOUR IDE (ADS / VS Code) │
│ │
│ ┌──────────────────┐ ┌───────────────────────────────┐ │
│ │ Table DDL (#file)│ │ Workload Query (#selection) │ │
│ │ (The Structure) │ │ (The Access Pattern) │ │
│ └────────┬─────────┘ └──────────────┬────────────────┘ │
│ │ │ │
│ ┌────────▼─────────────────────────────▼────────────────┐ │
│ │ Copilot Chat Context Window │ │
│ │ "Design an optimal non-clustered index covering..." │ │
│ └──────────────────────────────────────┬────────────────┘ │
└─────────────────────────────────────────┼───────────────────┘
│ HTTPS
▼
┌─────────────────────────────┐
│ GitHub Copilot Backend │
│ (LLM Inference Engine) │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ CREATE NONCLUSTERED INDEX │
│ (With INCLUDE columns) │
└─────────────────────────────┘
The AI will often just list columns alphabetically or in the order they appear in the WHERE clause. As DBAs, we know the golden rule of compound indexes: Equality predicates first, Inequality (range) predicates second. We must explicitly enforce this rule in our system prompts.
Field Note: I once audited a database where an AI assistant had suggested an index on
(CreatedDate, StatusID)for a query looking forStatusID = 1 AND CreatedDate > '2026-01-01'. The developer deployed it. Because the range column (CreatedDate) was leading, the engine couldn't seek to the exactStatusIDefficiently. We swapped the column order to(StatusID, CreatedDate)and query execution dropped from 4 seconds to 12 milliseconds. Always double-check the AI's key column order.
We will use Copilot Chat to analyze access patterns and suggest advanced indexing strategies, including INCLUDE columns and filtered indexes.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Dual Context |
#file:Table.sql + #selection
|
Feeding Copilot the table structure AND the specific slow query simultaneously. |
| Include Specification | "Use INCLUDE for SELECT..." |
Forcing Copilot to create a covering index instead of a wide, bloated composite key. |
| Filtered Indexes | "Suggest a filtered index..." |
Creating highly optimized, small footprint indexes for skewed data (e.g., WHERE IsDeleted = 0). |
Ensure your workspace is clean. We need our DDL separated from our query analysis files.
Performance-Tuning-Workspace/
├── DDL/
│ └── 01_TransactionTable.sql <-- The Table Structure
└── Workloads/
└── 01_DailyReportQuery.sql <-- The Access Pattern
Alright, let's get into the lab. We have a massive Transactions table, and the nightly reporting query is timing out. We need to design the perfect covering index.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Force Copilot to generate a mathematically optimal non-clustered index using key order best practices and INCLUDE columns. |
| Target Instance | Local Developer Edition or Azure SQL |
| Duration | 90 Minutes |
| Deliverables | A perfectly structured CREATE NONCLUSTERED INDEX T-SQL statement. |
In your IDE, create a file named TransactionTable.sql inside your DDL folder. Paste the following:
CREATE TABLE dbo.FinancialTransactions (
TransactionID BIGINT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
TenantID INT NOT NULL,
CustomerID INT NOT NULL,
Amount DECIMAL(18,4) NOT NULL,
CurrencyCode CHAR(3) NOT NULL,
TransactionType VARCHAR(20) NOT NULL,
StatusID INT NOT NULL,
CreatedDate DATETIME2 NOT NULL,
ProcessedDate DATETIME2 NULL,
GatewayReference VARCHAR(100) NULL,
RefundReason VARCHAR(255) NULL,
IsFlagged BIT NOT NULL DEFAULT 0,
RiskScore INT NULL,
ModifiedBy VARCHAR(50) NOT NULL,
ModifiedDate DATETIME2 NOT NULL
);Create a second file named DailyReportQuery.sql in your Workloads folder. Paste the following query:
-- Nightly Financial Report
SELECT
TransactionID,
CustomerID,
Amount,
CurrencyCode,
ProcessedDate
FROM dbo.FinancialTransactions
WHERE StatusID = 3 -- 3 = 'Settled'
AND CreatedDate >= '2026-10-01'
AND CreatedDate < '2026-11-01';Highlight the query in DailyReportQuery.sql. Open Copilot Chat (Ctrl+Alt+I). Type this exact prompt:
"Acting as a Senior SQL Server DBA, review the query in my #selection against the table structure in #file:TransactionTable.sql. Design the optimal Non-Clustered Covering Index for this exact query. Ensure equality predicates are leading in the index key, followed by inequality predicates. Put all other retrieved columns into the INCLUDE clause. Output the CREATE INDEX script."
Look closely at the T-SQL Copilot generated.
🔍 Pause & Inspect Checkpoint:
- Look at the key columns (inside the parentheses). Is
StatusIDlisted beforeCreatedDate? If not, the AI failed the equality-first rule.- Look at the
INCLUDEclause. It should containTransactionID,CustomerID,Amount,CurrencyCode, andProcessedDate.- Wait—look closer. Is
TransactionIDin theINCLUDElist? SinceTransactionIDis the Clustered Primary Key, it is already silently included in every non-clustered index. A senior DBA knows not to explicitly declare it. Did the AI know that?- Raise your hand if your AI included TransactionID explicitly. (If it did, challenge it in chat: "TransactionID is the clustered key. Should it be explicitly included?")
Copy your vetted CREATE NONCLUSTERED INDEX statement, review it one last time, and execute it against your test database.
⚡ Lab Micro-Challenge: We only ever run this query for
StatusID = 3. In the same chat thread, ask Copilot: "Rewrite this index as a SQL Server Filtered Index to save disk space, assuming we only care about Settled transactions." See how it movesStatusIDout of the key entirely and into aWHEREclause in the index definition!
AI loves to suggest indexes. It doesn't love to think about storage costs.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Suboptimal Key Order | LLM places range/inequality columns (Date > X) before equality columns (Status = Y). |
Explicitly prompt: "Enforce the rule: Equality columns first, Inequality columns second in the key." |
| Massive Key Size (Error 900 bytes limit) | AI puts all SELECT columns into the main Index Key instead of the INCLUDE clause. |
Prompt: "Keep the key narrow. Move non-search columns to the INCLUDE clause." |
| Redundant Explicit Clustered Keys | AI adds the Primary Key to the INCLUDE list, wasting tokens and clarity. |
Inform Copilot: "Do not explicitly include the Clustered PK in the INCLUDE list, as it is already present at the leaf level." |
| Ignoring Fill Factor | Indexing highly volatile columns (like ModifiedDate) without adjusting fill factor leads to page splits. |
Add to prompt: "This is a high-OLTP table. Suggest an appropriate FILLFACTOR for this index." |
Check these off to confirm you've mastered AI index generation:
- I successfully provided both a DDL file and a workload query to Copilot Chat.
- I forced Copilot to separate Index Key columns from
INCLUDEcolumns. - I verified that the equality predicate (
StatusID) preceded the range predicate (CreatedDate). - I challenged the AI on explicit inclusion of the Clustered Primary Key.
- I successfully generated a Filtered Index variant for skewed data workloads.
You now know how to build the perfect schema and the perfect index. But what happens when the ORM (Entity Framework or Hibernate) sends a nightmare query to your engine?
In Day 6: Execution Plan Analysis & Legacy Code Refactoring, we are going to extract raw XML execution plans, feed them directly into the LLM, and have Copilot identify bookmark lookups, sort warnings, and parameter sniffing issues. Bring your worst-performing queries tomorrow!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-5, solid understanding of Stored Procedures and temporary table mechanics.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Overcome the historic friction of database unit testing by leveraging AI to rapidly generate mock data, isolated test harnesses, and comprehensive edge-case assertions for Test-Driven Development (TDD).
By the end of this module, you will be able to:
- Articulate the principles of Test-Driven Development (TDD) as applied to relational databases and stored procedures.
- Construct deterministic mock data sets using Copilot to isolate procedure logic from live transactional data.
- Enforce rigorous boundary testing (e.g., zero values, negative numbers, nulls) by explicitly prompting AI to generate edge-case scenarios.
- Diagnose fragile test harnesses, specifically identifying missing rollback mechanics or lingering temporary objects that pollute the database.
- Validate business logic autonomously using standard T-SQL assertions (or frameworks like tSQLt) generated by AI.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Database |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): When using AI to generate mock data for testing, you must ensure it does not accidentally regenerate real PII based on your prompt context. Always explicitly instruct the LLM to use synthetically generated, fictional names and randomized non-identifying data.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Financial and healthcare regulations require demonstrable proof that business logic operates correctly before deployment. A robust, automated T-SQL test harness fulfills the "automated validation" requirement for CI/CD pipelines under SOC2 Type II compliance.
Welcome back. Take your seats. Today, we confront the reality of database engineering: We are terrible at testing our own code.
Application developers have had JUnit, NUnit, and xUnit for decades. They write a test, watch it fail, write the code, and watch it pass. DBAs, on the other hand, typically deploy a stored procedure, run it once with a "happy path" parameter, see that it returns rows, and call it a day.
Why? Because mocking relational data is excruciating. To test a discounting procedure, you might need to mock a Customer, an Order, three OrderLines, and a PricingTier. It takes two hours to write the test for ten minutes of code.
Today, we fix this. AI is exceptionally good at generating synthetic data and writing boilerplate assertions.
┌─────────────────────────────────────────────────────────────┐
│ YOUR IDE (ADS / VS Code) │
│ │
│ ┌──────────────────┐ ┌───────────────────────────────┐ │
│ │ Target Proc DDL │ │ Boundary Requirements │ │
│ │ (#file) │ │ (0%, negative values, NULLs) │ │
│ └────────┬─────────┘ └──────────────┬────────────────┘ │
│ │ │ │
│ ┌────────▼─────────────────────────────▼────────────────┐ │
│ │ Copilot Chat Context Window │ │
│ │ "Generate a T-SQL test harness using temp tables..." │ │
│ └──────────────────────────────────────┬────────────────┘ │
└─────────────────────────────────────────┼───────────────────┘
│ HTTPS
▼
┌─────────────────────────────┐
│ GitHub Copilot Backend │
│ (LLM Inference Engine) │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Test Harness Script │
│ (Mock Data + Assertions) │
└─────────────────────────────┘
Field Note: A few years ago, an e-commerce client deployed a new discount calculation procedure right before Black Friday. It was only tested with standard cart values ($50, $100). A user discovered that if they applied a specific coupon combination, their cart total went to -$5.00, and the system credited their credit card. A simple boundary test for negative integers would have saved the company a quarter of a million dollars. Today, we force the AI to write that exact test.
We will use Copilot Chat to build isolated testing scripts. By "isolated," we mean tests that do not rely on existing data in the database, using either #TempTables or BEGIN TRAN / ROLLBACK wrappers.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Boundary Injection | "Test boundary conditions..." |
Forcing Copilot to test edge cases (NULL, zero, negatives, max values). |
| Mock Data Gen | "Generate 5 rows of synthetic data" |
Quickly populating temporary tables with INSERT statements to satisfy FK relationships. |
| Assertion Setup | "Assert that Actual equals Expected" |
Generating the IF...ELSE or THROW logic that fails the test if the SP returns the wrong data. |
TDD-Project-Workspace/
├── Procedures/
│ └── usp_CalculateDiscountTier.sql <-- The target code
└── Tests/
└── test_CalculateDiscountTier.sql <-- The AI-generated harness
Alright, let's build this. We are going to deploy a slightly flawed stored procedure for calculating discounts, and then use AI to build a test harness that catches the flaw.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Generate an isolated T-SQL test harness to validate stored procedure logic and catch edge-case failures. |
| Target Instance | Local Developer Edition or Azure SQL (tempdb) |
| Duration | 90 Minutes |
| Deliverables | A complete, repeatable T-SQL testing script with mock data and assertions. |
In your IDE, create a file named usp_CalculateDiscountTier.sql. Paste and run this script in your sandbox database:
CREATE OR ALTER PROCEDURE dbo.usp_CalculateDiscountTier
@PurchaseAmount DECIMAL(18,2),
@DiscountPercent DECIMAL(5,2) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
-- Basic tier logic
IF @PurchaseAmount >= 1000
SET @DiscountPercent = 20.00;
ELSE IF @PurchaseAmount >= 500
SET @DiscountPercent = 10.00;
ELSE
SET @DiscountPercent = 0.00;
-- Note: No handling for negative numbers!
END;
GOCreate a new file called test_CalculateDiscountTier.sql.
Open Copilot Chat (Ctrl+Alt+I). Type this exact prompt:
"Acting as a Senior Database QA Engineer, review the stored procedure in #file:usp_CalculateDiscountTier.sql. Generate a T-SQL test harness script to test this procedure. I want you to test the following boundary conditions: a standard purchase ($600), a high purchase ($1500), a $0 purchase, and a negative purchase amount (-$100). Use variables to capture the output and write explicit assertions (using THROW or PRINT) to validate the expected DiscountPercent for each scenario."
Look closely at the generated T-SQL.
🔍 Pause & Inspect Checkpoint:
- Did the AI create individual test cases for all four scenarios?
- Look at the negative purchase amount test. What did the AI declare as the expected result? Since the SP defaults to
0.00for anything under 500, the AI likely expects0.00.- Does the test harness clean up after itself?
- Raise your hand if your AI used a
TRY...CATCHblock for the assertions.
Copy the generated code into your SQL window and hit F5.
You should see output confirming the tests. You will immediately notice that a negative purchase amount results in a 0% discount. In a real business scenario, a negative purchase (a refund) should likely throw an error, not calculate a zero discount. The test harness has surfaced a business logic gap!
Modify the original stored procedure to handle the negative amount:
IF @PurchaseAmount < 0
THROW 50001, 'Purchase amount cannot be negative.', 1;Now, ask Copilot to update the test harness:
"I updated the procedure to THROW an error if the amount is negative. Update the test harness so that the negative purchase test explicitly expects an error to be caught."
⚡ Lab Micro-Challenge: For those already done: Raw T-SQL test harnesses are great, but
tSQLtis the industry standard. Open Chat and prompt: "Rewrite this entire test harness using the tSQLt framework syntax. Assume the test class is named [DiscountTests]." Watch how it structures theEXEC tSQLt.AssertEqualscommands!
Writing tests with AI is fast, but it requires strict oversight.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| State Pollution | The AI inserts mock data into actual physical tables without a ROLLBACK, ruining your dev environment. |
Enforce isolation in the prompt: "Wrap all DML operations in a BEGIN TRAN / ROLLBACK TRAN block." |
| AI Confirms Bad Logic | The LLM looks at your flawed SP and writes a test that expects the flawed output (circular logic). | You must manually dictate the expected business outcome in your prompt, not just ask the AI to "write a test." |
| Missing Identity Inserts | The AI tries to insert mock data into an IDENTITY column and the script fails. |
Prompt: "Remember to use SET IDENTITY_INSERT ON if inserting mock data into primary keys." |
| Testing Only the Happy Path | Copilot generates 5 tests for normal values and ignores edge cases. | Explicitly list the boundary conditions in the prompt: "Test NULL, 0, and negative values." |
Ensure you have completed the following before wrapping up:
- I deployed the target stored procedure to my sandbox.
- I successfully prompted Copilot to generate a multi-scenario T-SQL test harness.
- I verified that the AI-generated assertions correctly evaluated the
OUTPUTparameters. - I identified the logical flaw (negative numbers) exposed by the boundary tests.
- I understand the difference between letting AI guess the expected outcome versus defining the business rules explicitly in the prompt.
You now have a robust schema, highly tuned indexes, and automated unit tests. But how do we deploy this safely across environments?
In Day 7: Automated CI/CD Pipelines and Database Source Control, we will step out of the database engine and into DevOps. You will learn how to use GitHub Copilot to generate YAML deployment pipelines, configure SQLPackage.exe, and automate the execution of the very tests we wrote today.
Make sure you have an active GitHub account and basic familiarity with Git commits for tomorrow's session!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1–6, accumulated T-SQL scripts from previous labs.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Consolidate Week 1 learnings by auditing AI-generated artifacts for security and performance, identifying model hallucinations, and codifying successful interactions into a standardized, reusable enterprise Prompt Bank.
By the end of this module, you will be able to:
- Articulate the difference between a high-value AI interaction and a net-negative interaction (where review time exceeds generation time).
-
Construct a centralized
Prompt_Bank.mdcontaining highly engineered, parameterized prompts for daily DBA tasks. - Enforce internal DBA security baselines by performing a retrospective audit on all code generated during the week.
- Diagnose structural hallucinations in AI output (e.g., fabricated DMVs, deprecated syntax, or impossible execution plan operators).
- Validate the operational time savings achieved by comparing pre-AI and post-AI workflow durations for tasks like data modeling and testing.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| Workspace | The combined workspace files generated in Labs 1 through 6 |
| Network | Offline-capable for the audit; outbound HTTPS for prompt refinement |
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): As we build our Prompt Bank today, ensure that your saved prompt templates contain zero live data. Use placeholder tokens like
[CUSTOMER_ID]or<TableName>. A Prompt Bank is often shared across teams; hardcoding PII into a shared template violates data minimization principles.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Auditing AI-generated code against security baselines is a mandatory control. You must be able to demonstrate that AI is acting as a drafting tool, not an approving authority. The DBA remains the final control gate for SOX financial schemas or HIPAA data pipelines.
Welcome to the end of Week 1, everyone. Take a breath. We’ve covered a massive amount of ground—from setting up secure AI workspaces to building physical data models and unit tests out of thin air.
Today is about taking a step back. I want you to look at AI not as magic, but as a probabilistic tool. Sometimes the tool is sharp. Sometimes it hallucinates wildly.
The goal of AI is to save you time. However, if Copilot generates 500 lines of complex, nested dynamic SQL, and it takes you 4 hours to verify it isn't going to drop master, you haven't saved time—you've incurred technical debt.
Hallucinations in the DBA world are particularly dangerous because they often look completely plausible.
┌─────────────────────────────────────────────────────────────┐
│ THE HALLUCINATION TRAP │
│ │
│ User: "Find the memory utilization per database." │
│ │
│ AI: SELECT DB_NAME(database_id), memory_usage_mb │
│ FROM sys.dm_os_database_memory_stats; <-- FAKE DMV! │
│ │
│ Result: Invalid object name 'sys.dm_os_database_memory... │
└─────────────────────────────────────────────────────────────┘
The AI knows that sys.dm_os_... is a pattern for OS-level DMVs. It knows you asked about memory. So, it invents a view that sounds perfect but does not exist in SQL Server. Your job is to catch these instantly.
Field Note: Raise your hand if Copilot lied to you this week. Don't be shy, my hand is up too. A few months ago, I asked Copilot to generate a script to clear the procedure cache for a single database. It confidently gave me
DBCC FREEPROCCACHE. Luckily, I caught it before hitting F5 in production, because that command clears the cache for the entire instance, which would have caused a massive CPU spike. Trust, but aggressively verify.
The difference between a junior AI user and a senior AI user is the quality of their prompts. We are moving away from Zero-Shot Prompting (asking a question with no context) to Few-Shot Parameterized Prompting.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Zero-Shot | "Write a backup script" |
Bad. Yields generic, often outdated code. |
| System-Guided | "Use #file:DBA_Rules.md to write a backup script" |
Better. Enforces naming conventions and basic rules. |
| Parameterized Template | "Act as Sr DBA. Use [DB_NAME]. Perform CHECKSUM and COMPRESSION." |
Best. Highly reusable and deterministic. |
Today, we add the most valuable file in your repository: the Prompt Bank.
DBA-Master-Workspace/
├── Guidelines/
│ └── DBA_Rules.md
├── Prompts/
│ └── Prompt_Bank.md <-- Your personal library of engineered prompts
└── Code_Review/
└── Audit_Log_Week1.txt <-- Output from our Lab 7 security review
Today's lab is a retrospective audit and a consolidation of our assets.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Audit the week's AI code for security baselines and establish a reusable Prompt Bank. |
| Target Instance | Offline / IDE workspace review |
| Duration | 90 Minutes |
| Deliverables | A sanitized, peer-reviewed codebase and a populated Prompt_Bank.md file. |
Open every .sql file you generated in Days 1 through 6. We are looking for AI-introduced vulnerabilities.
-
Search for
sa: Did the AI default to using thesaaccount in any connection strings, linked servers, or execution contexts? If so, remove it. -
Search for
VARCHAR(MAX): Did the AI lazily assignMAXtypes to columns that should be strictly constrained (like a Zip Code or State Abbreviation)? -
Check Constraint Verification: Open the schema we built on Day 4. Did the AI actually include
CONSTRAINT [Name]or did it leave the constraints unnamed, creating system-generated GUID names (which makes them impossible to drop later)?
In your Prompts folder, create a new file named Prompt_Bank.md. We are going to codify the best interactions we had this week.
Paste this structure into your file:
# DBA Prompt Bank
## 1. Index Generation (Day 5)
**Prompt:**
> "Acting as a Senior SQL Server DBA, review the query in my #selection against the table structure in #file:[TABLE_DDL.sql]. Design the optimal Non-Clustered Covering Index. Enforce the rule: Equality predicates leading, followed by Inequality predicates. Put all other retrieved columns into the INCLUDE clause. Do not explicitly include the Clustered PK."
## 2. Schema Normalization (Day 4)
**Prompt:**
> "Act as an enterprise Data Architect. Read #file:[REQUIREMENTS.md]. Generate T-SQL DDL for a fully normalized 3NF schema. Ensure all tables use the `dbo` schema, no cascading deletes are used, and generate non-clustered indexes for ALL foreign keys."Look at the prompts above. Notice how we replaced specific file names with [TABLE_DDL.sql]?
🔍 Pause & Inspect Checkpoint:
- Look through your Prompt Bank. Are there any hardcoded server IPs?
- Are there any specific client names or proprietary business terms?
- Scrub them out. Replace them with bracketed variables like
[CLIENT_NAME]. Your Prompt Bank should be safe to share on a public GitHub repo without leaking corporate secrets.
⚡ Lab Micro-Challenge: Sometimes you have a terrible legacy query and you want Copilot to explain it. Write a prompt for your Prompt Bank designed to Deconstruct and Explain a query. (Hint: Tell the AI to explain it step-by-step, targeting a Junior DBA audience, and to specifically call out potential performance bottlenecks like implicit conversions or cursors). Add it as item #3 in your Prompt Bank.
Reviewing AI output requires a specific mindset. Watch out for these traps:
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Prompt Drift | Using a prompt that worked in Copilot v1, but behaves poorly in a newer model version. | Regularly test and update your Prompt Bank. Version control your Prompt_Bank.md. |
| The "Looks Good To Me" (LGTM) Trap | Skimming AI code instead of reading it line-by-line, missing subtle logic flaws. | Read AI code backwards, or read it strictly looking for one issue at a time (e.g., first pass: datatypes. second pass: constraints). |
| Fake System Procs | AI hallucinates EXEC sp_flush_memory instead of DBCC FREESYSTEMCACHE. |
If you don't instantly recognize the DMV or SP, look it up in Microsoft Learn before executing. |
| Leaking Context | You paste an execution plan containing parameter values (PII) into chat. | Sanitize execution plans (remove literal values) before asking AI for tuning advice. |
Check these off before we dismiss the class for the week:
- I audited all Week 1 T-SQL scripts for security and naming convention baselines.
- I identified and corrected at least one instance of suboptimal AI behavior from previous labs.
- I created a
Prompt_Bank.mdfile in my workspace. - I parameterized my prompts to ensure no sensitive data or hardcoded environments are saved.
- I understand how to measure if an AI interaction is actually saving me time.
Congratulations on completing Week 1: The AI-Augmented DBA Foundation.
Next week, we graduate from writing T-SQL to automating the infrastructure. In Week 2: AI-Driven DevOps and Automation, we will focus on using Copilot to write PowerShell modules, construct dbatools migration scripts, and generate YAML pipelines for automated database deployments.
Rest up, patch your local instances, and I will see you on Monday!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Phase 1 (Days 1-7), strong understanding of indexing and logical reads. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Train DBAs to identify, quantify, and programmatically refactor non-SARGable T-SQL predicates using AI, transforming crippling Index Scans into highly efficient Index Seeks.
By the end of this module, you will be able to:
- Articulate the principles of SARGability (Search Argument Able) and explain exactly why wrapping an indexed column in a scalar function forces the SQL engine to scan.
-
Construct measurable baseline metrics using
SET STATISTICS IO ONto quantify the physical cost of bad query predicates. - Enforce SARGable rewriting techniques by utilizing GitHub Copilot Chat to automatically refactor legacy reporting queries.
-
Diagnose hidden non-SARGable patterns, such as implicit data type conversions and leading wildcard
LIKEoperators. - Validate the success of AI-refactored code by proving a reduction in logical page reads and confirming the presence of an Index Seek operator.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Database |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): When pasting legacy queries into Copilot Chat for refactoring, ensure you scrub any literal string values that might contain PII (e.g., replace
WHERE Email = '[email protected]'withWHERE Email = '[email protected]'). Performance tuning does not require real payload data.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Refactoring queries often changes the execution plan, which can drastically alter CPU and Memory utilization on shared multi-tenant clusters. Ensure all AI-generated query refactors are load-tested in a staging environment mirroring production data volumes before deploying to SOC2-audited systems.
Welcome to Phase 2, everyone. Week 1 was all about building schemas and indexes correctly. But what happens when developers write queries that completely ignore the beautiful indexes we just built?
This is the concept of SARGability (Search-ARGument-ABLE).
Imagine I hand you a printed telephone book and ask you to find "Smith, John". You use the alphabetical index, jump to 'S', then 'Sm', and you find it in seconds. That is an Index Seek. Now, imagine I ask you to find everyone whose last name ends with "mith". The alphabetical index is useless. You have to read every single page of the phone book from start to finish. That is an Index Scan.
In SQL Server, if you wrap an indexed column in a function, the optimizer goes blind.
┌─────────────────────────────────────────────────────────────┐
│ THE SARGABILITY PENALTY │
│ │
│ Index on: OrderDate (DATETIME) │
│ │
│ BAD (Scan): WHERE YEAR(OrderDate) = 2026 │
│ Optimizer thinks: "I have to evaluate the │
│ YEAR() function on every row before I know │
│ if it matches. I must read the whole table." │
│ │
│ GOOD (Seek): WHERE OrderDate >= '2026-01-01' │
│ AND OrderDate < '2027-01-01' │
│ Optimizer thinks: "I know exactly where these │
│ values start and stop in the B-Tree." │
└─────────────────────────────────────────────────────────────┘
Field Note: Years ago, an ORM update pushed a query to a massive 2-billion-row financial ledger table. The query had a
WHERE ISNULL(IsCleared, 0) = 0predicate.IsClearedwas perfectly indexed, but theISNULLfunction wrapped the column, destroying SARGability. The query went from running in 4 milliseconds to 45 minutes, taking the storage array to 100% latency. The fix took 10 seconds to write (WHERE IsCleared = 0 OR IsCleared IS NULL), but it took a Sev 1 outage to find it. Today, we use AI to preemptively rewrite these.
AI models are exceptionally good at pattern recognition, which makes them perfect for translating non-SARGable predicates into range queries.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Query Selection | Highlight code -> Chat -> #selection
|
Feeding a specific badly-written WHERE clause to the AI without pasting the whole 500-line proc. |
| Explicit Directive | "Rewrite this to be SARGable" |
Using DBA-specific terminology triggers the LLM's advanced SQL tuning pathways. |
| Index Hinting | "Assume an index exists on [Col]" |
Giving the AI context so it prioritizes rewriting predicates affecting that specific column. |
Performance-Tuning-Workspace/
├── Data_Setup/
│ └── 01_Create_Large_Table.sql <-- Our 100k row test bed
└── Queries/
├── 01_Bad_Query.sql <-- The developer's original code
└── 02_AI_Refactored.sql <-- Copilot's SARGable rewrite
Let's prove the math. We are going to generate a table with 100,000 rows, write a terrible query, measure the I/O penalty, and have Copilot fix it for us.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Quantify the cost of a non-SARGable query and use Copilot to generate a mathematically equivalent SARGable rewrite. |
| Target Instance | Local Developer Edition or Azure SQL (tempdb or sandbox) |
| Duration | 90 Minutes |
| Deliverables | Before/After STATISTICS IO metrics proving a reduction in Logical Reads. |
In your IDE, open a new SQL file connected to a test database and execute this script to build our 100,000-row table and index:
-- Create the table
CREATE TABLE dbo.Orders (
OrderID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
OrderDate DATETIME NOT NULL,
Amount DECIMAL(10,2) NOT NULL,
CustomerID INT NOT NULL
);
GO
-- Insert 100,000 rows of mock data spanning a few years
WITH CTE AS (
SELECT TOP 100000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n
FROM sys.all_objects a CROSS JOIN sys.all_objects b CROSS JOIN sys.all_objects c
)
INSERT INTO dbo.Orders (OrderDate, Amount, CustomerID)
SELECT
DATEADD(DAY, - (n % 2000), '2027-01-01'), -- Dates going back a few years
(n % 500) * 1.5,
n % 1000
FROM CTE;
GO
-- Create our non-clustered index
CREATE NONCLUSTERED INDEX IX_Orders_OrderDate ON dbo.Orders(OrderDate) INCLUDE (Amount);
GOCreate a file named 01_Bad_Query.sql and paste the following. Execute it, and look at the "Messages" tab for the IO stats.
SET STATISTICS IO ON;
-- The developer wants all orders from the year 2026
SELECT OrderID, OrderDate, Amount
FROM dbo.Orders
WHERE YEAR(OrderDate) = 2026;
SET STATISTICS IO OFF;🔍 Pause & Inspect Checkpoint: Go to the Messages tab. Look for
Table 'Orders'. Scan count... logical reads...Raise your hand if your logical reads are over 250. Because we usedYEAR(), SQL Server had to read all 100,000 rows to find the matches. This is an Index Scan.
Highlight the SELECT statement. Open Copilot Chat (Ctrl+Alt+I) and type this exact prompt:
"Acting as a Senior Database Performance Tuner, review the T-SQL query in my #selection. The predicate uses a function on an indexed column, making it non-SARGable. Rewrite this query to be completely SARGable so SQL Server can perform an Index Seek on the OrderDate column. Output only the rewritten query."
Copilot should return a query utilizing a >= and < range. Paste it into your query window, wrap it in SET STATISTICS IO ON, and execute it:
SET STATISTICS IO ON;
-- AI Generated Rewrite (Should look similar to this)
SELECT OrderID, OrderDate, Amount
FROM dbo.Orders
WHERE OrderDate >= '2026-01-01' AND OrderDate < '2027-01-01';
SET STATISTICS IO OFF;🔍 Pause & Inspect Checkpoint: Go to the Messages tab again. Check the
logical reads. You should see a massive drop—likely from 250+ reads down to just a handful (proportional to the actual rows returned). You just transformed a Scan into a Seek!
⚡ Lab Micro-Challenge: Functions aren't the only SARGability killers. Write a query using
WHERE CustomerID = '15'(assumingCustomerIDis anINT). The string'15'causes an Implicit Conversion. Pass this to Copilot Chat and ask it: "Explain why this predicate causes an implicit conversion scan and rewrite it."
SARGability is strict. Here is where the AI—or your developers—might still get it wrong.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
LIKE '%term' |
A leading wildcard (%) makes it impossible to traverse the B-Tree alphabetically. |
Prompt AI: "Can we refactor this leading wildcard using Full-Text Search (CONTAINS) or reverse-string indexing?" |
ISNULL(Col, 0) = 0 |
Wrapping a column in ISNULL or COALESCE nullifies the index. |
Prompt AI: "Rewrite this ISNULL predicate to use explicit OR logic (Col = 0 OR Col IS NULL)." |
| Implicit Data Type Conversions | Comparing an NVARCHAR parameter to a VARCHAR column forces an index scan. |
Prompt AI: "Ensure all string parameters match the underlying table data type exactly. Add 'N' prefixes if the column is NVARCHAR." |
| Arithmetic on the Column |
WHERE Amount * 2 > 100 is non-SARGable. |
Prompt AI: "Move the math to the right side of the operator." (Result: WHERE Amount > 100 / 2) |
Confirm you have mastered SARGability refactoring:
- I successfully created the 100k row test table and index.
- I captured baseline
logical readsusingSET STATISTICS IO ONfor the non-SARGable query. - I successfully prompted Copilot to rewrite the
YEAR()function into a date range predicate. - I executed the refactored query and verified a significant drop in logical reads.
- I understand how functions, math, and implicit conversions on the left side of an operator destroy index seeks.
Today we looked at text-based I/O statistics. Tomorrow, things get visual.
In Day 9: AI and the Execution Plan, we are going to extract raw, complex XML execution plans from SQL Server, feed the actual XML into Copilot, and have the AI identify hidden warnings, sort spills to TempDB, and Bookmark Lookups.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Phase 1 and Day 8, strong understanding of T-SQL updates and logical reads. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Eradicate performance-killing procedural loops (Cursors and WHILE loops) from legacy databases by leveraging Copilot to refactor them into high-performance, declarative, set-based operations using Common Table Expressions (CTEs) and Window Functions.
By the end of this module, you will be able to:
- Articulate the fundamental architectural differences between procedural execution (RBAR) and declarative set-based execution in the SQL Server engine.
-
Construct targeted Copilot prompts that instruct the AI to bypass procedural translation and jump straight to modern T-SQL constructs like
SUM() OVER(). - Enforce best practices around tempdb contention by eliminating the hidden overhead generated by nested cursor declarations.
-
Diagnose AI-generated window function edge cases, particularly missing framing clauses (
ROWS UNBOUNDED PRECEDING). - Validate the operational time savings by benchmarking execution speed and CPU time before and after a set-based refactoring.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2012+ or Azure SQL Database (required for Window Functions) |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): In today's lab, we will be refactoring financial ledger calculations. When dealing with real-world cursor removal in legacy ERP systems, ensure you are testing the AI's logic on synthetic or thoroughly anonymized financial data.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Replacing an established cursor with a set-based update alters the foundational logic of a financial calculation (e.g., running balances). Under SOX, any logical change to financial calculation engines requires a documented parity test. The before and after balances must match exactly to a fraction of a cent.
Welcome back. Take your seats. Today we are hunting a DBA's oldest enemy: RBAR. Row-By-Agonizing-Row.
Developers often come to SQL Server with a procedural mindset from languages like C# or Python. To calculate a running total, they think: "Get the first row, hold the value in a variable, get the next row, add it, update the row... loop."
In SQL Server, we use Cursors for this. And Cursors are toxic to concurrency.
When you open a cursor, SQL Server often has to spin up a temporary work table in tempdb. It then issues thousands of microscopic locking operations as it fetches row by row. It breaks the optimizer's ability to parallelize the workload.
We want Declarative Set-Based code. We want to tell SQL Server what we want, not how to do it.
┌─────────────────────────────────────────────────────────────┐
│ PROCEDURAL VS DECLARATIVE EXECUTION │
│ │
│ ❌ Procedural (Cursor): │
│ "Fetch Row 1. Add $10 to Var. Update Row 1. │
│ Fetch Row 2. Add $15 to Var. Update Row 2." │
│ Cost: 100,000 separate transaction log writes. │
│ Time: 3 Minutes. │
│ │
│ ✅ Declarative (Set-Based with Window Functions): │
│ "UPDATE the entire table using SUM() OVER(ORDER BY Date)"│
│ Cost: 1 massive batch update, heavily optimized. │
│ Time: 300 Milliseconds. │
└─────────────────────────────────────────────────────────────┘
Field Note: I once parachuted into a critical healthcare system where the nightly billing routine was taking 14 hours. The business was threatening to buy millions of dollars in flash storage to fix it. We opened the code and found a nested cursor calling a scalar function inside a WHILE loop. It was executing over 40 million context switches per night. We spent one hour refactoring it into a single CTE with a Window Function. Execution time dropped from 14 hours to 42 seconds. No new hardware required. Let's learn how to do that using Copilot.
Translating a 200-line nested cursor into a 10-line set-based query requires Copilot to deeply understand the intent of the code, not just the syntax.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Intent Translation | "What is the business intent of this cursor?" |
Having Copilot summarize the procedural code before attempting a rewrite ensures it grasps the logic. |
| Window Function Prompting | "Rewrite using SUM() OVER() and a CTE." |
Explicitly guiding the AI away from messy self-joins and forcing modern T-SQL constructs. |
| Parity Testing | "Generate a validation query..." |
Asking Copilot to write a query that compares the old output to the new output to prove accuracy. |
Cursor-Removal-Workspace/
├── Data_Setup/
│ └── 01_Ledger_Data.sql <-- The 50,000 row test bed
└── Refactoring/
├── 01_Legacy_Cursor.sql <-- The painful procedural script
└── 02_SetBased_Rewrite.sql <-- Copilot's blazing fast rewrite
We have inherited a legacy banking script that calculates running account balances. It uses a cursor. We are going to benchmark it, laugh at how slow it is, and then ask Copilot to obliterate it.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Benchmark a procedural cursor, use Copilot to convert it to a declarative set-based CTE, and measure the performance gain. |
| Target Instance | Local Developer Edition or Azure SQL |
| Duration | 90 Minutes |
| Deliverables | A single UPDATE statement using a Window Function that replaces 40 lines of cursor logic. |
Execute this script in your sandbox to create our ledger table and populate it with 50,000 rows.
CREATE TABLE dbo.AccountLedger (
LedgerID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
AccountID INT NOT NULL,
TransactionDate DATETIME NOT NULL,
Amount DECIMAL(10,2) NOT NULL,
RunningBalance DECIMAL(10,2) NULL
);
GO
-- Insert 50,000 rows across 500 accounts
WITH CTE AS (
SELECT TOP 50000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n
FROM sys.all_objects a CROSS JOIN sys.all_objects b CROSS JOIN sys.all_objects c
)
INSERT INTO dbo.AccountLedger (AccountID, TransactionDate, Amount)
SELECT
(n % 500) + 1,
DATEADD(MINUTE, n, '2026-01-01'),
(n % 100) * 1.5 - 50.0
FROM CTE;
GO
-- Index for processing
CREATE NONCLUSTERED INDEX IX_Ledger_Account_Date ON dbo.AccountLedger(AccountID, TransactionDate);
GOCreate a file named 01_Legacy_Cursor.sql. Paste the following cursor script. Run it, and note the execution time.
SET STATISTICS TIME ON;
DECLARE @AccountID INT;
DECLARE @Amount DECIMAL(10,2);
DECLARE @RunningTotal DECIMAL(10,2);
DECLARE @LedgerID INT;
-- Reset table for a clean test
UPDATE dbo.AccountLedger SET RunningBalance = NULL;
DECLARE acct_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT AccountID FROM dbo.AccountLedger GROUP BY AccountID;
OPEN acct_cursor;
FETCH NEXT FROM acct_cursor INTO @AccountID;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @RunningTotal = 0;
DECLARE tran_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT LedgerID, Amount FROM dbo.AccountLedger
WHERE AccountID = @AccountID ORDER BY TransactionDate;
OPEN tran_cursor;
FETCH NEXT FROM tran_cursor INTO @LedgerID, @Amount;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @RunningTotal = @RunningTotal + @Amount;
UPDATE dbo.AccountLedger
SET RunningBalance = @RunningTotal
WHERE LedgerID = @LedgerID;
FETCH NEXT FROM tran_cursor INTO @LedgerID, @Amount;
END
CLOSE tran_cursor;
DEALLOCATE tran_cursor;
FETCH NEXT FROM acct_cursor INTO @AccountID;
END
CLOSE acct_cursor;
DEALLOCATE acct_cursor;
SET STATISTICS TIME OFF;🔍 Pause & Inspect Checkpoint: Depending on your hardware, that likely took anywhere from 5 to 15 seconds. For 50,000 rows, that is catastrophically slow. Raise your hand if your execution time was over 10 seconds.
Highlight the entire cursor block. Open Copilot Chat and type this exact prompt:
"Acting as a Senior Database Performance Tuner, review the nested cursor in my #selection. It calculates a running balance per account. Convert this nested cursor into a single, highly optimized set-based UPDATE statement. Use an updatable Common Table Expression (CTE) combined with the SUM() OVER() window function partitioned by AccountID and ordered by TransactionDate. Output only the refactored T-SQL code."
Copilot should output a query similar to this. Paste it, reset the table, and run it:
SET STATISTICS TIME ON;
-- Reset table for a clean test
UPDATE dbo.AccountLedger SET RunningBalance = NULL;
-- AI Refactored Set-Based Update
WITH RunningBalanceCTE AS (
SELECT
LedgerID,
RunningBalance,
SUM(Amount) OVER (
PARTITION BY AccountID
ORDER BY TransactionDate
ROWS UNBOUNDED PRECEDING
) AS CalculatedBalance
FROM dbo.AccountLedger
)
UPDATE RunningBalanceCTE
SET RunningBalance = CalculatedBalance;
SET STATISTICS TIME OFF;🔍 Pause & Inspect Checkpoint: Check your execution time. It should have completed in well under 1 second. You just achieved a massive performance gain by abandoning procedural logic.
⚡ Lab Micro-Challenge: Ask Copilot what the phrase
ROWS UNBOUNDED PRECEDINGdoes in the window function, and why leaving it out might cause a massive performance hit due to on-disk spooling.
Window functions are powerful but tricky. Watch out for AI hallucinations here.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| AI suggests a Correlated Subquery | Copilot might use (SELECT SUM(...) FROM ... WHERE T1.ID = T2.ID). This is just a hidden loop and performs terribly. |
explicitly dictate: "Do not use correlated subqueries. You MUST use the SUM() OVER() window function." |
| Missing Framing Clause | AI forgets ROWS UNBOUNDED PRECEDING. By default, SQL Server uses RANGE UNBOUNDED PRECEDING, which causes heavy TempDB spooling. |
Add to prompt: "Ensure the window function framing explicitly uses ROWS, not RANGE, for optimal performance." |
| CTE Update Fails | AI tries to update a CTE that uses an aggregate function in the SELECT list (which is illegal). |
Verify the AI applied the window function to a derived column, and the UPDATE targets the physical column mapped in the CTE. |
Confirm you have mastered cursor eradication:
- I successfully ran the procedural cursor and captured the baseline execution time.
- I prompted Copilot Chat to refactor the logic into a CTE with a Window Function.
- I ensured the AI correctly partitioned the data by
AccountIDand ordered byTransactionDate. - I executed the set-based update and verified the massive reduction in elapsed time.
- I understand the distinction between Row-By-Agonizing-Row (RBAR) and Declarative SQL.
You've eliminated scans and eradicated cursors. But sometimes, queries are still slow, and you can't figure out why.
In Day 10: XML Execution Plan AI Analysis, we are going to extract the raw XML execution plan of a complex, struggling query. We will feed that raw XML directly into Copilot Chat and have the AI act as an automated execution plan analyzer, identifying sort warnings, implicit conversions, and missing index spools.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Phase 1 and Days 8-9, solid understanding of JOIN types. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Demystify complex execution plans by teaching DBAs how to extract specific, problematic XML plan nodes and feed them into AI for instant diagnosis of cost bottlenecks, join selections, and sort warnings.
By the end of this module, you will be able to:
-
Articulate the difference between the graphical execution plan and the underlying XML schema that drives it.
-
Construct targeted XML extractions (Micro-RAG) to fit execution plan fragments within the AI's token limit without losing diagnostic context.
-
Diagnose physical operator choices (e.g., Hash Match vs. Nested Loops) by having AI analyze the cardinality estimates and missing indexes within the XML.
-
Enforce data privacy by scrubbing the
<ParameterList>XML nodes of any PII before passing plan fragments to the LLM. -
Validate AI-recommended index or query adjustments by comparing the "Before" and "After" execution plan shapes.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SSMS v19+ (For easy graphical/XML toggling) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Database |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Execution Plan XMLs contain a node called
<ParameterList>. If your query uses parameters (e.g.,@UserEmail = '[email protected]'), this real data is embedded directly into the XML. You must scrub or remove the<ParameterList>node before pasting execution plans into Copilot to avoid a GDPR data processor violation.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): When tuning queries that impact SOX-compliant financial reporting, ensure you document the AI's explanation of the execution plan change in your Jira/ServiceNow ticket. Auditors want to see why an index was added, not just that an AI suggested it.
Welcome back, class. Today, we are opening the black box.
When you click "Include Actual Execution Plan" in SSMS or Azure Data Studio, you get a beautiful graphical tree of operators (Index Seeks, Hash Matches, Sorts). But SQL Server doesn't generate pictures; it generates a highly detailed XML document. The UI simply renders that XML.
When a query is slow, we usually look for the operator with the highest "Cost %". But the why is buried in the XML: Did it spill to TempDB? Were the estimated rows drastically different from the actual rows? Did implicit conversion prevent a seek?
LLMs are phenomenal at reading XML. However, a massive execution plan can easily exceed 20,000 lines of XML, blowing out the AI's context window. We must learn to extract just the specific <RelOp> (Relational Operator) or <Warnings> nodes.
┌─────────────────────────────────────────────────────────────┐
│ THE XML PLAN EXTRACTION WORKFLOW │
│ │
│ ┌──────────────────┐ ┌───────────────────────────────┐ │
│ │ SQL Server Engine│───▶│ Actual Execution Plan (XML) │ │
│ └──────────────────┘ └──────────────┬────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────▼────────────────┐ │
│ │ YOU (The DBA): Locate the expensive node │ │
│ │ <RelOp NodeId="3" PhysicalOp="Hash Match" ...> │ │
│ │ ... [Extract this 50-line fragment] ... │ │
│ │ </RelOp> │ │
│ └──────────────────────────────────────┬────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────▼────────────────┐ │
│ │ Copilot Chat Context Window │ │
│ │ "Explain why the optimizer chose this Hash Match..." │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Field Note: I once watched a mid-level DBA paste a 15MB execution plan XML into a web-based LLM. The browser crashed instantly. When he finally got a smaller chunk to load, he asked the AI "Why is this slow?" The AI gave a generic answer about indexing. We then grabbed just the
<Warnings>node which contained<SpillToTempDb>. We fed only that node to Copilot and asked, "Why did this spill?" Copilot instantly pointed out that outdated statistics caused a massive memory grant underestimation. Precision prompting requires precision context.
We are using Copilot Chat today as an automated performance diagnostic assistant.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Fragment RAG | Paste <RelOp>...</RelOp>
|
Isolating a specific physical operation (like a Sort or Key Lookup) for AI analysis. |
| Join Diagnostics | "Why did this use a Hash Match?" |
Having the AI parse the EstimateRows and ActualRows attributes to explain join selection. |
| Warning Analysis | "Analyze this <Warnings> node." |
Demystifying complex implicit conversions or TempDB spill warnings buried in the plan. |
Execution-Plan-Workspace/
├── 01_Query_Setup.sql <-- Data generation script
├── 02_Problem_Query.sql <-- The query causing the issue
└── 03_XML_Fragment.xml <-- The extracted node for Copilot
Let's force SQL Server to make a heavy-handed decision. We will join two large, unindexed tables. SQL Server will be forced to use a Hash Match. We will extract the XML and ask Copilot to explain the optimizer's math.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Extract a problematic XML node from an Execution Plan and use Copilot to diagnose the physical join operator. |
| Target Instance | Local Developer Edition or Azure SQL |
| Duration | 90 Minutes |
| Deliverables | An AI-generated explanation of the Hash Match operator and a suggested indexing fix. |
Execute this script to create two tables with 50,000 rows each. Notice we are intentionally omitting foreign keys and indexes.
CREATE TABLE dbo.Customers_Heavy (
CustomerID INT, -- No PK!
CustomerName VARCHAR(100),
RegionCode CHAR(2)
);
CREATE TABLE dbo.Orders_Heavy (
OrderID INT,
CustomerID INT, -- No index!
OrderTotal DECIMAL(10,2)
);
GO
-- Insert 50,000 rows into each
WITH CTE AS (SELECT TOP 50000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n FROM sys.all_objects a CROSS JOIN sys.all_objects b)
INSERT INTO dbo.Customers_Heavy SELECT n, 'Customer ' + CAST(n AS VARCHAR), 'US' FROM CTE;
WITH CTE AS (SELECT TOP 50000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n FROM sys.all_objects a CROSS JOIN sys.all_objects b)
INSERT INTO dbo.Orders_Heavy SELECT n, (n % 50000) + 1, n * 1.25 FROM CTE;
GO
Open a new query window. Ensure "Include Actual Execution Plan" is enabled (Ctrl+M in SSMS, or the toggle button in ADS). Execute this query:
SELECT c.CustomerName, SUM(o.OrderTotal)
FROM dbo.Customers_Heavy c
INNER JOIN dbo.Orders_Heavy o ON c.CustomerID = o.CustomerID
WHERE c.RegionCode = 'US'
GROUP BY c.CustomerName;
-
Look at the graphical execution plan. You will see a large Hash Match operator joining the two tables.
-
Right-click anywhere in the graphical plan and select "Show Execution Plan XML...".
-
Press
Ctrl+Fand search for"Hash Match". -
Locate the opening
<RelOp>tag for that physical operation. Highlight the entire node (from<RelOp...>down to its corresponding</RelOp>). -
Copy this XML fragment.
🔍 Pause & Inspect Checkpoint: Look at the XML you just copied. Can you spot the
EstimateRowsandActualRowsattributes? Look for theMemoryFractionsorHashKeysnodes. This is the math the optimizer uses to build the graphical picture!
Open Copilot Chat. Paste your XML fragment (or reference it if you saved it to 03_XML_Fragment.xml), and add this prompt above it:
"Acting as a Principal SQL Server Database Architect, review the following Execution Plan XML node. Explain why the SQL Server optimizer chose a Hash Match Join over a Nested Loop Join or Merge Join in this specific scenario. Base your answer on the cardinality estimates and lack of ordered data shown in the XML. Finally, provide the exact T-SQL DDL to fix this so the optimizer can choose a more efficient join."
Copilot should explain that without indexes, both tables are unordered heaps. Because the row counts are large (50,000), a Nested Loop would be disastrous (50k * 50k iterations). A Hash Match builds a hash table in memory to probe the matches, which is the best choice for large, unordered sets.
The AI should then recommend creating Clustered Indexes or Non-Clustered Indexes on CustomerID for both tables to enable a Merge Join or an efficient Indexed Nested Loop.
⚡ Lab Micro-Challenge: Look back at your XML. Did the AI mention anything about a Missing Index warning? Sometimes the XML contains a
<MissingIndexes>node at the top level of the<QueryPlan>. Find it, paste it into Copilot, and ask it to parse the XML into a deployableCREATE INDEXstatement.
Parsing XML with AI requires a careful touch to avoid context limits.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| AI Context Window Exceeded | You pasted the entire 10MB .sqlplan file into Chat. |
Only extract the specific <RelOp> node or <Warnings> node that corresponds to the expensive operation. |
| AI suggests "Bitmap Join" | Hallucination. AI mixes up Oracle execution plan terminology with SQL Server. | Reply to Copilot: "SQL Server does not use Bitmap Joins in this context. Re-evaluate based on SQL Server 2025 optimizer rules." |
| PII Data Leakage | You pasted the <ParameterList> node containing real user emails or SSNs. |
ALWAYS scrub the <ColumnReference> and <ParameterList> nodes of literal string values before passing to an LLM. |
| XML is malformed in Chat | You missed the closing </RelOp> tag when copying. |
Ensure the XML tree is well-formed before pasting, or the AI will struggle to parse the nested operators. |
Confirm your execution plan analysis skills are sharp:
-
I successfully generated an Actual Execution Plan in SSMS or ADS.
-
I accessed the raw XML representation of the execution plan.
-
I successfully located and extracted a specific
<RelOp>node representing a physical operation. -
I scrubbed the XML fragment of any sensitive parameters (if applicable).
-
I used Copilot to accurately explain the optimizer's choice and suggest an indexing strategy to resolve it.
We have optimized indexes, removed cursors, and analyzed execution plans. But what happens when perfectly good queries start blocking each other?
In Day 11: Wait Statistics & Blocking Analysis, we are going to use AI to analyze output from sys.dm_os_wait_stats and sp_WhoIsActive. You will learn how to feed blocking chains into Copilot to identify lead blockers and suggest isolation level changes (like READ COMMITTED SNAPSHOT).
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Days 1-10, solid understanding of transactions (BEGIN TRAN/COMMIT) and isolation levels. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Demystify SQL Server concurrency issues by extracting Deadlock XML graphs from Extended Events and leveraging AI to instantly translate the locking cycle, identify the victim, and generate resolution scripts.
By the end of this module, you will be able to:
- Articulate the principles of locking hierarchies and lock modes (Shared, Exclusive, Update), and explain how SQL Server selects a deadlock victim based on rollback cost.
- Construct a deterministic deadlock scenario using parallel SSMS sessions and explicit transaction blocks.
-
Extract the
xml_deadlock_reportpayload natively from the SQL Serversystem_healthExtended Event session using T-SQL. - Diagnose the root cause of a locking cycle by feeding the raw Deadlock XML into Copilot Chat for structural analysis.
- Enforce concurrency best practices by evaluating the AI's suggested fixes (e.g., covering indexes, standardizing access order, or isolation level changes).
| Requirement | Details |
|---|---|
| IDE | SSMS v19+ (Required for easy dual-session simulation) or Azure Data Studio |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2012+ (Requires Extended Events support) |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Deadlock XML reports often capture the literal batch text executing at the time of the collision. If a user was executing a query like
UPDATE Users SET PasswordHash = '...' WHERE UserEmail = '...', that PII is embedded in the XML. You must scrub the<inputbuf>node before sending it to Copilot.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Deadlocks are not inherently errors; they are the engine protecting data consistency. However, high deadlock rates in financial systems trigger SLA violations. When applying AI-generated fixes, ensure you document whether the fix alters transaction boundaries (which impacts auditability) or just physical structures (like indexes).
Welcome back, everyone. Today we tackle the scariest error message a developer can receive: Transaction (Process ID X) was deadlocked on lock resources with another process and has been chosen as the deadlock victim.
A deadlock is not a bug in SQL Server. It is the engine doing its job. It is a logical stalemate. Process A holds a lock on Table 1 and needs Table 2. Process B holds a lock on Table 2 and needs Table 1. Neither can move forward.
SQL Server detects this cycle, calculates which transaction is cheaper to roll back (based on log bytes written), kills it (the Victim), and lets the other proceed (the Winner).
┌─────────────────────────────────────────────────────────────┐
│ THE CLASSIC DEADLOCK CYCLE │
│ │
│ [Holds Exclusive Lock] │
│ ┌────────────▶ Resource: Table A ────┐ │
│ │ │ │
│ Process 60 [Waiting for Lock] │
│ (Winner) Process 62 │
│ │ (Victim) │
│ │ │ │
│ [Waiting for Lock] [Holds Exclusive Lock] │
│ └───────────── Resource: Table B ◀───┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Historically, DBAs parsed Trace Flag 1222 output or tried to read the graphical deadlock graph in SSMS, tracing the red "X" to see what happened. But the XML contains the exact locking modes (e.g., U, X, S, IX) and the exact T-SQL batches.
Field Note: I once consulted for a logistics company where developers tried to "fix" deadlocks by plastering
WITH (NOLOCK)on every single query in the application. Sure, the deadlocks stopped, but their inventory reports started showing ghost shipments that had been rolled back. We removed theNOLOCKhints, pulled the Deadlock XMLs, and fed them to an LLM. It turned out they just needed a single non-clustered covering index to prevent an escalating Page Lock from turning into a Table Lock. Never compromise data integrity to fix a deadlock!
The XML deadlock report is dense and intimidating. Copilot excels at reading these graphs and summarizing the conflict in plain English.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Role Prompting | "Act as an escalation DBA..." |
Sets the AI's persona so it gives architectural fixes (access order, indexing) rather than just "rerun the query." |
| Node Analysis | "Analyze this xml_deadlock_report" |
Feeding the specific XML payload extracted from Extended Events. |
| Resolution Focus | "Provide the exact T-SQL to fix..." |
Forcing Copilot to output actionable CREATE INDEX or rewritten BEGIN TRAN blocks. |
Concurrency-Workspace/
├── Data_Setup/
│ └── 01_Deadlock_Tables.sql <-- Table creation
├── Simulation/
│ ├── 02_Session_A.sql <-- The Winner
│ └── 03_Session_B.sql <-- The Victim
└── Triage/
└── 04_Deadlock_Report.xml <-- Extracted XE XML for Copilot
Today, we are going to intentionally break our database. We will open two separate query windows, force a deadlock, extract the evidence from the system health extended event, and let AI tell us how we messed up.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Force a deadlock, extract the XML from the Ring Buffer/File Target, and have Copilot translate it and provide a fix. |
| Target Instance | Local Developer Edition (Do NOT run this in Prod!) |
| Duration | 90 Minutes |
| Deliverables | A clear AI summary of the deadlock cycle and a T-SQL remediation script. |
Execute this in a new query window to set up our tables.
CREATE DATABASE DeadlockLab;
GO
USE DeadlockLab;
GO
CREATE TABLE dbo.Supplier (SupplierID INT PRIMARY KEY, SupplierName VARCHAR(50));
CREATE TABLE dbo.Part (PartID INT PRIMARY KEY, PartName VARCHAR(50));
INSERT INTO dbo.Supplier VALUES (1, 'Acme Corp');
INSERT INTO dbo.Part VALUES (1, 'Widget');
GOYou must use TWO separate Query Windows (Session A and Session B) in SSMS or ADS.
In Session A (Window 1), run this and WAIT:
USE DeadlockLab;
BEGIN TRAN;
UPDATE dbo.Supplier SET SupplierName = 'Acme Corp Updated' WHERE SupplierID = 1;
-- DO NOT COMMIT YET. LEAVE WINDOW OPEN.In Session B (Window 2), run this and WAIT:
USE DeadlockLab;
BEGIN TRAN;
UPDATE dbo.Part SET PartName = 'Widget Updated' WHERE PartID = 1;
-- DO NOT COMMIT YET. LEAVE WINDOW OPEN.Back in Session A (Window 1), run this:
-- This will block, waiting for Session B
UPDATE dbo.Part SET PartName = 'Session A wants this part' WHERE PartID = 1;Back in Session B (Window 2), run this:
-- This completes the cycle. SQL Server will kill one of them.
UPDATE dbo.Supplier SET SupplierName = 'Session B wants this supplier' WHERE SupplierID = 1;🔍 Pause & Inspect Checkpoint: Look at the messages tab in one of your windows. You should see Error 1205: Transaction (Process ID X) was deadlocked... Raise your hand if you successfully triggered the deadlock! Be sure to issue a
ROLLBACKin the surviving window to clear the lock.
Let's pull the report from the default system_health Extended Event session (which captures deadlocks automatically). Run this query:
WITH SystemHealth
AS (
SELECT CAST(target_data as xml) AS TargetData
FROM sys.dm_xe_session_targets st
JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
WHERE name = 'system_health' AND st.target_name = 'ring_buffer'
)
SELECT TOP 1
XEventData.XEvent.query('(data/value/deadlock)[1]') AS DeadlockGraph
FROM SystemHealth
CROSS APPLY TargetData.nodes('//RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(XEvent)
ORDER BY XEventData.XEvent.value('(@timestamp)[1]', 'datetime') DESC;Click the hyperlinked XML in the results grid to open the raw XML. Copy the entire XML string.
Open Copilot Chat (Ctrl+Alt+I). Paste your Deadlock XML fragment, and add this prompt above it:
"Acting as a Principal SQL Server Database Architect, analyze the following xml_deadlock_report. Please explicitly identify: 1) The SPID of the victim process. 2) The SPID of the winning process. 3) The specific resources (tables/indexes) that were involved in the lock cycle. 4) The lock modes requested (e.g., X, U). Finally, explain the root cause (access order violation) and provide the logical fix to prevent this specific deadlock."
Copilot should correctly identify that Process A grabbed Supplier then Part, while Process B grabbed Part then Supplier.
The AI's suggested fix should not be an index in this specific case (since it's a cross-table update cycle), but rather an architectural correction: Transactions must always access objects in the exact same order.
⚡ Lab Micro-Challenge: What happens if a deadlock is caused by a
SELECTblocking anUPDATE? Ask Copilot Chat: "If a deadlock occurs between a reader (Shared lock) and a writer (Exclusive lock), how does turning on READ COMMITTED SNAPSHOT ISOLATION (RCSI) fix the problem?"
Extracting and parsing deadlocks can be tricky. Watch out for these snags:
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Query returns NULL for XML | The system_health session flushed the ring buffer, or XE is disabled. |
Use the file target instead: sys.fn_xe_file_target_read_file('system_health*.xel', null, null, null)
|
| Copilot gives generic advice | The XML was truncated due to length limits when pasting into Chat. | Only paste the core <deadlock> ... </deadlock> nodes, omitting extraneous environment metadata. |
AI suggests WITH (NOLOCK) |
LLMs sometimes suggest "easy" fixes that compromise data integrity. | Reject the suggestion in chat: "I cannot use NOLOCK as it permits dirty reads. Suggest a covering index or isolation level fix instead." |
| Can't trigger the deadlock | Your scripts executed too fast, or you put them all in one window. | You must use two separate physical SPIDs (windows) and pause manually before crossing the updates. |
Confirm your concurrency diagnostic skills are locked in:
- I successfully used multiple sessions and explicit transactions to force a deadlock.
- I extracted the
xml_deadlock_reportusing Extended Events (system_health). - I sanitized the XML's
<inputbuf>node to protect PII before using AI. - I used Copilot to translate the XML into plain English, identifying the Victim and Winner.
- I understand that standardizing object access order is the primary defense against cross-table deadlocks.
We have optimized the queries and resolved the deadlocks. Now it is time to write code that writes code.
In Day 12: AI for Dynamic SQL & Meta-Programming, we will use Copilot to generate robust, injection-safe Dynamic SQL. You will learn how to automate maintenance tasks by querying sys.tables and generating mass ALTER INDEX scripts dynamically, while letting the AI handle the nightmare of escaping single quotes!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-11, solid understanding of temporary tables (#table) vs table variables (@table).
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Equip DBAs to diagnose and remediate instance-wide TempDB bottlenecks (PFS/GAM contention and sort spills) by using AI to analyze complex DMV output and automatically generate memory-optimized mitigation scripts.
By the end of this module, you will be able to:
- Articulate the physical architecture of TempDB allocation pages (PFS, GAM, SGAM) and why rapid temporary object creation causes system-wide latch contention.
-
Construct diagnostic queries against
sys.dm_os_waiting_tasksandsys.dm_db_task_space_usageto capture TempDB resource hogs in real-time. -
Diagnose cryptic wait resource codes (e.g.,
2:1:1,2:1:3) by feeding DMV data into Copilot for instant translation. -
Enforce best practices by prompting AI to refactor disk-bound
#temptables into Memory-Optimized temp tables or inline table variables. -
Validate the reduction in
PAGEIOLATCH_UPandPAGELATCH_EXwaits following the deployment of AI-suggested TempDB optimizations.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SSMS v19+ |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2019+ (Required for Memory-Optimized TempDB metadata features) |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): When using
sys.dm_exec_sql_textto find which queries are hogging TempDB, the raw T-SQL text will be exposed. If a user is performing a massiveORDER BYon customer data causing a TempDB spill, the literal PII values may be in the query text. Always scrubsql_textbefore pasting into Copilot Chat.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): TempDB is a shared instance-level resource. A bad query from an ad-hoc reporting user can crash TempDB, bringing down a SOX-compliant financial application running on the same instance. Resolving TempDB contention is a critical availability control.
Welcome back, everyone. Today we are talking about the public restroom of SQL Server: TempDB. Everyone uses it, no one cleans up after themselves, and there is always a line for the door.
When you create a temporary table (#MyTempTable), SQL Server must allocate pages on disk. It checks the PFS (Page Free Space) page, the GAM (Global Allocation Map), and the SGAM (Shared Global Allocation Map).
If you have 500 concurrent connections all creating and dropping #temp tables thousands of times a second, they all have to update page 2:1:1 (Database 2, File 1, Page 1). This is a physical hotspot on disk.
┌─────────────────────────────────────────────────────────────┐
│ PFS / GAM LATCH CONTENTION (The TempDB Funnel) │
│ │
│ SPID 55 (Create #T) ──┐ │
│ SPID 56 (Create #T) ──┼─▶ [ LATCH WAIT: PAGELATCH_EX ] │
│ SPID 57 (Drop #T) ──┤ File: 2:1:1 (PFS Page) │
│ SPID 58 (Create #T) ──┘ │
│ │
│ Result: The CPUs are idle, but the application is frozen │
│ because everyone is waiting in line to write to one page. │
└─────────────────────────────────────────────────────────────┘
Field Note: I once got a Sev-1 call at 3 AM. The entire production database was unresponsive. CPU was at 2%, disk IO was low, but no queries were completing. We checked
sys.dm_os_waiting_tasksand saw 800 sessions waiting onPAGELATCH_EXon resource2:1:3(the SGAM page). A developer had deployed an ORM update that fired a massive query with a wildly inaccurateORDER BY, causing gigabytes of data to "spill" to TempDB. The allocation bottleneck froze the instance. We killed the SPID and the server instantly recovered. Today, we use AI to identify and fix these before they cause an outage.
DMV output is just raw tabular data. Copilot is excellent at interpreting this data, identifying the offending SPID, and writing the T-SQL to mitigate the architectural flaw.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| DMV Translation | "Analyze this waiting_tasks output." |
Having Copilot decode what 2:1:1 or 2:1:3 means without Googling it. |
| Mitigation Scripting | "Rewrite this to avoid TempDB spills." |
Generating the exact T-SQL to convert standard #temp tables to Memory-Optimized structures. |
| Diagnostic Gen | "Write a DMV query to find TempDB hogs." |
Asking Copilot to write the complex joins between sys.dm_db_task_space_usage and sys.dm_exec_requests. |
TempDB-Tuning-Workspace/
├── Diagnostics/
│ ├── 01_Simulate_Contention.sql <-- The stress test
│ └── 02_Capture_DMVs.sql <-- AI-generated diagnostic queries
└── Mitigation/
└── 03_Memory_Optimized_Fix.sql <-- The architectural fix
Let's generate some pain. We are going to simulate heavy TempDB usage, capture the raw DMV data, feed it to Copilot, and have it generate a modern memory-optimized solution.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Simulate TempDB allocation contention, capture DMV state, and use Copilot to generate a Memory-Optimized table variable rewrite. |
| Target Instance | Local Developer Edition (SQL 2019+) |
| Duration | 90 Minutes |
| Deliverables | Diagnostic DMV script and a refactored T-SQL block using MEMORY_OPTIMIZED = ON. |
Instead of giving you the diagnostic query, let's ask Copilot to write it. Open Copilot Chat (Ctrl+Alt+I) and type:
"Acting as a Senior SQL Server DBA, write a diagnostic T-SQL query that joins
sys.dm_db_task_space_usage,sys.dm_exec_requests, andsys.dm_exec_sql_text. I need to identify which active SPID is currently consuming the most space (internal_objects_alloc_page_count) in TempDB."
Copy the resulting query into a new file named 02_Capture_DMVs.sql.
Open a new query window and paste this code. This simulates a poorly written procedure that uses massive temporary tables in a loop. Do not run it yet.
SET NOCOUNT ON;
DECLARE @i INT = 0;
WHILE @i < 10000
BEGIN
-- Heavy TempDB allocation
CREATE TABLE #TempHog (ID INT, DummyData CHAR(8000));
INSERT INTO #TempHog (ID, DummyData)
SELECT TOP 100 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), 'FILLER'
FROM sys.all_objects;
DROP TABLE #TempHog;
SET @i = @i + 1;
ENDExecute this script. While it is running (it will take a few seconds/minutes depending on your machine), quickly switch to your 02_Capture_DMVs.sql window and execute the AI-generated diagnostic query.
🔍 Pause & Inspect Checkpoint: Look at the results of your diagnostic query.
- Did it capture the SPID running the
WHILEloop?- Look at the
alloc_page_count. You should see thousands of pages being assigned to that session. Raise your hand if you successfully caught the query red-handed!
Highlight the WHILE loop script from Step 2. Open Copilot Chat and prompt:
"This T-SQL code is causing massive PFS contention in TempDB due to high-frequency creation and dropping of disk-bound temporary tables. Rewrite this script. Replace the #TempHog table with a modern SQL Server Memory-Optimized Table Type (assuming SQL Server 2019+) or an inline table variable to entirely bypass physical TempDB allocation."
Copilot will likely suggest creating a User-Defined Table Type with MEMORY_OPTIMIZED = ON, or swapping the #TempHog for a @TempHog table variable.
Paste the AI's rewritten code into a new window and execute it.
🔍 Pause & Inspect Checkpoint: Execute the new script. Notice the speed difference. Run your diagnostic DMV query again. The TempDB
alloc_page_countfor this new SPID should be zero (or drastically lower), because memory-optimized temp objects do not write to the physical TempDB data files!
⚡ Lab Micro-Challenge: SQL Server 2019 introduced a game-changing feature for this exact problem. Ask Copilot Chat: "What is SQL Server 2019 Memory-Optimized TempDB Metadata? Provide the ALTER SERVER CONFIGURATION command to enable it, and explain how it solves PFS contention without rewriting application code."
Dealing with TempDB is dealing with the core of the engine. AI sometimes misses the nuance of instance-level configurations.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| AI suggests adding data files | True, adding TempDB data files (up to the # of logical cores) helps PFS contention. But you can't do this via a single query rewrite. | Prompt: "I cannot change server configuration. Rewrite the T-SQL query itself to avoid TempDB." |
| "Memory Optimized Filegroup not found" | If the AI suggests MEMORY_OPTIMIZED = ON for a table variable, your database must have a memory-optimized filegroup. |
Prompt Copilot to: "Provide the prerequisite DDL to add a memory-optimized filegroup to the current database." |
| Table Variable Spills | AI swaps #table for @table, but table variables don't have column statistics, causing terrible query plans later. |
Prompt: "If the dataset is larger than 100 rows, ensure you include OPTION (RECOMPILE) so the optimizer doesn't guess 1 row for the table variable." |
Check these off before we close out for the day:
- I successfully used Copilot to write a complex DMV join for TempDB analysis.
- I simulated a TempDB allocation bottleneck using a rapid
#temptable loop. - I caught the offending session in real-time using my diagnostic script.
- I used AI to refactor the procedural loop into a Memory-Optimized Table Type or Table Variable.
- I understand the physical difference between a disk-bound temp table and a memory-optimized one.
We have conquered schemas, indexes, deadlocks, and now TempDB. But what if the data itself is the problem?
In Day 13: Data Type Optimization & Page Compression, we will use Copilot to analyze table footprints. We will hunt down bloated NVARCHAR(MAX) columns, unnecessary BIGINTs, and ask AI to calculate the exact storage savings of applying Row and Page Compression. Bring your largest tables!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-12, understanding of execution plans and plan caching.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Master the diagnosis and remediation of Parameter Sniffing by leveraging SQL Server Query Store DMVs and Copilot Chat to analyze performance divergence, evaluate mitigation strategies, and safely refactor volatile stored procedures.
By the end of this module, you will be able to:
- Articulate the mechanical difference between a compiled execution plan and runtime execution, and why SQL Server "sniffs" parameters.
-
Construct diagnostic queries against
sys.query_store_runtime_statsto identify queries suffering from extreme execution variance. - Diagnose parameter sniffing by feeding raw Query Store divergence data and stored procedure definitions into Copilot.
-
Enforce the correct architectural mitigation by having AI compare
OPTION (RECOMPILE),OPTIMIZE FOR UNKNOWN, and Local Variable Masking. - Validate the applied fix by analyzing the stabilization of logical reads and execution duration within Query Store.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SSMS v19+ |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Database (Query Store must be enabled) |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Query Store tracks the exact parameter values passed during execution (unless explicitly configured otherwise). When extracting data from
sys.query_store_planor runtime stats, ensure you do not copy actual user search terms or IDs into the LLM. Replace PII parameter values with generic tokens like@Param1 = 'HighVolumeCategory'.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Remediating parameter sniffing often involves forcing plans via Query Store or altering core stored procedures. For SOX-regulated financial databases, these changes must be traceable. Always use Copilot to generate a commented script explaining why a specific hint or plan-force was applied, linking it back to the incident ticket.
Welcome back, everyone. Grab your coffee, because today we are tackling the ghost in the machine: Parameter Sniffing.
Raise your hand if you have ever heard a developer say: "The stored procedure takes 10 minutes to run in the application, but when I run it in SSMS with the same parameters, it takes 1 second!"
That is parameter sniffing. When a stored procedure is compiled for the very first time, SQL Server looks (sniffs) at the parameters passed to it. It builds an execution plan perfectly tailored to those specific parameters and caches it.
If the first execution is for a customer with 2 records, it caches an Index Seek with a Key Lookup. If the next execution is for a customer with 5 million records, SQL Server blindly reuses that cached plan. The engine attempts 5 million Key Lookups, and your CPUs catch on fire.
┌─────────────────────────────────────────────────────────────┐
│ THE PARAMETER SNIFFING TRAP │
│ │
│ Execution 1: EXEC GetOrders @Cust = 'SmallClient' (5 rows) │
│ └── Optimizer builds Plan A (Index Seek + Nested Loop) │
│ └── PLAN A IS CACHED. │
│ │
│ Execution 2: EXEC GetOrders @Cust = 'BigClient' (5M rows) │
│ └── Optimizer blindly reuses CACHED PLAN A │
│ └── Result: 5,000,000 Nested Loop Iterations. (Outage) │
└─────────────────────────────────────────────────────────────┘
Field Note: I once dealt with a logistics database where a route calculation procedure usually took 20 milliseconds. One morning, it started taking 45 seconds, bringing the warehouse to a standstill. Why? Maintenance ran overnight and cleared the plan cache. The very first person to use the system in the morning ran a bizarre, edge-case query that pulled data for an entire continent. SQL Server cached that massive "Scan Everything" plan, and every normal user after them suffered. Query Store is our time machine to catch these divergences.
Query Store holds the historical runtime statistics of our queries. By feeding this variance data into Copilot alongside the T-SQL, we can bypass hours of manual plan analysis.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Divergence Analysis | Paste DMV output into Chat | "Look at this Query Store output. Why does Plan A have an avg_duration of 10ms and a max_duration of 5000ms?" |
| Mitigation Comparison | "Compare RECOMPILE vs Local Variables" | Asking AI to evaluate the tradeoffs of parameter masking versus compile-time CPU hits. |
| Hint Generation | "Generate Query Store Hint" | Having Copilot write the sp_query_store_set_hints syntax to force a specific behavior. |
Param-Sniffing-Workspace/
├── 01_Data_Skew_Setup.sql <-- The skewed data generator
├── 02_QueryStore_Extract.sql <-- DMV queries for Copilot
└── 03_AI_Mitigation_Options.sql <-- Refactored SPs and Hints
Today, we are going to intentionally build a table with heavily skewed data, create a stored procedure, trigger parameter sniffing, and then use Copilot to solve the riddle.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Simulate parameter sniffing, extract the performance divergence, and evaluate mitigation strategies with AI. |
| Target Instance | Local Developer Edition (SQL 2016+) with Query Store Enabled. |
| Duration | 90 Minutes |
| Deliverables | A detailed AI comparison of fixes and a remediated stored procedure. |
In a new query window, execute this script to build our skewed table and enable Query Store.
ALTER DATABASE CURRENT SET QUERY_STORE = ON (OPERATION_MODE = READ_WRITE);
GO
CREATE TABLE dbo.Transactions_Skewed (
TxID INT IDENTITY(1,1) PRIMARY KEY,
TenantID INT NOT NULL,
Amount DECIMAL(10,2) NOT NULL,
Filler CHAR(100) DEFAULT 'X'
);
GO
CREATE NONCLUSTERED INDEX IX_Tenant ON dbo.Transactions_Skewed(TenantID);
GO
-- Insert 1 "Rare" record (Tenant 1)
INSERT INTO dbo.Transactions_Skewed (TenantID, Amount) VALUES (1, 100.00);
-- Insert 99,999 "Common" records (Tenant 99)
WITH CTE AS (SELECT TOP 99999 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n FROM sys.all_objects a CROSS JOIN sys.all_objects b CROSS JOIN sys.all_objects c)
INSERT INTO dbo.Transactions_Skewed (TenantID, Amount) SELECT 99, 50.00 FROM CTE;
GO
CREATE OR ALTER PROCEDURE dbo.usp_GetTenantTransactions
@TenantID INT
AS
BEGIN
SELECT TxID, TenantID, Amount, Filler
FROM dbo.Transactions_Skewed
WHERE TenantID = @TenantID;
END;
GORun the following block. We clear the cache, run it for the "Rare" tenant (caching a Seek), and then run it for the "Common" tenant (forcing a terrible plan).
-- Clear procedure cache to force a fresh compile
DBCC FREEPROCCACHE;
GO
SET STATISTICS IO ON;
-- Execution 1: Sniffs Tenant 1 (1 row). Caches a perfect Seek + Key Lookup.
EXEC dbo.usp_GetTenantTransactions @TenantID = 1;
-- Execution 2: Uses the cached plan for Tenant 99 (99,999 rows).
-- It will perform 99,999 Key Lookups instead of a simple Clustered Index Scan!
EXEC dbo.usp_GetTenantTransactions @TenantID = 99;
SET STATISTICS IO OFF;🔍 Pause & Inspect Checkpoint: Look at your Messages tab. The first execution had maybe 3-5 logical reads. The second execution likely had over 100,000 logical reads! You have successfully reproduced Parameter Sniffing.
Let's pretend we found this in Query Store. We have a procedure that sometimes reads 3 pages, and sometimes reads 100,000.
Highlight the CREATE OR ALTER PROCEDURE code from Step 1. Open Copilot Chat.
Type the following prompt into Copilot Chat:
"Acting as a Senior Database Performance Tuner, review the T-SQL stored procedure in my #selection. According to Query Store runtime stats, this procedure suffers from severe Parameter Sniffing due to skewed data distribution (TenantID 1 has 1 row, TenantID 99 has 99,000 rows). Compare the architectural tradeoffs of fixing this using: 1) OPTION (RECOMPILE), 2) OPTIMIZE FOR UNKNOWN, and 3) Local Variable Reassignment (Parameter Masking). Recommend the best approach for a high-frequency OLTP environment."
Read the AI's comparison carefully.
- RECOMPILE: Perfect plans every time, but burns CPU compiling the plan on every single execution. Bad for high-frequency OLTP.
- OPTIMIZE FOR UNKNOWN: Uses statistical averages. Good compromise, but might yield a mediocre plan for everyone.
- Local Variables: Hides the parameter from the optimizer at compile time, forcing it to use density vectors (similar to UNKNOWN).
⚡ Lab Micro-Challenge: Copilot likely recommended
OPTIMIZE FOR UNKNOWNorOPTIMIZE FOR (@TenantID = 99)as the safest OLTP bet. Ask Copilot: "Rewrite the stored procedure using the OPTIMIZE FOR UNKNOWN query hint." Deploy the AI's rewritten procedure, clear the cache, and re-run the tests from Step 2. Notice how the execution plan stabilizes into a Scan for both, eliminating the 100,000-read disaster.
Fixing parameter sniffing is an art. Don't let AI use a sledgehammer when a scalpel is needed.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
AI suggests OPTION (RECOMPILE) everywhere |
LLMs know this solves sniffing, but they ignore the CPU compilation tax. | Challenge the AI: "This proc executes 500 times a second. Recompile will cause CPU starvation. Suggest an alternative." |
| Local Variables kill Cardinality Estimates | Masking parameters (DECLARE @LocalID = @ParamID) blinds the optimizer, causing it to guess row counts. |
Prompt AI: "Explain the impact of local variable masking on Cardinality Estimation in SQL Server 2014+." |
| Query Store Plan Forcing Fails | You try to force Plan A, but the schema changed, making the plan invalid. | Ensure your prompt includes: "Check if the forced plan is still valid after the recent index changes." |
Verify your mastery of parameter sniffing:
- I successfully generated a dataset with heavy cardinality skew.
- I demonstrated parameter sniffing by caching an inappropriate execution plan.
- I observed the massive logical read inflation (
STATISTICS IO) caused by the bad plan. - I utilized Copilot to contrast three different parameter sniffing mitigation techniques.
- I successfully applied a Query Hint (
OPTIMIZE FORorRECOMPILE) generated by AI to stabilize the execution.
We have optimized the queries, fixed the deadlocks, and tamed the optimizer. But how do we deploy all this code safely?
In Day 14: Infrastructure as Code (IaC) & Database Migrations, we will use Copilot to bridge the gap between DBAs and DevOps. You will learn how to generate dbatools PowerShell scripts, automate schema deployments, and write YAML pipelines to take our optimized code from Dev, to Staging, and safely into Production.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Days 1-13, familiarity with SQL Server wait statistics. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Empower DBAs to instantly generate complex, multi-layered diagnostic queries against SQL Server's Dynamic Management Views (DMVs) using natural language, enabling rapid triage of CPU, memory, and blocking bottlenecks.
By the end of this module, you will be able to:
-
Articulate the difference between instance-wide aggregate DMVs (
sys.dm_os_wait_stats) and point-in-time session DMVs (sys.dm_exec_requests). -
Construct sophisticated natural language prompts that force Copilot to correctly link relational DMVs using
CROSS APPLYand DMFs (Dynamic Management Functions). - Enforce diagnostic best practices by instructing AI to automatically filter out benign system background processes (SPID < 50) and benign wait types.
- Diagnose AI structural hallucinations, such as attempting to directly join incompatible DMV granularities.
- Validate the generated diagnostic script against a live server to identify active high-CPU sessions and their associated blocking chains.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SSMS v19+ |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2012+ or Azure SQL Database |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): When using DMVs like
sys.dm_exec_sql_textto troubleshoot active queries, the output will contain the literal T-SQL text executed by users. This text often contains raw PII in theWHEREorVALUESclauses. Never copy raw DMV output containing user data into an LLM prompt. We only ask the AI to write the diagnostic query, we do not feed the live user data back to it.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): For incident response in highly regulated environments, diagnostic scripts should be standardized, peer-reviewed, and stored in source control. Today, we will use AI to draft these scripts, which you must then validate and commit to your enterprise repo. Ad-hoc "guessing" during a Sev-1 outage violates availability and change control standards.
Welcome back, everyone. Take your seats. Today, we are learning how to read the vital signs of SQL Server using Dynamic Management Views (DMVs).
DMVs are in-memory views that expose the internal state of the SQL Server engine. They are our primary weapon during a Sev-1 outage. But there is a catch: the data is highly normalized. To get a clear picture of an active query, you have to join a session view, to a request view, to a SQL text function, to an execution plan function.
Memorizing these massive CROSS APPLY queries is tedious. This is exactly where AI shines.
However, we must understand the grain of the data to catch the AI when it makes a mistake.
┌─────────────────────────────────────────────────────────────┐
│ THE DMV HIERARCHY (What Copilot needs to navigate) │
│ │
│ [Who is connected?] │
│ sys.dm_exec_sessions (SPID, Login, Status) │
│ │ │
│ ▼ INNER JOIN │
│ [What are they doing RIGHT NOW?] │
│ sys.dm_exec_requests (CPU_time, Wait_Type, sql_handle) │
│ │ │
│ ▼ CROSS APPLY │
│ [What is the code?] │
│ sys.dm_exec_sql_text(sql_handle) │
│ │ │
│ ▼ CROSS APPLY │
│ [What is the execution plan?] │
│ sys.dm_exec_query_plan(plan_handle) │
└─────────────────────────────────────────────────────────────┘
Field Note: Years ago, a junior DBA was investigating high CPU on our primary trading database. He wrote a quick DMV query, saw a session with massive wait times, and killed it. The problem? He didn't filter out system sessions. He killed the Log Writer thread. The entire database engine immediately shut down to protect data integrity. We were down for 45 minutes during peak trading. Rule #1 of DMVs: Always filter
session_id > 50! Let's make sure our AI knows this rule.
Generating DMV scripts with Copilot requires precise nouns. If you just ask, "Write a query to find slow things," it will write garbage. You must explicitly name the domains you want: "Sessions, Requests, SQL Text, and Wait Types."
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| DMF Invocation | "Extract the sql_text using the handle" |
Forcing Copilot to use CROSS APPLY sys.dm_exec_sql_text instead of just returning the binary handle. |
| System Filtering | "Exclude background processes" |
Ensures the AI adds WHERE session_id > 50. |
| Wait Type Exclusions | "Filter out benign waits like SLEEP_TASK" |
Prevents the diagnostic output from being flooded with idle connections. |
Diagnostics-Workspace/
├── Baselines/
│ └── 01_Index_Usage_Stats.sql <-- AI-generated index audit
└── Active_Troubleshooting/
├── 02_Live_Blocking_Chain.sql <-- Real-time blocking analysis
└── 03_High_CPU_Waits.sql <-- Our Lab 14 script
A massive spike in CPU has just triggered an alert on your monitoring dashboard. You need a script immediately to find out who is burning CPU, what their code is, and if they are blocking anyone else.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Use Copilot Chat to generate a highly complex, multi-layered DMV diagnostic query that correlates CPU usage, wait types, and blocking sessions. |
| Target Instance | Local Developer Edition or Azure SQL |
| Duration | 90 Minutes |
| Deliverables | A deployable, enterprise-grade T-SQL diagnostic script. |
Open Copilot Chat (Ctrl+Alt+I). You are in a rush, so you feed it the exact business requirement. Type this exact prompt:
"Acting as a Senior SQL Server Escalation DBA, write a comprehensive DMV query that correlates active high-CPU sessions with their current wait types. The output MUST show: session_id, full query text, wait type, wait time in ms, total CPU time, and blocking session ID. Ignore sleeping sessions and system sessions (SPID <= 50). Sort by CPU time descending."
Copilot will generate a script. Do not execute it yet! Look closely at the code in the chat window.
🔍 Pause & Inspect Checkpoint:
- Look at the
FROMclause. Did it joinsys.dm_exec_requeststosys.dm_exec_sessions?- Look at how it retrieved the query text. Did it use
CROSS APPLY sys.dm_exec_sql_text(req.sql_handle)?- The Hallucination Test: Did the AI try to join
sys.dm_os_wait_stats? If it did, it failed!dm_os_wait_statsis an instance-wide historical aggregate; you cannot join it directly to a live session ID. The live wait type is found directly insidesys.dm_exec_requests.wait_type.- Raise your hand if your AI hallucinated an invalid join. (If it did, correct it in chat: "Do not join to dm_os_wait_stats. Use the wait_type column inside dm_exec_requests.")
Create a new file called 03_High_CPU_Waits.sql and paste your validated code. It should look somewhat similar to this:
SELECT
r.session_id,
s.login_name,
r.status,
t.text AS full_query_text,
r.wait_type,
r.wait_time,
r.cpu_time,
r.blocking_session_id
FROM sys.dm_exec_requests r
INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.is_user_process = 1 -- Filters out system SPIDs (usually > 50)
AND r.status <> 'sleeping'
ORDER BY r.cpu_time DESC;Execute this against your test instance. Unless you have an active workload running, it might only return your current SPID.
⚡ Lab Micro-Challenge: Let's upgrade this script. When a query is running,
sys.dm_exec_sql_textreturns the entire stored procedure, which might be 2,000 lines long. We only want the exact statement executing right now. Ask Copilot: "Update this script to calculate and extract the exact statement executing using statement_start_offset and statement_end_offset from dm_exec_requests." Watch the complex math it generates!
Generating diagnostic scripts with AI is fast, but it requires deep architectural knowledge to verify.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
AI joins dm_os_wait_stats to dm_exec_requests |
AI confuses historical instance waits with live session waits. | Correct the AI: "Extract wait_type directly from dm_exec_requests, do not join to historical wait stats." |
| Output shows irrelevant background tasks | AI forgot to filter system SPIDs. | Prompt: "Ensure the script explicitly filters for is_user_process = 1 or session_id > 50." |
| Missing Blocking Context | AI didn't include blocking_session_id. |
Prompt: "Ensure blocking_session_id is selected from dm_exec_requests to identify lead blockers." |
| Result is entirely NULL text | Missing the DMF invocation. | Prompt: "You must use CROSS APPLY sys.dm_exec_sql_text to resolve the sql_handle into plain text." |
Verify your mastery of AI-assisted DMV querying:
- I successfully prompted Copilot to generate a multi-DMV
SELECTstatement. - I verified the AI correctly used
CROSS APPLYforsys.dm_exec_sql_text. - I ensured the script filtered out system background processes (
is_user_process = 1). - I identified whether the AI attempted to incorrectly join aggregate wait stats to live session requests.
- I successfully executed the diagnostic query on a live instance without syntax errors.
Tomorrow is the final day of Phase 2! We are going to tie everything we've learned about performance tuning, deadlocks, and DMVs together.
In Day 15: Concurrency and Isolation Levels, we will use Copilot to analyze our workload and recommend isolation level changes. We will safely refactor applications to use READ COMMITTED SNAPSHOT ISOLATION (RCSI) and learn how to have the AI write the rollback validation scripts.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Phase 2 (Days 8–14), collected IO/CPU metrics from previous labs. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transition from technical execution to executive communication by utilizing AI to aggregate, calculate, and format complex performance baselines into professional, C-suite-ready Markdown reports demonstrating measurable operational ROI.
By the end of this module, you will be able to:
- Articulate the critical importance of establishing deterministic performance baselines (CPU, Duration, Logical Reads) prior to deploying AI-generated code.
- Construct structured prompts that instruct Copilot to ingest raw performance data and calculate percentage improvements accurately.
- Enforce corporate reporting standards by guiding AI to generate executive summaries, technical breakdowns, and markdown tables.
- Diagnose AI mathematical hallucinations, specifically verifying that the LLM correctly calculates reductions rather than inventing data points.
- Validate the overall impact of Phase 2 tuning efforts by producing a comprehensive milestone report suitable for IT change advisory boards (CAB).
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| Workspace | Your saved metrics and scripts from Days 8 through 14 |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Executive performance reports often get emailed widely across the organization. You must ensure that the query examples included in these summaries are strictly structural (DDL/DML schemas) and absolutely stripped of any customer data.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Before any performance fix enters a SOX-compliant production environment, the Change Advisory Board (CAB) requires evidence of the test. An AI-generated performance baseline report satisfies the "Evidence of Testing" control, proving the change is safe and beneficial before deployment.
Welcome to the end of Phase 2, everyone. Take a breath. Over the last week, we have eliminated cursors, bypassed parameter sniffing, fixed SARGability, and diagnosed deadlocks. You have saved your servers millions of CPU cycles.
But here is a harsh reality of database administration: If you do not document the baseline and the improvement, the business assumes the server fixed itself.
Performance tuning without benchmarking is just guessing. When we make a change, we must prove the ROI (Return on Investment). However, writing executive summaries, formatting tables, and calculating percentage decreases in logical reads takes time that DBAs rarely have.
This is where Large Language Models act as your personal Technical Writer.
┌─────────────────────────────────────────────────────────────┐
│ THE BASELINE TO BOARDROOM WORKFLOW │
│ │
│ [Raw DBA Notes] │
│ "Day 8 query: was 250,000 reads. Now 5 reads." │
│ "Day 9 cursor: was 15,000ms. Now 40ms." │
│ │ │
│ ▼ Feed raw metrics into Copilot Chat │
│ │
│ [AI Processing: Math & Formatting] │
│ Copilot calculates: (250000 - 5) / 250000 = 99.99% │
│ │ │
│ ▼ Output │
│ │
│ [Executive Markdown Report] │
│ Beautifully formatted tables, bold ROI statements, │
│ ready for the Change Advisory Board (CAB) Jira ticket. │
└─────────────────────────────────────────────────────────────┘
Field Note: I once spent three days rewriting a horrific, nested cursor used in a billing system. I dropped the execution time from 6 hours to 4 minutes. I quietly deployed it. A week later, the CTO asked why we were paying me if the cloud bill was going down on its own. From that day on, I never deployed a fix without an executive summary showing the "Before" and "After" CPU and IO costs. Today, we will use AI to write those summaries in 30 seconds.
Copilot is excellent at structuring unstructured data. By providing raw, messy notes, we can command the AI to organize it into professional markdown tables and calculate the deltas.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Data Structuring | "Format this raw data into a Markdown table" |
Turning hasty DBA notes into a clean, readable format. |
| Mathematical Deltas | "Calculate the percentage decrease for each metric" |
Forcing the AI to do the math to prove the performance gain. |
| Persona Shifting | "Write an executive summary for a non-technical CTO" |
Translating deep T-SQL tuning concepts into business value (time and compute saved). |
Reporting-Workspace/
├── Raw_Metrics/
│ └── 01_Tuning_Notes.txt <-- Your messy notes from the week
└── Final_Reports/
└── 02_Phase2_Executive_Summary.md <-- The AI-generated masterpiece
Today, we are putting down the T-SQL and picking up the pen. We will take our raw benchmark data from the previous 7 days and use Copilot to generate a stunning Phase 2 tuning report.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Aggregate performance metrics and generate a C-suite ready Markdown report utilizing Copilot. |
| Target Instance | IDE / Copilot Chat |
| Duration | 90 Minutes |
| Deliverables | A polished .md report calculating total logical reads and CPU time saved. |
Create a file named 01_Tuning_Notes.txt and paste the following raw, messy notes. (This represents the data we collected during our SET STATISTICS IO, TIME ON tests).
Day 8 SARGability: Bad query had 154,000 logical reads. Took 4500ms. AI rewrite has 12 logical reads, takes 15ms.
Day 9 Cursor Removal: Ledger update took 12,500ms. Set-based CTE took 120ms.
Day 12 TempDB: Loop allocated 45,000 pages in tempdb. Memory optimized table allocated 0 physical pages.
Day 13 Sniffing: Bad plan did 5,400,000 reads. OPTIMIZE FOR UNKNOWN stabilized it to 850 reads per execution.
Highlight all the text in your notes file. Open Copilot Chat (Ctrl+Alt+I) and type this exact prompt:
*"Act as a Technical Writer for an Enterprise Database Team. Take the raw performance tuning notes in my #selection and generate a professional 'Phase 2 Performance Tuning Milestone Report' in Markdown format.
Include the following sections:
- An Executive Summary explaining the overall stability and compute savings achieved.
- A Markdown table detailing the 'Before' and 'After' metrics for each tuning event, including a calculated column for 'Percentage Improvement'.
- A Technical Conclusion on why Set-Based logic and SARGability are critical for our database standards going forward."*
Look closely at the Markdown generated in the chat window.
🔍 Pause & Inspect Checkpoint:
- Did the AI format the table correctly?
- Check the math. AI models are notoriously bad at arithmetic. Did it calculate the SARGability read reduction correctly?
(154,000 - 12) / 154,000 = ~99.99%.- Raise your hand if your AI hallucinated a wrong percentage. If it did, correct it in chat: "Recalculate the percentage improvement for Day 13. Ensure the math is exact."
Click the "Insert into New File" button (or copy/paste) to move the generated Markdown into a new file named 02_Phase2_Executive_Summary.md.
Use your IDE's Markdown preview feature (Ctrl+Shift+V in VS Code/ADS) to view the rendered report.
⚡ Lab Micro-Challenge: Management loves financial numbers. In the Copilot Chat thread, add this prompt: "Assume our Azure SQL Database costs $0.05 per 1,000 logical reads. Add a column to the table estimating the financial savings per 1 million executions of the Day 13 Parameter Sniffing query." Watch how it translates logical performance into actual dollars!
Using AI for reporting is powerful, but it requires diligent proofreading.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| AI Math Hallucinations | LLMs predict text, they don't use calculators. Complex percentages are often guessed. | Always manually spot-check the AI's math, or explicitly tell it the formula to use in the prompt. |
| Overly Technical Jargon | The AI might leave too much DBA slang in the Executive Summary. | Prompt: "Rewrite the Executive Summary to be understood by a non-technical VP of Finance." |
| Markdown Formatting Breaks | Incomplete table pipes ` | ` cause the markdown to render poorly. |
Ensure you have closed out Phase 2 properly:
- I aggregated the raw performance metrics from my tuning labs.
- I successfully prompted Copilot to generate a structured Markdown report.
- I verified that the AI-calculated percentage improvements were mathematically accurate.
- I translated technical tuning efforts (logical reads) into business value (time/compute savings).
- I understand the necessity of establishing a baseline before deploying an AI-generated fix.
Congratulations on completing Phase 2: Performance Tuning & Concurrency. You are now equipped to tune any query that crosses your desk.
Starting tomorrow, we enter Phase 3: Automation, DevOps, and Infrastructure as Code (Days 16–21).
We will step out of T-SQL and into PowerShell. You will learn how to use Copilot to write dbatools automation scripts, build automated index maintenance routines, and generate CI/CD YAML pipelines for zero-downtime database deployments.
Prepare your terminals, class dismissed!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Phase 1 & 2. Basic familiarity with PowerShell and SQL Server Agent. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transition into Phase 3 by utilizing AI to write robust, dynamic, and safe administrative scripts across two vectors: in-engine index maintenance via Dynamic T-SQL, and fleet-wide backup compliance reporting via PowerShell and dbatools.
By the end of this module, you will be able to:
- Articulate the physical mechanics of index fragmentation thresholds (REORGANIZE at 5–30%, REBUILD > 30%) and the importance of page-count guardrails.
- Construct advanced natural language prompts that force Copilot to write complex, injection-safe Dynamic SQL for database maintenance.
- Validate AI-generated procedural maintenance code by using a "Print-Only" execution strategy before committing to live database alterations.
-
Enforce cross-server automation by commanding Copilot to generate PowerShell scripts leveraging the industry-standard
dbatoolsmodule. - Diagnose fleet health by dynamically querying a Central Management Server (CMS) to generate styled HTML compliance reports for backup SLAs.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or Visual Studio Code (v1.85+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ (Enterprise Edition preferred for ONLINE = ON features). A configured CMS is optional but recommended. |
| PowerShell | PowerShell v5.1 or v7+, with the dbatools module installed (Install-Module dbatools). |
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Automated maintenance scripts operate at the metadata level (system catalogs) and do not interact with PII payload data. However, ensure that any HTML backup reports generated do not expose sensitive client database names if those names contain PII (e.g.,
Client_JohnDoe_DB).🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Scheduled administrative tasks (like Index Rebuilds) and Backup SLAs are strictly audited controls. The PowerShell HTML report we generate today serves directly as "Evidence of Operation" for SOC2 auditors proving that daily backups are being verified across the fleet.
Welcome to Phase 3, everyone. You have spent the last two weeks tuning individual queries. Starting today, we scale up. We are moving from managing databases to managing fleets.
We have two primary tools for automation:
- Dynamic T-SQL: Best for tasks isolated within the SQL engine (like index rebuilding).
-
PowerShell (
dbatools): Best for tasks that cross server boundaries, interact with the OS, or require reporting to external files.
When records are inserted, updated, and deleted, the physical pages on disk become scattered. We resolve this using two commands:
- REORGANIZE: Defragments the leaf level of the B-Tree in the background. (Used for 5% to 30% fragmentation).
- REBUILD: Drops and recreates the index entirely. (Used for > 30% fragmentation).
If we ask Copilot to write a script for this, we must give it strict boundaries. Rebuilding a tiny 50-page table is a waste of CPU. Running a massive rebuild at 2:00 PM will cause blocking.
If you are managing 50 SQL Servers, you cannot log into each one to check backup status. The dbatools PowerShell module wraps thousands of lines of complex .NET code into simple cmdlets. By pairing Copilot with dbatools, we can orchestrate massive fleet-wide checks in seconds.
┌─────────────────────────────────────────────────────────────┐
│ THE FLEET REPORTING WORKFLOW (PowerShell) │
│ │
│ [CMS Registration] │
│ Get-DbaCmsRegServer (Fetches 50 server names instantly) │
│ │ │
│ ▼ │
│ [Status Check] │
│ Get-DbaLastBackup (Scans MSDB across all 50 servers) │
│ │ │
│ ▼ Filter: Since < 24 Hours │
│ │
│ [HTML Generation] │
│ ConvertTo-Html | Out-File C:\temp\BackupReport.html │
└─────────────────────────────────────────────────────────────┘
Field Note: I once walked into a shop with 140 SQL Servers. The DBAs spent the first two hours of every single day manually clicking through SSMS to verify backups. I sat down, used an AI assistant to draft a
dbatoolsscript looping through their CMS, and exported a color-coded HTML report. We scheduled it to run at 7:00 AM. I gave that team 10 hours of their week back. Automation is how you elevate from a technician to an architect.
Whether writing Dynamic T-SQL or PowerShell, Copilot removes the friction of syntax so you can focus on the logical rules.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Dynamic SQL Constraints | "Ensure string concatenation uses QUOTENAME" |
Forcing Copilot to generate injection-safe T-SQL maintenance loops. |
| PowerShell Module Forcing | "Write a PowerShell script using dbatools..." |
Directing the AI away from messy SMO objects and towards clean dbatools cmdlets. |
| Reporting Formatting | "Output the result to a styled HTML report" |
Instructing the AI to generate CSS blocks within the PowerShell script. |
Today, our lab has two distinct parts. First, we will generate a self-aware, in-engine index maintenance routine. Second, we will step out to the OS and generate a fleet-wide backup compliance report.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Generate an intelligent T-SQL index script and a PowerShell dbatools backup SLA report. |
| Target Instance | Local Developer Edition (SQL) and local terminal (PowerShell). |
| Duration | 90 Minutes |
| Deliverables | A safe Dynamic T-SQL script and a styled .html backup compliance report. |
-
Open Copilot Chat (
Ctrl+Alt+I) in your IDE. -
Type this exact, highly constrained prompt:
"Write a dynamic T-SQL script using
sys.dm_db_index_physical_statsthat loops through all user tables in the current database to check fragmentation. Apply these rules: skip indexes with under 1000 pages; if fragmentation is between 5-30%, execute ALTER INDEX REORGANIZE; if > 30%, execute ALTER INDEX REBUILD WITH (ONLINE = ON). Only allow execution during off-peak hours (1 AM to 4 AM). Ensure safe exception handling using TRY...CATCH." -
Review the AI's Output:
🔍 Pause & Inspect Checkpoint: Do not hit F5 yet! Look closely at the generated script.
- Did the AI include the
'LIMITED'scan mode parameter insys.dm_db_index_physical_stats? (If not, tell it to fix it, or it will scan the whole disk!). - Did it use
QUOTENAME()to safely concatenate the table and index names? -
The Safety Test: Change the
EXEC sp_executesql @SQLcommand toPRINT @SQL. Run it. Did it print out perfectly formattedALTER INDEXstatements?
- Did the AI include the
Now, we shift to PowerShell. Make sure you have opened a PowerShell terminal in VS Code/ADS.
-
Open Copilot Chat again. We are giving it a completely different domain task. Type:
"Write a PowerShell script using the dbatools module. The script must query a list of SQL Servers from a CMS (Central Management Server) named 'SQLAdmin01'. For each server, check for databases that have NOT had a full backup in the last 24 hours. Output the final result to a styled HTML report saved to C:\temp\MissingBackups.html. Include basic CSS for readability (red for missing backups)."
-
Review the AI's Output:
🔍 Pause & Inspect Checkpoint:
- Did Copilot use
Get-DbaCmsRegServerto fetch the servers? - Did it use
Get-DbaLastBackupto check the SLA? - Did it handle the time logic correctly (e.g.,
Where-Object { $_.LastFullBackup -lt (Get-Date).AddHours(-24) })?
- Did Copilot use
-
Execute the Script: (Note: If you do not have a CMS setup, ask Copilot to modify the script to use a hardcoded array of your local server names, e.g.,
$servers = @('localhost')). Run the PowerShell script. Navigate toC:\temp\and open the HTML file in your browser.⚡ Lab Micro-Challenge: Management wants this report emailed automatically. In Copilot Chat, ask: "Extend this PowerShell script to use Send-MailMessage (or Send-DbaMail) to email the HTML report as the body of an email to [email protected] if any databases are missing backups."
Automation scales your impact, but it also scales your mistakes.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Script hangs indefinitely | Running the index DMV scan without the 'LIMITED' parameter on a massive database. |
Always verify the DMV function parameters: sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'LIMITED'). |
| "Cannot rebuild online" | SQL Standard Edition does not support ONLINE = ON index rebuilds. |
Prompt Copilot: "Check SERVERPROPERTY('EngineEdition') and fall back to offline rebuilds if not Enterprise." |
| "The term 'Get-DbaLastBackup' is not recognized" | The dbatools module is not installed or imported on your machine. |
Run Install-Module dbatools -Scope CurrentUser in an admin PowerShell prompt. |
| PowerShell script blocked | OS Execution Policy prevents running unsigned scripts. | Run Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass before running the .ps1 file. |
Ensure you are ready for advanced automation:
- I successfully prompted Copilot to generate a complex, injection-safe Dynamic T-SQL script.
- I validated that the T-SQL script respected the
page_count > 1000and off-peak time guardrails. - I successfully generated a PowerShell script targeting the
dbatoolsmodule. - I verified that the PowerShell script correctly evaluated the 24-hour backup SLA.
- I generated and viewed a styled HTML compliance report directly from PowerShell.
Today you got a taste of what PowerShell and dbatools can do with AI assistance.
Tomorrow, in Day 17: Mass Deployments and Configuration Drift, we push the boundaries of fleet management. You will learn how to use Copilot to write automation scripts that synchronize sp_configure settings across 100 servers, migrate entire instances (logins, jobs, linked servers) in a few lines of code, and validate configuration baselines.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Phase 1 & 2, Basic PowerShell familiarity, dbatools module installed.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Master fleet-wide SQL Server administration by combining the immense power of the dbatools PowerShell module with GitHub Copilot to rapidly author safe, scalable, and modular automation scripts.
By the end of this module, you will be able to:
- Articulate the difference between single-instance T-SQL automation and multi-instance fleet management using PowerShell and SMO (SQL Management Objects).
-
Construct AI prompts that explicitly force Copilot to use modern
dbatoolscommands instead of deprecatedSQLPSor rawInvoke-Sqlcmdspaghetti code. -
Enforce safety rails in AI-generated scripts by mandating
-WhatIfparameters,Try/Catchblocks, and robust transcript logging. - Diagnose PowerShell execution policy blocks and Copilot hallucinations regarding missing or imaginary dbatools parameters.
- Validate a multi-server migration script (e.g., syncing SQL Agent Jobs or Logins) in a safe sandbox environment.
| Requirement | Details |
|---|---|
| IDE | Visual Studio Code (v1.85+) with the PowerShell extension installed. |
| Subscriptions | GitHub Copilot |
| Modules | PowerShell 5.1 or 7+, dbatools module (Install-Module dbatools) |
| Network | WinRM / Port 1433 access between your workstation and test SQL instances. |
| OS | Windows 10/11 or Windows Server |
🇪🇺 European Compliance Callout (GDPR): When writing scripts that migrate Logins or query user permissions across environments, ensure your AI prompts do not contain real usernames, SIDs, or domain names. Use
CONTOSO\orTESTDOMAIN\as placeholders in your prompts.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Fleet-wide execution scripts are highly dangerous if compromised. We will enforce strict logging (
Start-Transcript) in our AI prompts to ensure every administrative action taken by the PowerShell script is auditable for SOX compliance.
Alright, folks, take your seats. We are shifting gears today. For the past two weeks, we’ve been using a sniper rifle: T-SQL. T-SQL is perfect for deep, surgical performance tuning on a single instance.
But what happens when your CTO walks in and says, "We just acquired a company. I need you to sync 150 SQL Agent Jobs and 300 Logins across 50 instances by Monday"? If you try to do that with T-SQL and linked servers, you'll be working until Christmas.
Enter PowerShell and dbatools.
dbatools is the community-standard PowerShell module for SQL Server DBAs. It abstracts the highly complex SQL Management Objects (SMO) .NET library into hundreds of easy-to-use commands like Copy-DbaLogin or Get-DbaAgentJob.
Here is our new architectural flow for fleet management:
┌─────────────────────────────────────────────────────────────┐
│ YOUR IDE (VS Code) │
│ │
│ ┌──────────────────┐ ┌───────────────────────────────┐ │
│ │ .ps1 Script │───▶│ Copilot Context Window │ │
│ │ (PowerShell) │ │ (Understands dbatools syntax) │ │
│ └──────────────────┘ └──────────────┬────────────────┘ │
│ │ │
└─────────────────────────────────────────┼───────────────────┘
│ HTTPS
▼
┌─────────────────────────────┐
│ GitHub Copilot Backend │
│ (LLM Inference Engine) │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ AI-Generated Automation: │
│ Copy-DbaAgentJob -Source A │
│ -Destination B -WhatIf │
└─────────────────────────────┘
Copilot knows PowerShell very well. But historically, Microsoft pushed the terrible SQLPS module (which heavily used Invoke-Sqlcmd). If you aren't explicit in your prompts, the LLM will hallucinate ancient, clunky ways of managing SQL Server. You must command it to use dbatools.
Field Note: A few years ago, an admin used an LLM to write a script to "restart SQL services on all non-production servers." The AI generated a beautiful
Get-Service | Restart-Serviceloop. The admin didn't realize the AI had misconfigured the AD filter, and it pulled all servers, including the primary AG replica for the billing system. The script lacked a-WhatIfswitch. The outage lasted 45 minutes. Never run an AI-generated loop against a server array without-WhatIfand visual confirmation.
Today, we are moving out of Azure Data Studio and strictly into Visual Studio Code, utilizing the PowerShell extension.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Explicit Module Enforcement | "Using the dbatools module..." |
Forces Copilot to avoid legacy SQLPS or generic WMI calls. |
| Safety Switches | "Include the -WhatIf parameter" |
Simulates the execution of destructive/modifying commands. |
| Error Handling Injection | "Wrap this in a Try/Catch block..." |
Ensures the script doesn't blindly continue if Server #3 out of 50 is offline. |
Let's build a real-world DBA tool. We need a script that synchronizes missing SQL Agent jobs from a primary server to a disaster recovery (DR) server, but we want it fully logged and safely executed.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Generate a robust PowerShell script to synchronize SQL Agent jobs using dbatools. |
| Target Instance | Two local SQL instances (or simulate with one instance acting as both for code generation). |
| Duration | 90 Minutes |
| Deliverables | A parameterized .ps1 script with error handling and transcript logging. |
- Open VS Code.
- Create a new file named
Sync-SqlJobs.ps1. - Look at the bottom right corner of VS Code—ensure the language mode is set to PowerShell, not Plain Text.
Open the Copilot Chat panel. We are going to feed it a highly structured prompt to get enterprise-grade output. Type this exactly:
*"Act as a Senior SQL Server DBA. Write a PowerShell script using the
dbatoolsmodule to synchronize SQL Agent Jobs from a Source server to a Destination server. Requirements:
- Use the
Copy-DbaAgentJobcommand.- Accept
$Sourceand$Destinationas mandatory parameters.- Implement a
Try/Catchblock. If the connection fails, log an error and exit.- Use
Start-Transcriptto log all output toC:\temp\job_sync_log.txt.- Append the
-WhatIfswitch to the copy command for safety."*
Copilot will generate a script block. It should look something like this:
param (
[Parameter(Mandatory=$true)]
[string]$Source,
[Parameter(Mandatory=$true)]
[string]$Destination
)
$TranscriptPath = "C:\temp\job_sync_log.txt"
Start-Transcript -Path $TranscriptPath -Append
try {
Write-Host "Starting synchronization of SQL Agent Jobs from $Source to $Destination..."
# AI-Generated dbatools command
Copy-DbaAgentJob -Source $Source -Destination $Destination -Force -WhatIf
Write-Host "Synchronization simulation complete."
}
catch {
Write-Error "An error occurred during job synchronization: $_"
}
finally {
Stop-Transcript
}🔍 Pause & Inspect Checkpoint:
- Look at the
Copy-DbaAgentJobline. Did Copilot include the-WhatIfswitch as requested?- Did it include the
-Forceswitch? (AI sometimes adds this to overwrite existing jobs. Is that what you want? If not, remove it).- Does the directory
C:\temp\actually exist on your machine? If not, the transcript will fail.
Let's refine it. Tell Copilot Chat:
"Modify the script to ONLY copy jobs where the job name starts with 'DBA_Maint_'."
Copilot will likely introduce Get-DbaAgentJob combined with a Where-Object filter, piping it into Copy-DbaAgentJob.
Once it looks right, save the file. Open a terminal in VS Code and run it against your test instances:
.\Sync-SqlJobs.ps1 -Source "Localhost\SQL2022" -Destination "Localhost\SQLDR"
⚡ Lab Micro-Challenge: Ask Copilot to add an email notification block at the end of the script using
Send-MailMessageordbatools'sSend-DbaMailMessageif thecatchblock is triggered.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
Copy-DbaAgentJob is not recognized... |
dbatools module is not installed or imported. | Run Install-Module dbatools -Scope CurrentUser and Import-Module dbatools. |
| File cannot be loaded because running scripts is disabled. | Windows Execution Policy is set to Restricted. | Run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser. |
Copilot uses Invoke-Sqlcmd instead of dbatools. |
The prompt was too vague. | Remind the LLM explicitly: "Do not use Invoke-Sqlcmd. Use only native dbatools cmdlets." |
| Transcript path not found. | The AI hardcoded a path that doesn't exist on your OS. | Ensure C:\temp exists, or change the script to use $env:TEMP. |
| Script runs but does nothing. | You left -WhatIf on the command! |
Good! That means the safety net worked. Remove -WhatIf only when you are 100% sure of the target. |
- I successfully installed and imported the
dbatoolsmodule in VS Code. - I forced Copilot to generate a PowerShell script utilizing specific
dbatoolscmdlets. - The generated script included a
Try/Catchblock andStart-Transcriptfor audit logging. - I validated the script's intent by running it safely with the
-WhatIfparameter. - I successfully parameterized the script to accept dynamic Source and Destination server names.
Today we moved objects between servers. Tomorrow, we secure the enterprise.
In Day 18: Security Auditing & RBAC Scripting, we will use Copilot and dbatools to write a fleet-wide security auditor. We will query 50 instances simultaneously to find orphaned users, accounts with sysadmin privileges that shouldn't have them, and generate a beautiful HTML compliance report for the security team.
Class dismissed!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 16-17, basic understanding of backup files and PowerShell.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Eliminate "Schrödinger's Backup" by using AI to generate robust, automated PowerShell routines that physically validate backup file integrity (RESTORE VERIFYONLY) and centralize Disaster Recovery (DR) readiness metrics into an auditable SQL table.
By the end of this module, you will be able to:
- Articulate the difference between a successful backup job and a validated Recovery Point Objective (RPO) achievable during a disaster.
-
Construct precise AI prompts to generate PowerShell scripts that dynamically locate the latest
.bakfiles across network shares. -
Enforce data integrity by utilizing
RESTORE HEADERONLYandRESTORE VERIFYONLYto mathematically prove backup viability without requiring a full storage footprint. - Diagnose script failures by safely capturing terminating errors (e.g., corrupt media, torn pages) and logging them gracefully.
- Validate enterprise DR compliance by routing all automated test outcomes into a centralized SQL Server audit table.
| Requirement | Details |
|---|---|
| IDE | Visual Studio Code (v1.85+) with PowerShell extension |
| Subscriptions | GitHub Copilot |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Managed Instance |
| Storage | A local directory or network share to simulate a backup repository |
| OS | Windows 10/11 or Windows Server |
🇪🇺 European Compliance Callout (GDPR): If you expand this script to actually restore databases (rather than just
VERIFYONLY), you must ensure the destination server is authorized to house PII. Restoring a production database containing EU citizen data down to a less-secure Dev or QA environment without masking is a severe GDPR violation.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Auditors no longer accept "the backup job succeeded" as proof of DR readiness. SOC2 Type II and SOX compliance require evidence of restoration testing. The centralized audit table we build today serves directly as your automated compliance ledger.
Welcome back, everyone. Take your seats. Today we tackle the single most important job you have as a DBA: Protecting the data.
There is a famous saying in our industry: "You don't have a backup until you have successfully restored it." Until that moment, your backup is existing in a quantum state—it is both perfectly fine and totally corrupted at the same time. We call this Schrödinger's Backup.
RPO (Recovery Point Objective) is how much data you are allowed to lose. RTO (Recovery Time Objective) is how fast you have to get it back online.
If your nightly backup job reports "Success," but the underlying .bak file was written to a failing SAN disk, your RPO is destroyed. The only way to know is to test it. Doing this manually for hundreds of databases is impossible.
┌─────────────────────────────────────────────────────────────┐
│ AUTOMATED DR VALIDATION PIPELINE │
│ │
│ [PowerShell Automation Host] │
│ 1. Scan \\SAN\Backups\ for latest .bak files │
│ │ │
│ ▼ │
│ [SQL Server Engine] │
│ 2. Issue: RESTORE HEADERONLY FROM DISK = '...' │
│ 3. Issue: RESTORE VERIFYONLY FROM DISK = '...' │
│ │ │
│ ▼ │
│ [Audit Logging] │
│ 4. Write Status (Valid/Corrupt), LSNs, and Time to DB │
└─────────────────────────────────────────────────────────────┘
Field Note: Early in my career, I was managing a massive billing database. The third-party backup tool reported 100% success for six months. One morning, the SAN crashed. We went to restore, and SQL Server threw a fatal error:
The media family on device is incorrectly formed. The backup agent had been truncating the file header for six months, and nobody noticed because nobody tested the restores. I nearly lost my job. Automate yourVERIFYONLYchecks, or your backups are just imaginary safety nets.
When generating disaster recovery scripts, we must prompt Copilot to be extremely defensive. Network shares drop, files get locked by antivirus, and backups get corrupted.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Defensive File Handling | "Ensure the file is not locked before testing" |
Preventing the script from crashing if a backup is currently writing. |
| Try/Catch SQL Logic | "Capture the exact SQL exception message" |
Logging the specific VERIFYONLY error (e.g., checksum failure) instead of a generic PS error. |
| Audit Integration | "Write the result back to table dbo.BackupAudit" |
Creating a permanent, queryable history of DR tests for auditors. |
DR-Automation-Workspace/
├── Schema/
│ └── 01_Create_Audit_Table.sql <-- The compliance ledger
├── Scripts/
│ └── 02_Verify_Backups.ps1 <-- The AI-generated testing engine
└── Mock_Data/
├── ValidBackup.bak
└── CorruptBackup.bak <-- Our sabotage file
Today, we are going to build an automated auditor. We will create a logging table, use Copilot to write a PowerShell script that tests backup files, and then we will intentionally feed it a corrupted file to ensure it alerts us properly.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Automate RESTORE VERIFYONLY checks and log the outcomes to a central SQL table. |
| Target Instance | Local Developer Edition |
| Duration | 90 Minutes |
| Deliverables | A SQL Audit Table and a defensive PowerShell testing script. |
Open Azure Data Studio or SSMS and run this T-SQL to create your audit table. We will use tempdb for the lab, but in reality, this lives in your DBA_Admin database.
USE tempdb;
GO
CREATE TABLE dbo.DR_VerificationAudit (
AuditID INT IDENTITY(1,1) PRIMARY KEY,
DatabaseName VARCHAR(128) NOT NULL,
BackupFile VARCHAR(500) NOT NULL,
CheckDate DATETIME DEFAULT GETDATE(),
IsValid BIT NOT NULL,
ErrorMessage VARCHAR(MAX) NULL
);
GO
-- Create a quick test backup
BACKUP DATABASE model TO DISK = 'C:\temp\Model_Valid.bak' WITH INIT;
GOOpen VS Code, create a new file named Verify-Backups.ps1, and ensure the language mode is set to PowerShell.
Open Copilot Chat (Ctrl+Alt+I) and type this exact prompt:
*"Act as a Senior SQL Server Reliability Engineer. Write a PowerShell script that does the following:
- Finds the newest
.bakfile inC:\temp\.- Connects to
localhostand runsRESTORE VERIFYONLY FROM DISK = '<filename>'.- Uses a
Try/Catchblock to catch any restoration errors.- Regardless of success or failure, runs an
INSERTstatement intotempdb.dbo.DR_VerificationAuditlogging the DatabaseName, BackupFile path, IsValid (1 or 0), and the exact ErrorMessage if it failed. Do not use SMO; use standardInvoke-Sqlcmdfor the SQL execution."*
Look closely at the AI output.
🔍 Pause & Inspect Checkpoint:
- Did Copilot use
Get-ChildItem | Sort-Object LastWriteTime -Descending | Select-Object -First 1to find the newest file?- Did it wrap the
Invoke-Sqlcmdcall forRESTORE VERIFYONLYinside aTry/Catch?- Raise your hand if your AI forgot to escape the file path quotes in the SQL string. (e.g.,
FROM DISK = '$($file.FullName)'). If it messed up the string interpolation, fix it!
First, run the script as-is. It should pick up Model_Valid.bak, test it, and insert a success row into your audit table.
Check the table: SELECT * FROM tempdb.dbo.DR_VerificationAudit;
Now, let's play the villain. We are going to simulate a SAN corruption.
- Open Notepad.
- Type the words:
"This is a totally corrupted fake backup file." - Save the file as
C:\temp\Model_Corrupt.bak. (Because it is newer, the script will pick this one next).
Run your PowerShell script again.
⚡ Lab Micro-Challenge: Query your audit table again. You should see a new row with
IsValid = 0. What does theErrorMessagesay? It should say something like "The media family on device is incorrectly formed." You have successfully automated disaster detection!
Backup files are massive and fragile. Expect these real-world issues:
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
Access Denied on RESTORE |
The SQL Server Service account does not have read permissions to the file share. | The SQL Server Engine, not your PowerShell user, executes the RESTORE. Grant the SQL Service Account read access to the share. |
| Script hangs for hours |
RESTORE VERIFYONLY reads the entire file. For a 5TB database, this takes time. |
Prompt Copilot: "Add logic to run this via SQL Server Agent Jobs asynchronously, rather than making PowerShell wait." |
Invoke-Sqlcmd is not recognized |
The SqlServer module isn't loaded. |
Add Import-Module SqlServer to the top of the script. |
| False Positives on Corrupt Files | VERIFYONLY doesn't catch internal data corruption, just media corruption. | Add WITH CHECKSUM to your primary backup jobs so VERIFYONLY recalculates the page checksums. |
Confirm your DR automation is bulletproof:
- I created a centralized compliance audit table for DR readiness.
- I successfully generated a PowerShell script that finds the most recent
.bakfile. - I verified that the script securely executed
RESTORE VERIFYONLY. - I tested the
Try/Catchlogic by feeding the script a simulated corrupt backup file. - I confirmed the error was gracefully caught and logged to the SQL table instead of crashing the script.
You have mastered index maintenance and backup validation using PowerShell. But how do we monitor the real-time health of AlwaysOn Availability Groups across multiple data centers?
In Day 19: Availability Group Health Monitoring, we will use Copilot to write aggressive, real-time alerting scripts. We will query the AG DMVs to calculate replica synchronization lag in seconds and automatically trigger warnings if the secondary falls too far behind the primary!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Days 1-18, solid understanding of SQL Server security principals, logins, users, and roles. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Leverage Copilot to rapidly audit SQL Server environments for security vulnerabilities, enforce the Principle of Least Privilege (PoLP), and safely generate dynamic remediation scripts that replace elevated access with custom, restricted database roles.
By the end of this module, you will be able to:
-
Articulate the mechanical difference between server-level and database-level permissions, and explain the risks of the widespread
db_owneranti-pattern. -
Construct complex, cross-database T-SQL audit scripts using AI to instantly identify orphan users and accounts with
sysadminorCONTROL SERVERrights. - Diagnose the scope of over-provisioned accounts by analyzing the output of AI-generated security reports.
- Enforce the Principle of Least Privilege by prompting Copilot to generate idempotent remediation scripts (REVOKE and GRANT).
-
Validate the creation of custom database roles (e.g.,
db_executor) generated by AI to replace broad built-in roles securely.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SSMS v19+ |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Database |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Data Access Governance is a core tenant of GDPR. You must be able to prove who has access to PII and why. The audit scripts we generate today can be scheduled to run weekly, serving as automated evidence that broad access (like
db_owner) is continuously monitored and restricted.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): SOX audits specifically target Segregation of Duties (SoD). A developer cannot have
sysadminordb_ownerin production because they could alter financial data without leaving an application-level audit trail. The remediation scripts we build today are your primary tool for passing a SOX ITGC (IT General Controls) audit.
Welcome back, everyone. Today we are talking about security.
Why do application developers always ask for db_owner or sysadmin? Because security is hard, and db_owner makes the "Access Denied" errors go away. But assigning db_owner is like giving someone the master key to the bank vault just because they need to empty the trash. It violates the Principle of Least Privilege (PoLP).
Finding these over-provisioned users is difficult because SQL Server permissions are highly granular and scattered across master and individual user databases. You have to query sys.server_role_members, sys.database_role_members, and sys.server_permissions.
Look at the workflow on the screen behind me. We are going to use AI to build a radar that scans the entire instance, finds the anomalies, and then writes the code to fix them.
┌─────────────────────────────────────────────────────────────┐
│ THE AI SECURITY AUDIT & REMEDIATION CYCLE │
│ │
│ 1. [The AI Radar] │
│ Prompt: "Write a script to find all db_owners..." │
│ │ │
│ ▼ │
│ 2. [The Discovery] │
│ Result: User 'App_Service' has db_owner in 14 databases. │
│ │ │
│ ▼ │
│ 3. [The AI Remediation Generator] │
│ Prompt: "Write a script to REVOKE db_owner and GRANT │
│ EXECUTE, db_datareader, and db_datawriter instead." │
│ │ │
│ ▼ │
│ 4. [Safe Execution] │
│ DBA reviews the REVOKE/GRANT block and executes. │
└─────────────────────────────────────────────────────────────┘
Field Note: I once took over an environment where the previous DBA granted
sysadminto a third-party reporting tool because it "needed to read system views." A week later, that tool was compromised via a zero-day vulnerability. The attackers used the reporting tool's SQL login to runxp_cmdshell, drop ransomware on the underlying OS, and encrypt the backups. If that account had simply been grantedVIEW SERVER STATEinstead ofsysadmin, the attack would have stopped at the database layer.
The LLM only knows relational security theory. It will gleefully write a script to revoke access. You must provide the guardrails so it doesn't accidentally lock out sa or NT AUTHORITY\SYSTEM.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Explicit Exclusions | "Exclude system accounts like sa or ##MS..." |
Preventing the AI from generating scripts that audit or drop native SQL Server services. |
| Role Mapping | "Replace db_owner with a custom db_executor role" |
Directing Copilot to generate the exact DDL to create custom roles and map users. |
| Dynamic SQL Generation | "Loop through all user databases to check..." |
Forcing Copilot to use sp_MSforeachdb or a cursor to audit the entire instance at once. |
Security-Audit-Workspace/
├── Audits/
│ └── 01_Instance_Security_Scan.sql <-- AI-generated discovery script
└── Remediation/
├── 02_Revoke_Overprovisioned.sql <-- AI-generated fix
└── 03_Create_Custom_Roles.sql <-- PoLP role definitions
Today, we are going to act as the security auditor. We will plant a rogue user in our sandbox, use Copilot to build a script to find them, and then use Copilot again to strip their rights and apply a custom role.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Use Copilot to audit instance-wide elevated permissions and generate a PoLP remediation script. |
| Target Instance | Local Developer Edition |
| Duration | 90 Minutes |
| Deliverables | A cross-database audit script and a custom role remediation script. |
Execute this in a new query window to create a fake application login that has far too much power.
USE master;
GO
CREATE LOGIN [RogueAppUser] WITH PASSWORD = 'StrongPassword123!';
-- Oh no, they made it a sysadmin!
ALTER SERVER ROLE sysadmin ADD MEMBER [RogueAppUser];
GO
USE tempdb;
GO
CREATE USER [RogueAppUser] FOR LOGIN [RogueAppUser];
-- And they gave it db_owner!
ALTER ROLE db_owner ADD MEMBER [RogueAppUser];
GOOpen Copilot Chat (Ctrl+Alt+I). We need a script that searches the whole server. Type this exact prompt:
"Acting as an Enterprise SQL Server Security Auditor, write a dynamic T-SQL script that loops through all databases (excluding system databases). The script should return a result set of all database users who have the
db_ownerrole, AND any server logins that have thesysadminorCONTROL SERVERpermission. Exclude built-in system accounts (e.g., 'sa', 'NT AUTHORITY%', '##MS%'). Output only the T-SQL code."
Copilot will likely generate a script using either a cursor looping through sys.databases or the undocumented sp_MSforeachdb.
🔍 Pause & Inspect Checkpoint:
- Did the AI include the exclusions for
saand##MS%?- Did it join
sys.server_role_membersandsys.server_principalscorrectly to find thesysadminaccounts?- Execute the script. Does
RogueAppUsershow up in the results?
Now that we found the vulnerability, we need to fix it safely. We do not want to delete the user; we want to restrict them. In Copilot Chat, type:
*"Based on the previous audit, I need a T-SQL remediation script for the user 'RogueAppUser'. Please generate a script that does the following:
- REVOKES
sysadminfrom 'RogueAppUser' at the server level.- Switches to
tempdband REVOKES thedb_ownerrole from 'RogueAppUser'.- Creates a new custom database role in
tempdbnameddb_executor.- GRANTS EXECUTE, SELECT, INSERT, UPDATE, and DELETE to this new
db_executorrole.- Adds 'RogueAppUser' to this new custom role and the
db_datareaderanddb_datawriterroles."*
Look at the AI's output. It should contain ALTER SERVER ROLE sysadmin DROP MEMBER [RogueAppUser]; followed by the database-level role creation and mapping.
Copy the script, review it one last time, and hit F5.
⚡ Lab Micro-Challenge: Run your Audit script from Step 2 again.
RogueAppUsershould completely disappear from the results! You have successfully secured the instance. Next, ask Copilot: "How do I query SQL Server to verify what permissions the newdb_executorrole actually has?"
Security scripting is dangerous. A single wrong word can take down an application.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| AI drops the login completely | You used the word "Remove" instead of "Revoke" in your prompt. | Be explicitly precise: "Do not DROP the user. Use ALTER ROLE to REMOVE them from the role." |
| Syntax Error in Dynamic SQL | Copilot sometimes struggles with single-quote escaping inside EXEC sp_executesql. |
Prompt Copilot: "Fix the syntax error. Ensure all single quotes inside the dynamic string are properly escaped." |
| Cannot revoke sysadmin from 'sa' | The audit script didn't filter system accounts, and the DBA blindly ran the remediation. | Always enforce WHERE name NOT IN ('sa') in your AI prompts. |
| Application breaks after remediation | The application actually needed to run TRUNCATE TABLE (which requires schema modification rights). |
Test role changes in Staging. Use SQL Server Profiler / Extended Events to catch Permission Denied errors. |
Confirm your security automation skills:
- I successfully planted a test user with elevated privileges.
- I prompted Copilot to write a cross-database dynamic audit script.
- I verified the script successfully excluded native system accounts.
- I used Copilot to generate a safe
REVOKEandGRANTremediation script. - I understand how to create and map users to a custom
db_executorrole to satisfy PoLP.
You have mastered local instance security. But the world is moving to the cloud.
In Day 20: Cloud Migration & Azure SQL Readiness, we are going to use AI to assess our on-premises databases for cloud compatibility. We will use Copilot to analyze Data Migration Assistant (DMA) reports, identify blocking features (like FileStream or Cross-Database queries), and generate the refactoring code needed to make our databases Azure-ready.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Days 1-19, deep understanding of physical filegroups, constraints, and indexes. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Demystify the complexity of SQL Server table partitioning by leveraging Copilot to scaffold and automate robust "Sliding Window" maintenance routines, achieving instant data archival with zero downtime.
By the end of this module, you will be able to:
- Articulate the metadata-only nature of partition switching, distinguishing between physical data deletion (DELETE operations) and logical metadata pointers.
- Construct foundational partitioning architecture, including Partition Functions (boundaries) and Partition Schemes (filegroup mapping).
-
Diagnose partition alignment failures, identifying when Non-Clustered indexes or mismatched
CHECKconstraints prevent a successful partition switch. -
Enforce data retention policies by using Copilot to generate a dynamic Stored Procedure that automates the
SPLIT,SWITCH, andMERGEsliding window lifecycle. -
Validate the state of partitioned tables by querying catalog views (
sys.partitions,sys.partition_functions) before and after executing the AI-generated routine.
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SSMS v19+ |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ Enterprise Edition (or Standard 2016 SP1+) |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Data Minimization mandates that personal data should not be kept longer than necessary. Automated partition archiving is a primary mechanism for GDPR compliance, allowing you to instantly move aged PII out of active transactional systems and into secured, cold-storage filegroups.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Audit logs (like the ones we are partitioning today) must be retained according to strict corporate policies. When utilizing a sliding window, ensure your AI-generated script explicitly logs the success or failure of the
SWITCHoperation to a central monitoring table so auditors can verify the retention SLA is met.
Welcome back, everyone. Today we are tackling the heavy lifting of Data Lifecycle Management: Table Partitioning.
As tables grow into the billions of rows, executing a simple DELETE FROM AuditLog WHERE CreatedDate < '2020-01-01' becomes impossible. It bloats the transaction log, causes massive blocking, and takes hours.
Partitioning allows us to chop a massive table into logical slices based on a boundary (usually a Date). Because these slices are physically distinct under the hood, we can perform a Metadata Switch. We can swap a partition out of the main table and into an empty archive table in milliseconds, regardless of whether it contains 10 rows or 100 million rows.
To maintain this over time, we use a Sliding Window.
┌─────────────────────────────────────────────────────────────┐
│ THE SLIDING WINDOW LIFECYCLE │
│ │
│ 1. SPLIT (Prepare for next month) │
│ Creates an empty boundary at the "front" of the table. │
│ │
│ 2. SWITCH (Archive the oldest month) │
│ Instantly reassigns metadata of Partition 1 to an │
│ identical, empty staging/archive table. │
│ │
│ 3. MERGE (Clean up) │
│ Removes the now-empty boundary point at the "back", │
│ sliding the whole window forward by one month. │
└─────────────────────────────────────────────────────────────┘
Field Note: I once inherited a 4-Terabyte payment processing table. The nightly cleanup job ran a
DELETEstatement that took 7 hours and routinely caused transaction log full errors, taking down the application. We implemented partitioning. The exact same data cleanup—using aSWITCHto an archive table followed by aTRUNCATE—took exactly 14 milliseconds. The challenge? The syntax forSPLIT,SWITCH, andMERGEis notoriously tedious to write dynamically. Today, we make the AI write it for us.
Copilot is exceptional at managing boilerplate T-SQL. Partition maintenance requires heavily parameterized dynamic SQL to calculate the next boundary date and the oldest boundary date.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Contextual Definition | #file:PartitionSchema.sql |
Providing the exact DDL so Copilot aligns the archive table perfectly. |
| Dynamic Calculation | "Determine the oldest boundary dynamically" |
Forcing the AI to query sys.partition_range_values instead of hardcoding dates. |
| Alignment Constraints | "Ensure indexes are aligned" |
Prompting the AI to remind you if your staging table lacks identical physical structures. |
Partitioning-Workspace/
├── Schema/
│ └── 01_Base_Partition_Setup.sql <-- Foundational DDL
└── Automation/
├── 02_AI_Sliding_Window_Proc.sql <-- The AI-generated maintenance SP
└── 03_Verification_Queries.sql <-- DMVs to prove it worked
Today, we will set up a monthly partitioned audit log. Then, we will challenge Copilot to write the highly complex maintenance stored procedure required to slide the window forward, archiving the oldest month.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Establish a partitioned table and use AI to generate a dynamic Sliding Window stored procedure. |
| Target Instance | Local Developer Edition |
| Duration | 90 Minutes |
| Deliverables | A deployable maintenance SP and partition metadata validation scripts. |
In a new query window, execute this script to build our filegroups, function, scheme, and tables.
USE master;
GO
CREATE DATABASE PartitionLab;
GO
USE PartitionLab;
GO
-- 1. Create Partition Function (Monthly Boundaries)
CREATE PARTITION FUNCTION pf_MonthlyRange (DATETIME2)
AS RANGE RIGHT FOR VALUES ('2026-01-01', '2026-02-01', '2026-03-01');
-- 2. Create Partition Scheme
CREATE PARTITION SCHEME ps_MonthlyScheme
AS PARTITION pf_MonthlyRange ALL TO ([PRIMARY]);
-- 3. Create the Main Table
CREATE TABLE dbo.AuditLog (
AuditID BIGINT IDENTITY(1,1),
LogDate DATETIME2 NOT NULL,
LogMessage VARCHAR(255)
) ON ps_MonthlyScheme(LogDate);
GO
CREATE CLUSTERED INDEX CIX_AuditLog ON dbo.AuditLog(LogDate);
GO
-- 4. Create the empty Archive Staging Table (Must match exactly)
CREATE TABLE dbo.AuditLog_Archive (
AuditID BIGINT IDENTITY(1,1),
LogDate DATETIME2 NOT NULL,
LogMessage VARCHAR(255)
) ON [PRIMARY];
GO
CREATE CLUSTERED INDEX CIX_AuditLog_Archive ON dbo.AuditLog_Archive(LogDate);
GO
-- Insert some dummy data into the oldest partition (Jan 2026)
INSERT INTO dbo.AuditLog (LogDate, LogMessage) VALUES ('2026-01-15', 'Old Data');
GOCreate a file named 01_Base_Partition_Setup.sql and paste the code from Step 1 so Copilot can read it.
Open Copilot Chat (Ctrl+Alt+I) and type this exact prompt:
"Act as a Principal SQL Server DBA. Review the partitioning architecture in #file:01_Base_Partition_Setup.sql. I need to automate the archiving of old data. Write a dynamic T-SQL stored procedure named
dbo.usp_MaintainAuditPartitionsthat performs a Sliding Window operation: 1. Querysys.partition_range_valuesto find the oldest boundary date. 2.SWITCHthe oldest partition fromdbo.AuditLogintodbo.AuditLog_Archive. 3.MERGEthe old boundary point to clean up the partition function. 4. UseTRY...CATCHfor safe execution. Output ONLY the T-SQL code."
Review the code Copilot generated. Partitioning metadata is complex.
🔍 Pause & Inspect Checkpoint:
- Did the AI query
sys.partition_range_valuesjoined tosys.partition_functionsto grab the oldest boundary value into a variable?- Did it generate the
ALTER TABLE dbo.AuditLog SWITCH PARTITION 1 TO dbo.AuditLog_Archivesyntax?- Did it use
ALTER PARTITION FUNCTION pf_MonthlyRange() MERGE RANGE (@OldestBoundary)?- Raise your hand if your AI output included dynamic SQL (
sp_executesql). (Because DDL often requires dynamic strings for variables, this is expected and correct!)
Paste and execute the AI-generated CREATE PROCEDURE script to compile it.
Before we run the new procedure, let's look at the metadata. Run this query:
SELECT
p.partition_number,
p.rows,
v.value AS BoundaryValue
FROM sys.partitions p
LEFT JOIN sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id
LEFT JOIN sys.partition_schemes ps ON i.data_space_id = ps.data_space_id
LEFT JOIN sys.partition_functions f ON ps.function_id = f.function_id
LEFT JOIN sys.partition_range_values v ON f.function_id = v.function_id AND p.partition_number = v.boundary_id
WHERE p.object_id = OBJECT_ID('dbo.AuditLog') AND i.index_id IN (0,1);Note that Partition 2 (January) contains our 1 row of data.
Now, Execute the AI procedure:
EXEC dbo.usp_MaintainAuditPartitions;Run the validation query again. Partition 2 should now be empty (0 rows), and the boundary for 2026-01-01 has been merged away!
Check your archive table: SELECT * FROM dbo.AuditLog_Archive; — The data is there, moved in milliseconds.
Partition switching is incredibly strict. If one byte is out of alignment, it fails.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| "ALTER TABLE SWITCH statement failed..." | The source and destination tables are not structurally identical. | Ensure columns, nullability, data types, and clustered/non-clustered indexes match exactly. |
| "Destination table must be empty." | You ran the sliding window twice without clearing the archive table. | Prompt Copilot: "Add a check to TRUNCATE TABLE dbo.AuditLog_Archive at the start of the procedure if it contains rows." |
| Foreign Key / Check Constraint mismatch | Partitioned tables have specific boundary logic. The staging table lacks the matching CHECK constraint. | Before switching, you must create a CHECK constraint on the Archive table matching the boundary you are switching in. |
| "Partition function can only be altered if no partition scheme..." | The NEXT USED filegroup is not set. | To SPLIT a new boundary, you must first issue ALTER PARTITION SCHEME [Name] NEXT USED [Filegroup]. |
Confirm your advanced architecture skills:
- I successfully created a Partition Function and Scheme.
- I created an aligned Archive staging table.
- I used Copilot to generate a dynamic Sliding Window stored procedure.
- I executed the
SWITCHandMERGEoperations seamlessly without physical data movement delays. - I verified the metadata shift using
sys.partitionsandsys.partition_range_values.
We've mastered in-engine automation and data archiving. Now, it's time to bridge the gap between Dev and Ops.
In Day 21: CI/CD Pipeline Generation & Source Control, we will leverage Copilot to generate YAML deployment pipelines for GitHub Actions and Azure DevOps. You will learn how to take our carefully crafted T-SQL schemas and automate their deployment across Dev, Staging, and Production environments safely!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc. Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist Audience: Experienced SQL Server DBAs (US & Europe) Prerequisites: Completion of Days 1–20, fundamental understanding of High Availability (HA) and Disaster Recovery (DR) architectures. Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Master the real-time operational health monitoring of SQL Server Always On Availability Groups by utilizing AI to write sophisticated PowerShell and DMV-driven alerting scripts that track synchronization lag and queue bloat before they turn into RPO breaches.
By the end of this module, you will be able to:
- Articulate the fundamental trade-offs between Synchronous and Asynchronous commit modes regarding transaction latency and Recovery Point Objective (RPO).
-
Construct precise DMV diagnostic queries against
sys.dm_hadr_database_replica_statesto isolate lagging secondary replicas. - Enforce proactive infrastructure monitoring by prompting Copilot to build automated PowerShell scripts that calculate sync lag in seconds.
- Diagnose performance roadblocks in AG architectures, specifically distinguishing between network-bound Log Send Queues and CPU/disk-bound Redo Queues.
-
Validate alerting routines against simulated Availability Group telemetry to ensure proper threshold breach detection (e.g., Log Send Queue >
$500\text{ MB}$ ).
| Requirement | Details |
|---|---|
| IDE | Visual Studio Code (v1.85+) with PowerShell extension |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ (Standard or Enterprise Edition with Always On enabled, or local simulation) |
| PowerShell | PowerShell 5.1 or 7+, with dbatools or SQL Server modules |
| Network | TCP Port 1433 and Endpoint Port (e.g., 5022) open between replicas |
| OS | Windows Server / Windows 10/11 |
🇪🇺 European Compliance Callout (GDPR): Monitoring AG health status involves querying system metadata (
sys.dm_hadr...), which does not expose individual user payloads or PII. However, ensure that any alerting webhook or email distribution list configured in your PowerShell script complies with corporate data minimization rules.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): High Availability is a foundational availability control under SOC2 Type II. Auditors require proof that secondary replicas are monitored continuously and that RPO SLAs are actively enforced. The automated alerting script we build today satisfies this critical compliance logging requirement.
Welcome back, class. Today we enter the world of mission-critical uptime: Always On Availability Groups (AG).
When you manage production environments in North America or Europe, a single instance failure is unacceptable. We deploy Availability Groups to replicate databases across multiple nodes. But an AG is only as good as its synchronization health.
When a transaction commits on the Primary replica, the transaction log record must be sent across the network to the Secondary replica.
-
Synchronous Commit: The Primary waits for the Secondary to acknowledge that the log has hardened on disk. Guarantees zero data loss (
$RPO = 0$ ), but if the network lags, transaction latency spikes for your users. -
Asynchronous Commit: The Primary fires the log records and commits immediately. High performance, but if the primary dies unexpectedly, you risk data loss (
$RPO > 0$ ).
To monitor this health, we look at the internal engine DMVs—specifically sys.dm_hadr_database_replica_states.
┌─────────────────────────────────────────────────────────────┐
│ ALWAYS ON REPLICA DATA FLOW & BOTTLENECKS │
│ │
│ [Primary Replica] │
│ Transactions written to Log Buffer ──┐ │
│ │ │ │
│ ▼ ▼ │
│ [Log Send Queue] ──(Network)──▶ [Secondary Replica] │
│ (If network is slow, Log received in FIFO queue │
│ queue size grows MBs) │ │
│ ▼ │
│ [Redo Queue] │
│ (If secondary disk/CPU │
│ is slow, redo lags) │
└─────────────────────────────────────────────────────────────┘
-
Log Send Queue Size (
log_send_queue_size): Measured in Kilobytes. Represents how much log data has accumulated on the primary waiting to be sent to the secondary. If this climbs over$500\text{ MB}$ , your network link is saturated or the secondary is unresponsive. -
Redo Queue Size (
redo_queue_size): Measured in Kilobytes. Represents log data received by the secondary that hasn't yet been hardened/replayed into the database files. If this climbs, your secondary node's hardware (disk/CPU) is choking.
Field Note: I once received an emergency alert at 1:00 AM because an asynchronous disaster recovery replica in Frankfurt fell 400 GB behind the primary in Dublin. Why? Someone ran a massive index rebuild on the primary during business hours. The network couldn't push the log fast enough. Because it was async, the primary didn't care—until the local drive on the primary ran out of space because it couldn't truncate the transaction log (since the AG log send queue was holding the VLF pins open)! Monitoring the log send queue is the only way to catch this before storage exhaustion strikes.
Writing multi-replica health checks in raw T-SQL requires querying instance-local DMVs. Writing it in PowerShell allows you to query a central dashboard or poll all AG nodes dynamically.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| DMV Query Generation | "Query sys.dm_hadr_database_replica_states..." |
Forcing Copilot to write precise JOINs against AG cluster metadata. |
| Threshold Calculations | "Calculate sync lag in seconds" |
Translating raw byte sizes into human-readable business impact metrics. |
| Alert Triggering | "If log send queue exceeds 500MB, trigger..." |
Writing conditional execution blocks that fire webhooks or emails. |
HA-Monitoring-Workspace/
├── Scripts/
│ └── Check-AGHealth.ps1 <-- The AI-generated monitoring engine
└── Logs/
└── AG_Alert_History.log <-- Output audit trail
Today, we are going to act as systems engineers. We will use Copilot to write a comprehensive PowerShell script that monitors AG synchronization lag and triggers an automated warning if thresholds are breached.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Build a PowerShell script to monitor AG queues, calculate sync lag, and alert on threshold breaches. |
| Target Instance | Local SQL Server (with or without a live AG; we will include simulation blocks). |
| Duration | 90 Minutes |
| Deliverables | A parameterized .ps1 monitoring script with threshold alerts. |
Open VS Code, create a new file named Check-AGHealth.ps1, and open Copilot Chat (Ctrl+Alt+I). Type this exact prompt:
"Act as an Enterprise SQL Server Automation Engineer. Write a PowerShell script that checks the health of SQL Server Always On Availability Groups. Requirements: 1. Query
sys.dm_hadr_database_replica_statesand related AG DMVs to retrieve database names, replica roles, synchronization state, log send queue size (KB), and redo queue size (KB). 2. Calculate the estimated synchronization lag in seconds. 3. Implement a conditional check: If thelog_send_queue_sizeexceeds 500 MB ($512,000\text{ KB}$), write a critical warning to the console and log it to a local text file. 4. Include robustTry/Catcherror handling in case the instance is not part of an Availability Group."
Examine the script generated by Copilot in your editor window.
🔍 Pause & Inspect Checkpoint:
- Did Copilot use
Invoke-Sqlcmdordbatools(Get-DbaAgReplica) to fetch the metrics?- Look at how it handled the
$500\text{ MB}$ calculation. Did it correctly convert Megabytes to Kilobytes ($500 \times 1024 = 512,000\text{ KB}$ )?- The Simulation Test: If your local sandbox instance doesn't have an active AG configured, the DMV query will return zero rows. Ask Copilot: "Add a mock fallback dataset for testing purposes if no active AG metadata is found on the local instance."
Save your script. Open your PowerShell terminal in VS Code and execute it:
.\Check-AGHealth.ps1 -SqlInstance "localhost"⚡ Lab Micro-Challenge: Let's take this alerting capability to the next level. In Copilot Chat, prompt: "Modify the script so that when the 500 MB threshold is breached, it automatically sends a payload to a Microsoft Teams or Slack webhook URL using
Invoke-RestMethod." See how clean modern notification plumbing is written in PowerShell!
Monitoring high availability structures requires careful handling of cluster states.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| DMV returns zero rows | The local instance is a standalone server, not part of an active AG. | Ensure you test against a multi-node AG cluster or implement the mock fallback dataset suggested in Step 2. |
Invalid object name 'sys.dm_hadr...' |
Always On Availability Groups feature is not enabled on this SQL Server edition/instance. | Enable Always On via SQL Server Configuration Manager or use Enterprise/Standard editions. |
| Queue size reporting negative or wild numbers | Integer overflow in PowerShell when multiplying large byte values. | Ensure queue sizes from DMVs are cast explicitly as [long] (64-bit integers) in PowerShell. |
| False positive alerts during heavy index rebuilds | Temporary large log send queues during maintenance windows are normal. | Build a scheduled maintenance window exclusion window into your monitoring script logic. |
Confirm your high availability monitoring skills are active:
- I understand the core mechanical differences between Synchronous and Asynchronous commit modes.
- I can identify the functional difference between
log_send_queue_sizeandredo_queue_size. - I successfully prompted Copilot to generate a PowerShell script targeting AG health DMVs.
- I verified that the script correctly evaluates the
$500\text{ MB}$ log send queue threshold. - I tested the script's error handling (
Try/Catch) against standalone or simulated instance metadata.
You have mastered fleet-wide PowerShell automation, security auditing, data partitioning, and high-availability health checks.
Tomorrow is our final session in Phase 3: Day 22: CI/CD Pipeline Generation & Database Source Control. We will tie the entire course together by using GitHub Copilot to write automated YAML deployment pipelines for GitHub Actions, turning all our tuning scripts, DDL models, and security policies into a seamless, automated deployment engine.
Rest up, and I will see you tomorrow!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 16–21, strong familiarity with T-SQL automation scripts and stored procedures.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transform manual script execution into fully autonomous enterprise maintenance by using GitHub Copilot to generate programmatic, idempotent T-SQL deployment scripts (sp_add_job, sp_add_jobstep) that codify our Phase 3 automation routines into resilient SQL Server Agent jobs complete with retry logic and failure notifications.
By the end of this module, you will be able to:
-
Articulate the architecture of the
msdbsystem database and explain why programmatic stored procedures (sp_add_job) are superior to manual SSMS GUI creation in enterprise CI/CD pipelines. -
Construct precise AI prompts that generate fully idempotent T-SQL deployment scripts, ensuring repeated executions safely check for existing jobs before creating them.
-
Enforce resilience by embedding advanced job step parameters, such as configurable retry attempts (
$3$ retries), retry intervals, and explicit failure flow routing. -
Diagnose silent automation failures by configuring SQL Server Operators and wiring up automated email notifications on job failure.
-
Validate the compiled SQL Agent job by inspecting its properties, validating step execution orders, and testing failure handling in a sandbox environment.
| Requirement | Database / IDE Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SQL Server Management Studio (SSMS v19+) |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Managed Instance (Agent service must be running) |
| Assets | Completed automation scripts from Days 16 through 21 |
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): When configuring operator email notifications for failed maintenance jobs, ensure that alert emails are routed to a secure internal distribution list (
[email protected]) rather than individual personal mailboxes, satisfying data privacy and internal governance standards.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Automated jobs performing maintenance, index rebuilds, or backup verifications must be documented, version-controlled, and programmatically deployable. Hardcoding jobs through the SSMS GUI violates infrastructure-as-code principles. Using T-SQL deployment scripts stored in Git satisfies SOC2 audit requirements for change control.
Welcome back, class. This is our final administrative session of Phase 3. Over the past week, we have written brilliant PowerShell scripts for fleet backups, security audits, partitioning, and AG health checks.
But a script sitting on your local desktop or a Git repo isn't protecting your database yet. It needs a heartbeat. It needs to run on a schedule, handle transient network hiccups gracefully, and page you if things go wrong. That heartbeat is the SQL Server Agent.
While most DBAs right-click in SSMS and use the Job Wizard to create jobs, enterprise architects do not. If you manage 50 servers, you cannot click through the UI 50 times. You write Idempotent Deployment Scripts using stored procedures inside the msdb system database.
┌─────────────────────────────────────────────────────────────┐
│ THE IDEMPOTENT AGENT DEPLOYMENT PIPELINE │
│ │
│ 1. CHECK: Does Job 'DBA_Weekly_Maintenance' exist in msdb? │
│ ├─ YES ──▶ Drop or Update existing job steps │
│ └─ NO ──▶ Create new via msdb.dbo.sp_add_job │
│ │
│ 2. ATTACH: Bind Script as Step 1 (Retry: 3, Interval: 5m) │
│ │
│ 3. CONFIGURE: Attach Schedule & Operator Notifications │
└─────────────────────────────────────────────────────────────┘
-
msdb.dbo.sp_add_job: Creates the core job shell (name, owner, enabled state, description). -
msdb.dbo.sp_add_jobstep: Attaches executable T-SQL or PowerShell blocks, controlling retry counts and failure actions. -
msdb.dbo.sp_add_jobschedule: Defines when the job runs (daily, weekly, recurrence). -
msdb.dbo.sp_add_jobserver: Binds the job to the local target server instance.
Field Note: Years ago, a brilliant junior DBA spent three days tuning our index maintenance script. He deployed it via the SSMS GUI on our primary production server. Two weeks later, during a major migration, we had to spin up a secondary DR cluster. Guess what was missing? The index maintenance job. Because it wasn't scripted in code, it was left behind. Always codify your infrastructure. If it isn't in code, it doesn't exist.
Writing sp_add_job scripts manually is agonizing. You have to capture return codes, declare @job_id UNIQUEIDENTIFIER variables, and pass massive strings of T-SQL into @command. Copilot handles this boilerplate text effortlessly.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Idempotency Guard | IF EXISTS (SELECT... |
Ensuring the script can be run 100 times without throwing "Job already exists" errors. |
| Retry Configuration | @retry_attempts = 3 |
Forcing the agent to retry transient failures before giving up and failing. |
| Step Chaining | @on_fail_action = 2 |
Directing the job step to quit with failure and trigger alerts if an error occurs. |
Agent-Automation-Workspace/
├── Scripts/
│ └── 01_Index_Maintenance.sql <-- Our Day 16 script payload
└── Deployment/
└── 02_Deploy_Maintenance_Job.sql <-- The AI-generated msdb wrapper
Today, we are taking one of our powerful automation scripts from earlier in the week (such as our index maintenance script from Day 16) and wrapping it into a robust, idempotent T-SQL deployment script using msdb.dbo.sp_add_job.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Generate an idempotent T-SQL deployment script to programmatically create a SQL Agent job with retry logic and failure notifications. |
| Target Instance | Local Developer Edition (msdb database) |
| Duration | 90 Minutes |
| Deliverables | A deployable .sql script that safely creates or updates an enterprise SQL Agent job. |
Imagine our payload is the optimized index maintenance script we wrote on Day 16. For this lab, we will represent it as a placeholder string inside our prompt.
Open Azure Data Studio or SSMS. Open Copilot Chat (Ctrl+Alt+I) and type this exact prompt:
"Acting as an Enterprise SQL Server DevOps Engineer, write an idempotent T-SQL deployment script that creates a SQL Agent job named 'DBA-Automated-Maintenance'. Requirements: 1. Check if the job already exists in
msdb.dbo.sysjobs. If it does, delete it cleanly usingsp_delete_jobso we can perform a clean redeployment. 2. Create the job usingmsdb.dbo.sp_add_jobwith a descriptive description and enabled = 1. 3. Add a job step usingmsdb.dbo.sp_add_jobstepthat executes a sample maintenance command (e.g., a simple PRINT statement representing our index routine). 4. Configure the job step with@retry_attempts = 3and@retry_interval = 5(minutes). 5. Configure failure notifications to email an operator named 'DBA-Team' if the job fails. 6. Add the local server target usingmsdb.dbo.sp_add_jobserver. Output only the executable T-SQL code."
Examine the script generated by Copilot in your chat window.
🔍 Pause & Inspect Checkpoint:
Did Copilot check for the job's existence and include clean-up logic (
sp_delete_job)?Look at the
sp_add_jobstepparameters. Did it correctly pass@retry_attempts = 3and@retry_interval = 5?The Operator Check: If your test instance doesn't have an operator named 'DBA-Team' configured, the script might fail when binding notifications. Ask Copilot: "Add a safe pre-check to create the 'DBA-Team' operator if it does not already exist using
msdb.dbo.sp_add_operator."
Copy the validated T-SQL script into a new query window and execute it against your sandbox instance (F5).
You should see a series of Command(s) completed successfully messages.
-
In SSMS or Azure Data Studio, expand SQL Server Agent -> Jobs.
-
Refresh the folder. You should see DBA-Automated-Maintenance listed!
-
Right-click the job, select Properties, and verify:
- General: Enabled, correct description.
- Steps: Step 1 is present with retry counts configured.
- Notifications: Email notification set to trigger on failure.
⚡ Lab Micro-Challenge: Let's test the execution. Right-click your new job in Object Explorer and select "Start Job at Step...". Watch it run successfully. Next, modify the job step command via T-SQL to intentionally throw an error (e.g.,
RAISERROR('Simulated Failure', 16, 1);), run it again, and check your Job History to see the 3 automatic retries in action!
Programmatic agent deployment requires strict adherence to system stored procedure parameters.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
The job name... already exists. |
The script lacked idempotency logic to check and drop or modify the existing job. | Ensure your prompt explicitly demands an IF EXISTS check and a call to sp_delete_job or sp_update_job. |
The specified @enabled value is invalid |
Incorrect datatype passed to a system procedure parameter (e.g., passing a string instead of a bit/tinyint). | Review the parameter definitions for sp_add_job (e.g., @enabled INT). Let Copilot correct the datatypes. |
| Job fails immediately upon run | The user context running the job step lacks permissions on target objects. | Ensure @database_name parameter in sp_add_jobstep explicitly targets the correct context (e.g., master or your user database). |
| Notifications fail to send | Database Mail is not configured on the SQL Server instance. | Ensure Database Mail (sysmail_help_account_sp) is enabled and configured before attaching email alerts to Agent jobs. |
Confirm your SQL Server Agent automation skills are deployment-ready:
-
I understand the purpose of managing SQL Server Agent jobs programmatically via
msdbsystem procedures. -
I successfully prompted Copilot to generate an idempotent deployment script (
sp_add_job,sp_delete_job). -
I verified that job steps were correctly configured with retry attempts (
$3$ retries) and interval intervals ($5$ minutes). -
I included operator notifications for automated failure alerting.
-
I executed the deployment script and successfully verified the job's presence and configuration in SQL Server Agent.
Congratulations! You have completed Phase 3: Administrative Automation & Scripting, and with it, the core technical curriculum of the AI-Augmented SQL Server DBA training program.
Over these 22 days, you have transformed your workflow:
- Phase 1 taught you how to build secure schemas, indexes, and unit tests using AI.
- Phase 2 gave you mastery over performance tuning, SARGability, execution plans, and deadlock analysis.
- Phase 3 equipped you with enterprise-grade automation, fleet-wide PowerShell scripts, data partitioning, always-on monitoring, and programmatic SQL Agent deployments.
Take everything you have built—your Prompt Bank, your scripts, and your automated deployment models—and apply them to your daily operations. You are now fully equipped to lead the AI-driven modernization of your database infrastructure.
Thank you for your dedication, and happy tuning!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1–22, strong foundational knowledge of T-SQL, automation, and basic AI prompt engineering.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transition from single-prompt AI interactions to Hierarchical and Auditable Multi-Agent Systems (HAMS) by establishing specialized agent personas—separating code creation (Writer Agent) from rigorous safety and performance auditing (Auditor Agent).
By the end of this module, you will be able to:
-
Articulate the inherent risks and limitations of single-prompt AI generation when building complex enterprise T-SQL or PowerShell scripts.
-
Construct specialized system prompts and persona configurations for dedicated operational roles (Writer vs. Auditor).
-
Enforce internal DBA security baselines by routing AI-generated code through a multi-stage validation handoff pipeline.
-
Diagnose subtle architectural anti-patterns (such as RBAR loops, implicit conversions, and unindexed queries) using adversarial persona auditing.
-
Validate production-ready scripts through automated multi-agent peer review before deployment to staging or production repositories.
| Requirement | Details |
|---|---|
| IDE | Visual Studio Code (v1.85+) or Azure Data Studio with GitHub Copilot extension |
| Subscriptions | GitHub Copilot (Business/Enterprise preferred) |
| Workspace | Dedicated VS Code workspace with active .copilotignore file |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Multi-agent workflows often require sharing raw schema snippets or legacy procedural code across agent handoffs. Ensure your
.copilotignorefile is active and that no real consumer PII or unmasked database dumps are pasted into persona system prompts.🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Enterprise control frameworks require separation of duties (SoD)—the developer who writes code cannot be the sole approver. HAMS models this control digitally by forcing an independent "Auditor Agent" to inspect scripts for security and concurrency vulnerabilities prior to human review.
Welcome back, everyone. Take your seats. Today we explore the bleeding edge of AI-augmented systems administration: Hierarchical and Auditable Multi-Agent Systems (HAMS).
Up until now, you have been acting as a single-agent controller. You write a prompt, Copilot generates a script, and you review it. But as DBAs managing high-throughput systems, relying on a single pass creates blind spots. Copilot tries to balance syntax generation, performance optimization, security checks, and error handling all at once—often resulting in subtle regressions.
HAMS solves this by applying the engineering principle of Separation of Concerns to AI personas:
┌─────────────────────────────────────────────────────────────┐
│ THE MULTI-AGENT HAMS WORKFLOW │
│ │
│ [Legacy Code / User Request] │
│ │ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ WRITER AGENT │──┐ │
│ │ (Focused on Modern T-SQL) │ │
│ └────────────────────────┘ │ │
│ │ │
│ ▼ │
│ [Generated Code Artifact] │
│ │ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ AUDITOR AGENT │ │
│ │ (Adversarial Security │ │
│ │ & Performance Review) │ │
│ └───────────┬────────────┘ │
│ │ │
│ ├──▶ [Critical Defect Found] ──▶ Return to Writer│
│ └──▶ [Approved] ──▶ Deploy to Staging│
└─────────────────────────────────────────────────────────────┘
-
The Writer Agent: Tuned for fluency, speed, and modern T-SQL constructs (window functions, set-based operations, CTEs). It operates with high creative latitude.
-
The Auditor Agent: Tuned with adversarial instructions. It reads the Writer's code with extreme skepticism, hunting specifically for cursors, missing transaction blocks, non-SARGable operators, and privilege escalations.
Field Note: In traditional software engineering, you never merge your own pull request without a code review. Why do we treat AI-generated SQL any differently? Establishing a multi-agent review loop prevents 90% of the runtime errors that slip past tired DBAs working late-night shifts.
To build a multi-agent workflow in your IDE, you define clear role constraints using Markdown system prompt headers or distinct chat threads.
| Feature | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Persona Framing | "Act as a Senior T-SQL Developer..." |
Directing the AI to prioritize modern declarative syntax over procedural code. |
| Adversarial Scrutiny | "Act as an adversarial security auditor..." |
Forcing the AI to look exclusively for flaws, risks, and missing error handling. |
| Structured Output | "Provide a Severity Level (Critical/Warning)" |
Standardizing the Auditor's feedback into actionable remediation items. |
Multi-Agent-Workspace/
├── Personas/
│ ├── Writer_Agent_Prompt.md <-- Modernization & DDL rules
│ └── Auditor_Agent_Prompt.md <-- Security & SARGability rules
└── Workflow_Staging/
├── 01_Legacy_Input.sql
├── 02_Writer_Output.sql
└── 03_Auditor_Report.md
Today, we will configure our first dual-agent pipeline in VS Code. We will pass a legacy, inefficient stored procedure through our Writer Agent, and then subject the result to our Auditor Agent.
Lab Overview Table
| Item | Detail |
|---|---|
| Goal | Establish Writer and Auditor agent personas and execute a multi-agent code review cycle. |
| Target Instance | IDE / Copilot Chat workspace |
| Duration | 90 Minutes |
| Deliverables | Configured agent prompt templates and an audited, modernized T-SQL script. |
Create a file in your workspace named Writer_Agent_Prompt.md and populate it with this system instruction:
# Role: Senior T-SQL Developer & Modernization Specialist
**Directive:** Write high-performance, modern T-SQL code using set-based operations, CTEs, window functions (`SUM() OVER()`), and ANSI-standard syntax. Always include explicit schema prefixes (e.g., `dbo.`) and parameterized queries to prevent SQL injection. Bypass all procedural loops (WHILE loops, cursors) unless explicitly requested.
Create a second file named Auditor_Agent_Prompt.md and populate it with this system instruction:
# Role: Principal Database Security & Performance Auditor
**Directive:** Review provided T-SQL scripts with extreme skepticism. Check for:
1. Non-SARGable expressions (scalar functions on indexed columns, implicit conversions).
2. RBAR (Row-By-Agonizing-Row) patterns, cursors, or unindexed joins.
3. Missing explicit transaction management (`BEGIN TRAN`, `COMMIT`, `ROLLBACK`, `XACT_ABORT`).
4. Security vulnerabilities (dynamic SQL without `sp_executesql` parameterization, over-privileged grants).
Output a structured Markdown report detailing severity levels (Critical, Warning, Info) and provide the exact corrected remediation code.
-
The Legacy Input: Create a file named
01_Legacy_Input.sqlcontaining a poorly written query or stored procedure that uses a scalar function in theWHEREclause (WHERE YEAR(OrderDate) = 2026) or a cursor. -
Phase 1 (The Writer): Open Copilot Chat. Reference
#file:Writer_Agent_Prompt.mdand#file:01_Legacy_Input.sql. Prompt Copilot:"Using the persona defined in the prompt file, modernize the legacy code in the input file into high-performance T-SQL." Save the output to
02_Writer_Output.sql. -
Phase 2 (The Auditor): Open a fresh Copilot Chat thread. Reference
#file:Auditor_Agent_Prompt.mdand#file:02_Writer_Output.sql. Prompt Copilot:"Audit the T-SQL script in the output file against our enterprise database security and performance standards. Provide your severity assessment and finalized code."
🔍 Pause & Inspect Checkpoint: Did the Auditor Agent catch any minor performance traps or missing error handling that the Writer Agent glossed over? This separation of duties is the core value of HAMS.
⚡ Lab Micro-Challenge: Ask the Auditor Agent: "Does this script safely handle deadlocks or transaction rollbacks if an exception occurs mid-execution?" Observe how the Auditor suggests adding
SET XACT_ABORT ON;to enforce clean error handling.
Multi-agent setups require strict adherence to context boundaries.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Auditor agrees with everything | The Auditor prompt is too passive and lacks adversarial framing. | Update the Auditor prompt to be explicitly critical: "Assume the provided code contains hidden performance bugs and security flaws until proven otherwise." |
| Context Window Bleed | Passing too many large files into a single chat thread causes the LLM to lose focus. | Keep agent files modular. Clear chat history between the Writer phase and the Auditor phase. |
| Hallucinated Schema Objects | The Writer invents tables or columns not present in your base architecture. | Always provide the base DDL schema file alongside the legacy code prompt. |
Confirm your multi-agent architecture skills are established:
-
I created distinct system prompt files for both the Writer and Auditor agent personas.
-
I successfully executed a modernization pass using the Writer Agent.
-
I subjected the generated code to adversarial review using the Auditor Agent.
-
I analyzed the returned severity report and applied the recommended performance and safety fixes.
-
I understand how separation of duties in AI workflows reduces production bugs.
Congratulations! You have completed Day 23, stepping into the advanced paradigm of Multi-Agent Architectures (HAMS).
You now possess a complete, professional, 23-day curriculum spanning foundational AI setup, advanced performance tuning, infrastructure automation, security auditing, and multi-agent governance. Take these workflows, customize your prompt banks, and lead the AI-driven transformation of your database infrastructure!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1–23, foundational understanding of SQL Server security principals, logins, users, and permissions.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Secure AI-assisted database workflows and automated diagnostic pipelines by establishing a strict Least-Privilege Authentication Architecture, ensuring AI tools can inspect server health metadata while remaining mathematically barred from accessing sensitive user tables or PII.
By the end of this module, you will be able to:
-
Articulate the security and compliance risks associated with granting broad or elevated permissions (
sysadmin,db_owner) to AI diagnostic integrations. -
Construct specialized, read-only metadata service accounts leveraging server-level operational permissions (
VIEW SERVER STATE,VIEW ANY DEFINITION). -
Enforce data minimization by explicitly denying
SELECTprivileges on application schemas to prevent accidental PII exfiltration. -
Diagnose security boundary enforcement by testing query execution under restricted AI service principals.
-
Validate production-readiness of AI diagnostic architectures against regulatory frameworks (GDPR, HIPAA, SOC 2).
| Requirement | Details |
|---|---|
| IDE | Azure Data Studio (v1.48+) or SQL Server Management Studio (SSMS v19+) |
| Subscriptions | GitHub Copilot |
| SQL Server Engine | SQL Server 2016+ or Azure SQL Database with a test database containing mock user data |
| Network | Outbound HTTPS to api.github.com
|
| OS | Windows, macOS, or Linux |
🇪🇺 European Compliance Callout (GDPR): Under GDPR Article 32, organizations must implement appropriate technical measures to ensure a level of security appropriate to the risk. Granting AI diagnostic tools direct access to database tables containing PII violates data protection by design. Enforcing metadata-only service accounts satisfies this architectural safeguard.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Auditors evaluate how third-party plugins and AI helpers interact with your data tier. Using a dedicated low-privilege login (
AI_DiagnosticService) provides clear separation of duties and an immutable audit trail, ensuring compliance with strict IT General Controls (ITGC).
Welcome back, everyone. Today we address a critical security frontier: Least-Privilege AI Authentication.
When you use AI assistants to troubleshoot query performance, analyze execution plan XMLs, or inspect DMV wait stats, the AI often suggests running diagnostic queries. If you execute those queries under your own sysadmin credentials or a blanket db_owner service account, you risk exposing confidential tables or allowing an unconstrained tool to ingest raw PII into external caching layers.
To safely leverage AI, we must implement a Metadata-Only Security Model:
┌─────────────────────────────────────────────────────────────┐
│ LEAST-PRIVILEGE AI DIAGNOSTIC ARCHITECTURE │
│ │
│ [AI Diagnostic Assistant / Copilot Workspace] │
│ │ │
│ ▼ │
│ [Service Principal: AI_DiagnosticService] │
│ ├── ALLOWED: VIEW SERVER STATE, VIEW ANY DEFINITION │
│ └── ALLOWED: sys.dm_os_waiting_tasks, sys.dm_exec_... │
│ └── EXPLICIT DENY: SELECT ON SCHEMA::dbo (BLOCKED PII) │
│ │ │
│ ▼ │
│ [SQL Server Enterprise Instance] │
└─────────────────────────────────────────────────────────────┘
* **Separation of Concerns:** Diagnostic routines require access to engine telemetry, not row payloads.
* **Zero-Trust Metadata:** By granting server-level operational visibility without table data rights, we give the AI the scalpel it needs without handing over the keys to the kingdom.
> **Field Note:** Early in the enterprise AI wave, a team connected an automated troubleshooting bot to their primary database using an `sa` connection string so it "wouldn't run into permission errors." Within two weeks, a diagnostic dump accidentally packaged customer email columns into a public debugging log. Never compromise your security perimeter for convenience. Build the guardrails first.
## 🎯 Section 2: Copilot Focus – Least-Privilege Scaffolding
When prompting Copilot to write diagnostic scripts or security setups, you must explicitly demand fine-grained permission assignments rather than broad roles.
| Feature | Syntax / Usage | DBA Practical Use Case |
| ----- | ----- | ----- |
| **Granular Grants** | `"Grant explicit metadata permissions only"` | Directing the AI to avoid `ALTER SERVER ROLE sysadmin` templates. |
| **Explicit Denials** | `"Deny SELECT on user table schemas"` | Forcing security checks that ensure data exfiltration paths are mathematically sealed. |
| **Context Validation** | `"Test execution under restricted login"` | Writing validation scripts using `EXECUTE AS LOGIN` to test boundary enforcement. |
## 🔬 Section 3: LAB 24 – Constructing the Restricted Security Role
In today's lab, we will build a dedicated, low-privilege login for our AI diagnostic workflow, assign it read-only metadata rights, and verify that it can read server health metrics while being completely blocked from reading customer PII tables.
**Lab Overview Table**
| Item | Detail |
| ----- | ----- |
| **Goal** | Create a restricted AI audit login, assign metadata permissions, and test PII exfiltration prevention. |
| **Target Instance** | Local Developer Edition with a test database |
| **Duration** | 90 Minutes |
| **Deliverables** | A verified least-privilege security provisioning and testing script. |
### Step 1: Create the Dedicated Login and User Context
Execute the following T-SQL script in your SSMS management session as a `sysadmin` to establish the dedicated service principal:
```sql
USE master;
GO
-- 1. Create a dedicated SQL login for AI diagnostic tools and audit scripts
CREATE LOGIN [AI_DiagnosticService]
WITH PASSWORD = 'ComplexPassword_ChangeMe_2026!',
CHECK_EXPIRATION = ON,
CHECK_POLICY = ON;
GO
-- 2. Create user in your target user database for metadata scope
USE [EnterpriseDB];
GO
CREATE USER [AI_DiagnosticService] FOR LOGIN [AI_DiagnosticService];
GO
Execute this block to apply the Principle of Least Privilege:
-- Grant server-level operational and definition visibility
GRANT VIEW SERVER STATE TO [AI_DiagnosticService];
GRANT VIEW ANY DEFINITION TO [AI_DiagnosticService];
GO
-- Grant database-level metadata permissions without table SELECT rights
USE [EnterpriseDB];
GO
GRANT VIEW DEFINITION TO [AI_DiagnosticService];
-- Explicitly seal the perimeter against data exfiltration
DENY SELECT ON SCHEMA::dbo TO [AI_DiagnosticService];
GOSwitch your connection context to verify the restrictions in real time:
-- Test 1: Verify DMV diagnostic query execution (Should Succeed)
EXECUTE AS LOGIN = 'AI_DiagnosticService';
SELECT session_id, wait_type, wait_duration_ms
FROM sys.dm_os_waiting_tasks;
REVERT;
GO
-- Test 2: Verify PII / Table Data Exfiltration Prevention (Should Fail)
EXECUTE AS LOGIN = 'AI_DiagnosticService';
SELECT CustomerID, EmailAddress, CreditCardNumber
FROM dbo.Customers;
REVERT;
GO🔍 Pause & Inspect Checkpoint:
- Did Test 1 return telemetry data successfully?
- Did Test 2 throw an explicit
The SELECT permission was denied on the object 'Customers'error?- Raise your hand if your security boundaries are fully operational!
Securing AI service integrations requires vigilance against common permission creep patterns.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Query Store inspection fails | Lack of database state visibility for query store telemetry. | Grant specific database state rights: GRANT VIEW DATABASE STATE TO [AI_DiagnosticService];. |
Copilot suggests db_datareader |
LLMs default to standard read roles when asked to give access to a database. | Correct the prompt: "Do not use db_datareader. We require metadata-only access with explicit DENY SELECT on schemas." |
EXECUTE AS LOGIN fails |
The current user lacks permission to impersonate logins. | Ensure you are executing the test block under a sysadmin account context. |
Confirm your least-privilege AI security architecture is secure:
-
I created a dedicated low-privilege SQL login (
AI_DiagnosticService). -
I assigned explicit server metadata permissions (
VIEW SERVER STATE,VIEW ANY DEFINITION). -
I enforced data minimization by applying an explicit
DENY SELECTon user table schemas. -
I tested and verified that operational DMVs remain queryable while PII table access is blocked.
-
I understand how this architecture protects data compliance under GDPR and SOC 2 frameworks.
Congratulations on completing Day 24: Least-Privilege AI Authentication Architectures.
You have now completed the entire extended curriculum of the AI-Augmented SQL Server DBA training program. You are equipped with enterprise-grade prompt engineering, advanced performance tuning, multi-agent governance, fleet automation, and hardened security models.
Deploy your secure audit roles, enforce your .copilotignore boundaries, and enjoy a faster, safer DBA workflow!
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Working knowledge of Git, GitHub, fundamental CI/CD concepts, and T-SQL DDL/DML.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Equip senior database professionals with the skills to embed AI-driven semantic analysis and static code guardrails directly into CI/CD pipelines, automatically intercepting and blocking destructive T-SQL operations before they reach production.
By the end of this module, you will be able to:
- Construct a GitHub Actions workflow YAML file authored and optimized using GitHub Copilot.
- Enforce strict pre-deployment database guardrails that dynamically scan Pull Request payloads for prohibited DDL commands.
-
Diagnose automated build failures caused by malicious or accidental destructive queries (
DROP,TRUNCATE,ALTER). - Validate AI-generated analysis of T-SQL scripts, recognizing the boundary between semantic LLM evaluation and deterministic Regex checks.
- Articulate the token limitations and context-window risks associated with sending large migration scripts to external AI endpoints during automated builds.
| Requirement | Specification | Notes for DBAs |
|---|---|---|
| IDE | VS Code (v1.85+) or Azure Data Studio (v1.47+) | Must have GitHub Copilot Chat extension installed and active. |
| Source Control | GitHub Account (Free, Pro, or Enterprise) | Required for Pull Requests and GitHub Actions execution. |
| LLM Endpoint | Azure OpenAI or standard OpenAI API Key | Will be stored securely as a GitHub Repository Secret for the runner. |
| Target Engine | SQL Server 2025 / Azure SQL Database | Local Developer edition is fine for testing the rejected scripts. |
| OS / Runner | Ubuntu-latest (GitHub Hosted Runner) | Standard Linux runner environment for our CI/CD pipeline steps. |
🇪🇺 European Compliance Callout (GDPR): If you are deploying this in a European enterprise, ensure your data processor agreements cover the specific LLM endpoint used in your CI/CD pipeline. Do not send
.sqlfiles containing raw dataINSERTstatements with PII to the AI API. Restrict your CI/CD AI scanner strictly to DDL (schema) scripts to maintain your privacy boundary.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): For SOX and SOC2 compliance, the automated rejection of a PR by an AI must be treated as an audit event. Ensure your GitHub Actions logs are retained. We will use repository secrets for API keys; never hardcode enterprise credentials or IP indemnification tokens into the
sql_audit.ymlfile.
Welcome to Day 25, everyone. Grab your coffee and take a seat.
We've all been there. It's 4:30 PM on a Friday. A junior developer submits a "minor hotfix" PR. It gets a rubber-stamp approval, merges into the main branch, and the deployment pipeline kicks off. Ten minutes later, your monitoring dashboard lights up like a Christmas tree because a rogue TRUNCATE TABLE just wiped out your active sessions table.
Historically, we've used static code analysis—Regex checks and tools like SQLFluff—to catch these. But static checks are dumb. A developer can bypass a DROP TABLE regex check with dynamic SQL: EXEC('DR' + 'OP TABLE Users').
This is where AI enters the pipeline. We can use an LLM not just to look for text patterns, but to evaluate the semantic intent of the SQL script during the CI/CD build process.
Let's look at the architecture of what we are building today:
+-------------------+ +-----------------------+ +-------------------------+
| Developer IDE | ----> | GitHub Pull Request | ----> | GitHub Actions Runner |
| (Creates PR with | | (Triggers workflow) | | (Executes sql_audit.yml)|
| destructive SQL) | +-----------------------+ +-----------+-------------+
+-------------------+ |
v
+-------------------------+
| AI Validation Step |
| (Extracts .sql files) |
+-----------+-------------+
|
v
+-------------------+ +-----------------------+ +-------------------------+
| Action FAILS | <---- | Context Window (Diff) | <---- | Azure OpenAI / LLM |
| (PR Blocked!) | | "Does this contain | | (Analyzes semantic |
+-------------------+ | a DROP or TRUNCATE?" | | intent & syntax) |
+-----------------------+ +-------------------------+
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Familiarity with Python/PowerShell scripting, legacy T-SQL constructs (cursors, NOLOCK), and REST API fundamentals.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Empower senior database architects to construct an automated, multi-agent AI pipeline capable of batch-processing, refactoring, and auditing legacy T-SQL schema and stored procedures at scale, while strictly enforcing enterprise compliance and deterministic code safety.
By the end of this module, you will be able to:
- Articulate the architectural differences between single-file IDE Copilot assistance and automated, multi-agent REST API processing for large-scale database migrations.
- Construct a programmatic automation loop (Python/PowerShell) that ingests legacy stored procedures and pipelines them through distinct "Worker" and "Auditor" AI agents.
- Enforce strict enterprise boundary constraints by isolating the migration pipeline from production databases and applying contextual token limits.
- Diagnose hallucinated refactoring outputs where the AI misinterprets legacy business logic (like implicit cursor behaviors or deprecated outer joins).
- Validate the structural consistency and safety of modernized T-SQL using automated programmatic gating and peer review processes.
| Requirement | Specification | Notes for DBAs |
|---|---|---|
| IDE | VS Code (v1.85+) or Azure Data Studio | Required for script authoring and folder manipulation. |
| Subscriptions | Azure OpenAI API or GitHub Copilot API | Active API key required. We will use environment variables, never hardcode keys. |
| SQL Engine | SQL Server 2025 or Azure SQL | Used as the standard syntax target for modernization. |
| Network / Ports | Outbound TCP 443 (HTTPS) | Ensure corporate firewalls allow outbound API calls to api.openai.com or *.openai.azure.com. |
| OS / Runtime | Windows 11 / Linux with Python 3.10+ | We will use Python for the orchestrator script today. |
🇪🇺 European Compliance Callout (GDPR): When batch-processing legacy stored procedures, you must ensure your migration payload contains absolutely no hardcoded PII, test customer records, or production data fragments. Ensure your Data Processing Agreement (DPA) with Microsoft covers the Azure OpenAI endpoints you are hitting. Enable the "No Training on Enterprise Data" toggle for your subscription to maintain a strict privacy boundary.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): If these legacy procedures dictate financial reporting logic (SOX) or touch PHI (HIPAA), automated refactoring carries immense audit weight. Ensure your pipeline scripts output comprehensive execution logs. Store your API keys in Azure Key Vault or local credential managers to ensure IP indemnification and maintain credential containment.
Welcome back, everyone. Take your seats. Yesterday we built CI/CD guardrails to keep bad code out. Today, we are going on the offensive.
Raise your hand if your enterprise has a Utils database full of stored procedures written in 2008 by a developer who thought cursors and NOLOCK hints were the pinnacle of engineering. Keep your hand raised if management just told you to migrate all 500 of those procedures to Azure SQL by the end of Q3.
Doing that manually is a fast track to burnout. Doing that by pasting 500 files one by one into GitHub Copilot Chat will make you lose your mind.
For large-scale migrations, we need to graduate from the IDE to an Automated Multi-Agent Pipeline. We use automation (Python/PowerShell) to loop through our files, pass them to a "Worker Agent" tasked with modernization (e.g., swapping cursors for set-based logic, removing deprecated syntax), and then pass the output to an "Auditor Agent" tasked purely with finding flaws in the Worker's code.
Let’s look at the ASCII architecture of what we are building today:
+---------------------+ +------------------------+ +-------------------------+
| Local Disk | | Python Orchestrator | | LLM Endpoint (Azure/GH) |
| /legacy | | (Batch Processing Loop)| | |
| - proc_01.sql | ===> | [1] Read File | ===> | [Worker Agent Prompt] |
| - proc_02.sql | | | <=== | Modernized T-SQL |
| - proc_03.sql | | [2] Hold in Memory | | |
+---------------------+ | | ===> | [Auditor Agent Prompt] |
| [3] Evaluate Result | <=== | "PASS" or "FAIL+Reason" |
+---------------------+ | | +-------------------------+
| Local Disk | | [4] If PASS, save to: |
| /modernized | <=== | /modernized/ |
| - proc_01_v2.sql | | else, Log Error. |
+---------------------+ +------------------------+
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Familiarity with SQL Server Agent, Extended Events (XE), PowerShell (SqlServer module), and Webhooks.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Equip senior DBAs with the architecture and AI-prompting techniques necessary to design, validate, and deploy secure, event-driven self-healing routines for transient SQL Server failures.
By the end of this session, you will be able to:
- Articulate the event-driven architecture bridging SQL Server Alerts, Extended Events, and automated response scripts.
- Construct precise, context-aware Copilot prompts to generate idempotent, fail-safe PowerShell remediation routines.
- Enforce strict boundary conditions (e.g., disk space limits) within AI-generated scripts to prevent cascading infrastructure failures.
- Diagnose automated response execution paths and troubleshoot permission or execution policy blockers in SQL Server Agent.
- Validate the end-to-end self-healing pipeline using simulated critical errors (e.g., Error 1105) in an isolated sandbox.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) or Azure Data Studio with GitHub Copilot extension installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise preferred). |
| SQL Server Engine | SQL Server 2019 or 2022 (Developer or Enterprise Edition). |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com, plus access to internal Slack/Teams webhook URLs. |
| OS | Windows Server 2022 (for Agent/PowerShell native testing) or Linux (Ubuntu 20.04+) with pwsh. |
🇪🇺 European Compliance Callout (GDPR): Automated remediation scripts often capture context around the query that caused the failure. Ensure your Extended Events and alert payloads are scrubbed of PII (Personally Identifiable Information) before being passed to any external logging mechanism or AI context window. Verify your Copilot telemetry exclusion settings are enforced at the organization level.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Any script that automatically alters database state (like expanding a data file) must be fully audited. SQL Server Agent Jobs executing these AI-generated PowerShell scripts must run under tightly scoped Proxy Accounts, never sysadmin. IP indemnification applies to webhook traffic routing through your enterprise firewall.
Welcome back, everyone. Settle in. Today, we are moving from observability to action.
For twenty years, we've trained ourselves to wake up at 3:00 AM because a database filegroup filled up. You log in, check the LUN, see there's 500GB free, issue an ALTER DATABASE command to add 10GB, and go back to sleep. Why are human beings doing this? A relational database is essentially a complex, stateful factory. If a conveyor belt jams (Error 1105: Filegroup Full), the factory should ideally pause, clear the jam, and notify the floor manager.
But letting AI write your automation requires extreme caution. When dealing with LLMs, we must understand token mechanics and context truncation. If you paste a 5,000-line SQL error log into Copilot and ask, "Write a script to fix this," the LLM might truncate the actual root cause hidden at the bottom of the stack trace. Worse, due to the probabilistic nature of LLMs, it might generate a script that expands your file infinitely without checking underlying disk space.
Here is the deterministic architecture we are building today:
[ SQL Server Engine ] -> Error 1105 Occurs (Data File Full)
|
v
[ SQL Server Alert ] -> WMI / Event Trapped
|
v
[ SQL Server Agent ] -> Triggers Automated Job (Proxy Account)
|
v
[ PowerShell Script ] <== (AI-Generated via IDE & Copilot)
1. Check Free Disk Space
2. Expand File by 10% (Max 5GB)
3. Invoke-RestMethod (Webhook)
|
v
[ Teams / Slack ] -> "Incident Auto-Resolved. No PagerDuty needed."
🎙️ Field Note
Let me tell you about a "resume-generating event" from a client last year. A junior DBA used an LLM to write an auto-expand script fortempdb. It worked beautifully. Unfortunately, the prompt didn't specify a maximum growth boundary. A Cartesian product query from the reporting team hittempdb, the self-healing script fired repeatedly every 60 seconds, and it filled the entire Tier-1 SAN, taking down 40 other production instances. Automation without boundaries is just a faster way to crash your datacenter. Always enforce deterministic limits on AI output.
When drafting remediation scripts, your Copilot context is everything. You cannot just ask for a "fix." You must provide the exact parameters.
| Feature / Marker | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Targeting Context | @workspace |
Ensure Copilot reads your existing SqlServer module connection strings in your repo. |
| Referencing Schemas | #file:DB_Config.json |
Force Copilot to read your environment thresholds (e.g., max file size limits) before writing the script. |
| System Rules | Use strict ErrorActionPreference |
Append this to every PowerShell prompt to ensure the script stops on failure rather than failing silently. |
Before you write the script, ensure your repository looks like this so Copilot has the right context:
📂 dba-automation-repo
┣ 📂 config
┃ ┗ 📜 storage-thresholds.json
┣ 📂 scripts
┃ ┗ 📜 Auto-Expand-DataFile.ps1
┗ 📂 tests
┗ 📜 Test-AutoExpand.ps1
Alright, roll up your sleeves. Open VS Code. Raise your hand if your Azure SQL Edge container isn't running from yesterday.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Automate Error 1105 Remediation | localhost\SQL2022 |
90 Minutes | 1 Setup SQL, 1 PS Script, 1 Webhook Alert |
Run this in SSMS or Azure Data Studio. We are creating a database with a tiny, artificially restricted file to easily trigger Error 1105.
-- Create a tiny database
CREATE DATABASE [SelfHealingDB]
ON PRIMARY (
NAME = N'SelfHealing_Data',
FILENAME = N'/var/opt/mssql/data/SelfHealing_Data.mdf',
SIZE = 5MB,
MAXSIZE = 10MB, -- Artificial cap to force the error
FILEGROWTH = 1MB
);
GO
USE [SelfHealingDB];
CREATE TABLE FillMeUp (ID INT IDENTITY(1,1), Filler CHAR(8000));
GOOpen a new file in VS Code named Auto-Expand-DataFile.ps1. Open GitHub Copilot Chat.
Do not type "write a script to expand a sql file." Use this exact, deterministic prompt:
Prompt:
@workspace Create a PowerShell script to remediate SQL Server Error 1105. It must take parameters for ServerName and DatabaseName. Requirements: 1) Use the SqlServer module. 2) Check the underlying OS disk space first. 3) Only increase the MAXSIZE and SIZE of the primary data file by 10MB IF there is at least 1GB of free disk space. 4) Send a JSON payload via Invoke-RestMethod to a Slack webhook URL (use a dummy URL for now). 5) Include Try/Catch blocks logging to Windows Event Viewer or standard out.
Before you hit Tab to accept the generated code, pause for 5 seconds.
🔍 Pause & Inspect Checkpoint
Look closely at line 4 (or wherever your if condition is generated).
- Did Copilot actually query WMI or
Get-Volumefor the disk space? - Did it hardcode credentials, or is it using Windows Authentication (
Integrated Security=True)? - Never deploy an AI script that doesn't validate free space before allocating it.
Your AI output should look something like this (adjust as necessary based on your specific Copilot generation):
param (
[string]$ServerName = "localhost",
[string]$DatabaseName = "SelfHealingDB",
[string]$WebhookUrl = "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
)
$ErrorActionPreference = "Stop"
try {
# DBA Verification: Check Disk Space (Assuming Windows C: drive for this demo)
$disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'"
$freeSpaceGB = [math]::truncate($disk.FreeSpace / 1GB)
if ($freeSpaceGB -lt 1) {
throw "Insufficient disk space ($freeSpaceGB GB free) to safely expand database."
}
# Connect to SQL and execute expansion
$query = @"
ALTER DATABASE [$DatabaseName]
MODIFY FILE (NAME = N'SelfHealing_Data', SIZE = 20MB, MAXSIZE = 50MB);
"@
Invoke-Sqlcmd -ServerInstance $ServerName -Database "master" -Query $query -QueryTimeout 30
# Alert the team
$payload = @{ text = "✅ AUTO-REMEDIATION: Expanded data file for $DatabaseName on $ServerName." } | ConvertTo-Json
Invoke-RestMethod -Uri $WebhookUrl -Method Post -Body $payload -ContentType "application/json"
Write-Output "Remediation successful."
} catch {
$errorMsg = $_.Exception.Message
Write-Error "Failed to remediate 1105: $errorMsg"
# Fallback alert could go here
}In a real environment, you would create a SQL Server Alert for Error Number 1105 (Severity 17) and point it to a SQL Agent Job that runs a CmdExec or PowerShell step calling your script.
For today, manually trigger the script, then go back to SSMS and run:
-- Trigger the error
INSERT INTO FillMeUp (Filler)
SELECT TOP 2000 'A' FROM sys.objects a CROSS JOIN sys.objects b;
-- This will fail with Error 1105.
-- Now run your PS script, and rerun the insert. It should succeed!⚡ Lab Micro-Challenge Finished early? Ask Copilot to refactor the PowerShell script to calculate the current file size dynamically using SMO (SQL Server Management Objects) and expand it by exactly 15%, rather than hardcoding "20MB".
If your script isn't firing or fixing the issue, check these common traps:
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| "Invoke-Sqlcmd is not recognized" | Missing PowerShell module on the agent host. | Run Install-Module -Name SqlServer -Force -AllowClobber as Admin. |
| Script runs manually but fails in Agent | SQL Agent Service Account lacks permissions. | Create a Proxy Account mapped to a Credential with local admin/disk read rights, and assign the Job Step to use the Proxy. |
| Endless Loop / SAN Filled | AI generated a blind ALTER DATABASE without space checks. |
Implement strict IF ($FreeSpace -gt X) logic as shown in Step 3. |
| Error 1105 persists after script runs | AI modified the wrong logical file name. | Ensure Copilot extracts the specific logical file name from the alert token $(ESCAPE_SQUOTE(A-LOGICAL-FILE)) passed from the SQL Alert. |
| Webhook 429 Too Many Requests | Alert storm triggered the webhook multiple times a second. | Configure the SQL Server Alert's "Delay between responses" to at least 5 minutes. |
Ensure you have completed and understood the following before logging off today:
- I can explain why checking underlying disk space is mandatory before executing an AI-generated auto-expand script.
- I successfully used Copilot with strict parameter requirements to generate PowerShell.
- I scrutinized the AI-generated PowerShell code specifically for error handling (
Try/Catch) and deterministic boundaries. - I verified that the automated script executes under least-privilege principles (Proxy Accounts vs. sysadmin).
- My mock webhook successfully fired, proving the communication chain from SQL -> Agent -> PS -> Network works.
Tomorrow, we tackle AI-Driven Index Tuning and Parameter Sniffing Remediation. We'll learn how to feed actual XML execution plans into Copilot to generate highly accurate composite index recommendations, and more importantly, how to use AI to safely validate those indexes against workload histograms before creating them in production.
Homework: Ensure your AdventureWorks2022 database is restored and you have Query Store enabled on your sandbox instance. We will need the telemetry data.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Working knowledge of Azure SQL/AWS RDS service tiers, T-SQL scaling commands, and performance metric exports (CSV).
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Empower senior DBAs to leverage AI for data-driven FinOps, transforming raw cloud telemetry into deterministic, automated right-sizing actions that drastically reduce monthly compute spend without sacrificing performance.
By the end of this session, you will be able to:
- Articulate the principles of Database FinOps and the risks of over-provisioning in PaaS environments.
- Construct structured data prompts that allow Copilot to accurately parse and analyze comma-separated performance telemetry.
- Enforce safe scaling boundaries by ensuring AI considers peak storage I/O limits, not just average CPU utilization.
- Diagnose over-provisioned instances by utilizing LLM reasoning to identify sustained low-utilization patterns over a 30-day window.
-
Validate AI-generated
ALTER DATABASEand CLI commands for automated tier scaling before executing them against production subscriptions.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) or Azure Data Studio with GitHub Copilot extension installed. |
| Subscriptions | Active GitHub Copilot License, read-access to an Azure/AWS billing sandbox (optional). |
| SQL Server Engine | Azure SQL Database or Managed Instance (Concepts apply to AWS RDS). |
| Network / Endpoints | Standard outbound HTTPS (TCP 443) to api.github.com. |
| OS | Windows 11 / Server 2022, or macOS/Linux for cross-platform DBAs. |
🇪🇺 European Compliance Callout (GDPR): When exporting telemetry logs for AI analysis, ensure no customer-specific query text, database names containing PII, or internal IPs leak into the CSV headers or data rows. Scrub server names to generic identifiers (e.g., Server_A) before feeding them into the Copilot context window.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Scaling databases up or down triggers billing events and changes underlying infrastructure limits. Your FinOps automation must write heavily to enterprise audit logs. Never allow an AI script to execute a scale-down operation on a SOX-in-scope financial system without a secondary human-in-the-loop approval gate.
Alright, grab a seat. Let’s talk about money.
Cloud elasticity was sold to us as a miracle—pay only for what you use. The reality? Application teams provision 80 vCores "just in case" for launch day, the launch goes fine, and nobody ever dials the hardware back down. Six months later, the CFO is staring at a $250,000 Azure bill, and suddenly it's the DBA's fault.
Today, we are bridging the gap between DBA and FinOps. We are going to use AI to find the fat and trim it. But here is the critical architectural reality when using LLMs for data analysis: Token Truncation.
If you try to feed Copilot a raw CSV containing minute-by-minute CPU stats for 100 databases over 30 days, you will blow past the token limit instantly. The LLM will silently truncate the data, hallucinate the missing numbers, and tell you to scale down a database that actually hits 95% CPU every Friday night. You must pre-aggregate your data (e.g., Daily Max, not Daily Average) before the AI sees it.
Here is the analytical flow we are building:
[ Azure Monitor / CloudWatch ] -> Export 30-Day Telemetry
|
v
[ Aggregation Script (Python/PS) ] -> Squash to Daily MAX values
|
v
[ Cleaned CSV File ] <== (Read by IDE Context)
|
v
[ Copilot Analysis ]
1. Identifies Max CPU/IO < 20%
2. Calculates Cost Delta ($)
3. Generates Scaling Scripts
|
v
[ DBA Review & Execution ] -> `ALTER DATABASE [DB] MODIFY (SERVICE_OBJECTIVE = 'HS_Gen5_4')`
🎙️ Field Note
I once had an enthusiastic junior DBA use an LLM to "optimize" our Azure SQL spend. The AI looked at average CPU, which was 5%, and recommended scaling down from 16 vCores to 2 vCores. The DBA ran the script. What the AI missed—because it wasn't asked—was that the ETL batch process maxed out the transaction log I/O throughput for two hours every night. The 2-vCore tier's IOPS limit choked the ETL, causing a massive SLA breach. Never scale down based on CPU alone. I/O limits dictate PaaS survival.
To get reliable financial analysis from Copilot, we need to constrain its creativity. We aren't asking for code right now; we are asking for data processing.
| Feature / Syntax | DBA Practical Use Case |
|---|---|
#file:utilization.csv |
Directly binds your aggregated metric log to the prompt so Copilot doesn't guess the data. |
Format output as a Markdown table |
Forces Copilot to return its findings (Instance, Current Tier, Proposed Tier, Savings) in a readable format for management. |
System Prompting (Constraints) |
"Assume Azure SQL vCore pricing. Do not recommend scale downs if Max IO > 50%." |
📂 dba-finops-workspace
┣ 📂 raw_metrics
┃ ┗ 📜 azure_sql_30d_raw.csv (Ignored by AI)
┣ 📂 processed_data
┃ ┗ 📜 daily_max_metrics.csv (Fed to AI)
┣ 📂 pricing_reference
┃ ┗ 📜 azure_vcore_rates.txt (Provides pricing context to LLM)
┗ 📂 output_scripts
┗ 📜 Auto_RightSize.sql
Time to get our hands dirty. Open VS Code. We are going to feed Copilot a mock telemetry file and ask it to play CFO.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Identify & Remediate Over-provisioning | FinOps Workspace | 90 Minutes | 1 Savings Report, 1 T-SQL Scaling Script |
Create a new file in your workspace named daily_max_metrics.csv and paste the following mock data. This represents 30 days of peak utilization for three databases.
DatabaseName,CurrentvCores,CurrentTier,MaxCPU_30d,MaxMemory_30d,MaxIO_30d,MonthlyCost
Sales_Prod,16,BusinessCritical,14%,22%,18%,$4100
HR_Archive,8,GeneralPurpose,5%,8%,2%,$1200
Logistics_DB,4,GeneralPurpose,88%,90%,95%,$600Open GitHub Copilot Chat. We need to be highly specific to prevent hallucinations.
Prompt:
@workspace Read #file:daily_max_metrics.csv. Identify any database where MaxCPU_30d, MaxMemory_30d, AND MaxIO_30d are ALL below 20%. For those qualifying databases, propose scaling them down by exactly half their current vCores, staying within the same tier family (e.g., BC to BC, GP to GP). Calculate the estimated new monthly cost assuming a linear 50% price drop. Present the findings as a Markdown table with columns: Database, Current vCores, Proposed vCores, Monthly Savings.
Before you hit enter, double-check your conditions. Did you include I/O? Yes.
🔍 Pause & Inspect Checkpoint Look at Copilot's response.
- Did it correctly ignore
Logistics_DB? (It should, because its utilization is dangerously high). - Did it correctly identify
Sales_ProdandHR_Archiveas candidates? - Never take the AI's math as gospel. Verify the 50% cost reduction math in your head before passing this report to your boss.
Now that we have our targets, let's have Copilot write the T-SQL to execute the changes safely.
Prompt:
Based on the qualifying databases identified above, generate the exact T-SQL ALTER DATABASE commands to scale them to the proposed vCore counts in Azure SQL. Wrap the commands in a TRY/CATCH block. Include a PRINT statement that outputs the old tier and new tier.
Your output should look similar to this:
BEGIN TRY
PRINT 'Initiating scale-down for Sales_Prod from BC_Gen5_16 to BC_Gen5_8...';
ALTER DATABASE [Sales_Prod] MODIFY (SERVICE_OBJECTIVE = 'BC_Gen5_8');
PRINT 'Initiating scale-down for HR_Archive from GP_Gen5_8 to GP_Gen5_4...';
ALTER DATABASE [HR_Archive] MODIFY (SERVICE_OBJECTIVE = 'GP_Gen5_4');
PRINT 'FinOps scale-down commands submitted successfully.';
END TRY
BEGIN CATCH
PRINT 'Error Number: ' + CAST(ERROR_NUMBER() AS VARCHAR);
PRINT 'Error Message: ' + ERROR_MESSAGE();
END CATCH
GO⚡ Lab Micro-Challenge
Finished early? Cloud scaling operations run asynchronously. Ask Copilot to modify the script to dynamically query sys.dm_operation_status in a WHILE loop to check the status of the ALTER DATABASE command and PRINT "Scaling Complete" only when the state changes to COMPLETED.
Watch out for these landmines when using AI for cloud cost optimization:
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| AI recommends scaling down an active DB | Fed average metrics instead of peak/max metrics to the LLM. | Pre-process logs in PowerShell/Python to group by Day and extract MAX(). |
| "Pricing model not recognized" | Copilot's training data has outdated Azure/AWS pricing. | Include a small pricing_reference.txt file in your workspace mapping tiers to current costs. |
| ALTER DATABASE syntax error | LLM mixed up Azure SQL DB syntax with Managed Instance or On-Prem syntax. | Explicitly state "Use Azure SQL Database PaaS syntax" in your prompt. |
| Application Timeouts post-scale | Scaled down CPU, but bottlenecked on storage IOPS limits of the lower tier. | Always mandate Copilot to check MaxIO_30d <= 30% before recommending scale-downs. |
| Token Limit Exceeded | Passed a 100,000-row CSV file into the chat window. | Truncate the file to aggregated summaries or analyze top 20 most expensive databases at a time. |
Check these off before you run any FinOps scripts in production:
- I understand the danger of token truncation and why I must pre-aggregate my metric logs.
- I explicitly forced the AI to evaluate I/O and Memory, not just CPU, before recommending a scale-down.
- I verified the mathematical calculations in the AI-generated savings report manually.
- I reviewed the generated
ALTER DATABASEscripts for correct Azure/AWS syntax and service objective naming conventions. - I understand that scaling operations cause a brief connection drop at the tail end of the process, and I have scheduled these for maintenance windows.
Tomorrow, we dive deep into AI-Driven Execution Plan Analysis and Parameter Sniffing. We've touched on it before, but now we are going to learn how to safely export XML execution plans, feed them directly into the LLM context window, and have Copilot highlight exactly which node is causing the cardinality estimation failure.
Homework: Ensure you have a local instance of SQL Server running with Query Store enabled, as we will be pulling historical XML plans for analysis.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Familiarity with Deadlock XML graphs, Execution Plans, stored procedure tuning, and Jira/ServiceNow queue management.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Equip senior DBAs to systematically annihilate chronic technical debt using a multi-prompt AI orchestration workflow, safely transforming weeks of backlog tickets into a few hours of supervised, high-yield engineering.
By the end of this session, you will be able to:
- Articulate the AI Orchestrator workflow (Context Injection -> Writer Agent -> Auditor Agent -> Human Review) for complex database troubleshooting.
- Construct specialized Copilot prompts that isolate root causes within dense Deadlock XML graphs and obfuscated legacy SSRS procedures.
- Enforce the "Auditor Agent" pattern, forcing the LLM to critique its own generated solutions before you ever test them.
- Diagnose multi-layered performance issues by linking missing index requests directly to the underlying workload execution plans.
- Validate the cost/benefit ratio of AI-assisted technical debt reduction by tracking elapsed resolution time and compute impact.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) or Azure Data Studio with GitHub Copilot extension installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise preferred). |
| SQL Server Engine | SQL Server 2019/2022 or Azure SQL Database. |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com. |
| OS | Windows 11 / Server 2022, or macOS/Linux for cross-platform DBAs. |
🇪🇺 European Compliance Callout (GDPR): Deadlock XMLs and SSRS report parameters are notorious for capturing live PII (e.g., @PatientID, @CreditCardHash). You must aggressively scrub these parameter values from your *.xdl and *.sql files before passing them into the Copilot context window.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Closing a backlog ticket with AI-generated code still requires standard Change Advisory Board (CAB) approval for SOX-in-scope databases. Ensure your commit messages clearly document that an AI-assisted analysis was performed, accompanied by the human DBA's validation checklist.
Alright folks, settle in. Today we are tackling the monster under the bed: the DBA Backlog.
Every enterprise data team has one. It's the graveyard of "good intentions"—the low-priority deadlocks that happen at 2 AM on Sundays, the missing index requests from developers that lack context, and the legacy SSRS reports that take 45 seconds to render. We ignore them because analyzing them takes hours, and we barely have time to keep the lights on.
Today, we change the math. We are going to use AI to process these tickets in bulk. But we aren't just going to ask Copilot to "fix it." We are going to employ the AI Orchestrator Workflow. This means you simulate a two-person team inside the LLM: a Junior DBA (Writer Agent) who proposes the fix, and a Senior DBA (Auditor Agent) who attempts to tear the fix apart.
Here is the deterministic flow:
[ Jira/ServiceNow Backlog ] -> Export Ticket Data (XML, SQL, Logs)
|
v
[ Context Injection ] -> Clean files loaded into VS Code Workspace
|
v
[ 1. Writer Agent Prompt ] -> "Analyze this deadlock XML and propose a fix."
|
v
[ 2. Auditor Agent Prompt ] -> "Act as a Senior DBA. Critique the proposed fix.
What are the negative side effects on tempdb or locks?"
|
v
[ Human Review ] -> You make the final call, apply the fix, and track the time saved.
🎙️ Field Note
Early in my AI journey, a developer submitted a ticket for a missing index. I blindly fed the dynamic management view (DMV) recommendation to an LLM and told it to write theCREATE INDEXscript. It did. I deployed it. What the LLM didn't know—because I didn't enforce the Auditor Agent step—was that the table had 4 billion rows and 600 inserts a second. The new index caused massive PAGEIOLATCH_EX contention and brought the app down. Never let the Writer Agent deploy code without the Auditor Agent cross-examining it first.
To clear the backlog effectively, you must master role-playing within the Copilot chat.
| Feature / Syntax | DBA Practical Use Case |
|---|---|
#file:deadlock_graph.xdl |
Injecting raw XML directly into the context window for lock analysis. |
@workspace /explain |
Asking Copilot to break down a 2,000-line legacy SSRS stored procedure. |
Act as a critical Senior DBA... |
The "Auditor" prompt. Forces the LLM out of "helpful" mode and into "skeptical" mode. |
📂 dba-backlog-zero
┣ 📂 ticket_1044_deadlock
┃ ┗ 📜 graph.xdl
┣ 📂 ticket_1045_slow_report
┃ ┗ 📜 sp_MonthlySales_Legacy.sql
┗ 📂 ticket_1046_missing_index
┗ 📜 query_and_plan.sql
Open your IDE. We are going to process three simulated backlog tickets in record time. Raise your hand if you don't have the lab files extracted.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Resolve 3 Chronic Tickets | VS Code Local Workspace | 90 Minutes | 3 Audited Fixes, 1 ROI Tracker |
Ensure you have three files ready. For this lab, load a sample Deadlock XML (graph.xdl), a messy stored procedure (sp_MonthlySales.sql), and a query with a missing index request.
Open the graph.xdl file. Look at the raw XML—it's unreadable. Let's use the Orchestrator workflow.
Prompt 1 (Writer Agent):
@workspace Read #file:graph.xdl. Identify the victim process and the survivor process. Explain the exact sequence of events that led to the cyclic dependency (e.g., Process A held X, requested Y; Process B held Y, requested X). Propose two different T-SQL solutions to prevent this deadlock from recurring.
Pause and read the output. Now, challenge it.
Prompt 2 (Auditor Agent):
Act as a Senior Database Architect. Review the two solutions you just proposed. What are the operational downsides of each? Will adding theNOLOCKhint cause dirty reads that violate financial reporting standards? Will changing the isolation level impacttempdbversion store sizing?
🔍 Pause & Inspect Checkpoint
Look closely at the Auditor's response. Did it catch the fact that adding NOLOCK to a financial report is a compliance violation? If you just accepted the Writer Agent's code, you would have introduced a data integrity bug. This is why human review is mandatory.
Open your legacy 1,000-line stored procedure.
Prompt:
@workspace Read #file:sp_MonthlySales.sql. This procedure suffers from severe parameter sniffing. Rewrite the core execution block using local variables or theOPTIMIZE FOR UNKNOWNhint. Strip out all deprecated syntax (e.g., old JOIN styles).
⚡ Lab Micro-Challenge
Finished early? Take the rewritten SSRS procedure and ask Copilot to generate a suite of EXEC statements that test the procedure with edge-case parameters (NULLs, dates out of bounds, massive data ranges) so you can validate the new execution plans.
In a real enterprise, you must prove the value of AI. Open a markdown file and document:
- Ticket ID: 1044
- Traditional Resolution Time: ~2.5 hours (XML parsing, testing).
- AI-Assisted Resolution Time: 15 minutes.
- Time Saved: 2.25 hours.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Copilot refuses to read the Deadlock XML | File extension .xdl not recognized or file is too large. |
Rename to .xml or paste the specific <deadlock> nodes directly into chat. |
| Auditor Agent just agrees with the Writer | Prompt was too polite. LLMs default to sycophancy. | Use aggressive phrasing: "Critique this brutally," "Find 3 reasons this will fail." |
| Missing Index fix ignores existing indexes | You didn't provide schema context. | Always include #file:table_schema.sql so the AI can suggest composite modifications, not just brand new indexes. |
| "Token length exceeded" on SSRS proc | The legacy procedure is 5,000+ lines long. | Break the proc into chunks, or ask Copilot to focus exclusively on the specific SELECT statement causing the bottleneck. |
| Accidental PII leak in prompt | XML parameters contained real emails/names. | Use a quick RegEx find/replace in VS Code to obfuscate parameters before opening Copilot. |
- I can articulate the difference between the Writer Agent and Auditor Agent prompts.
- I successfully parsed a Deadlock XML graph using Copilot and identified the root cyclic dependency.
- I actively pushed back on a generated solution by asking Copilot to evaluate negative side-effects on the SQL engine.
- I scrubbed all PII from my backlog artifacts before injecting them into the AI context window.
- I have begun tracking the "time saved per ticket" to report FinOps/efficiency metrics to management.
Tomorrow is the big one: Day 30: The Capstone – Automated Enterprise Migration & Code Conversion. We will take everything we’ve learned over the last 29 days and use AI to convert a legacy, on-prem Oracle database schema and workload directly into Azure SQL Database, including automated testing pipelines.
Homework: Rest up, review your notes on context window management, and make sure your Azure CLI is authenticated.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-29. Proficiency in multi-agent prompt orchestration, T-SQL, PowerShell, and GitHub Actions.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Demonstrate the complete transformation from a manual Query Operator to an AI-Augmented Data Architect by orchestrating a zero-typing, end-to-end multi-agent deployment of a complex database solution.
By the end of this session, you will be able to:
- Articulate the architectural role of a human-in-the-loop when managing multi-agent LLM workflows for infrastructure deployment.
- Construct a comprehensive, zero-typing deployment package (Schema, Logic, Health Checks, CI/CD) using only deterministic AI prompts.
- Enforce enterprise security guardrails by utilizing AI Auditor Agents to cross-examine Writer Agents before sandbox execution.
- Diagnose logical drift in the AI's Chain of Thought logs when generating interdependent objects like Foreign Keys and CI/CD YAML files.
- Validate a full system deployment in under two hours, achieving zero manual syntax errors and 100% compliance with established standards.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) with GitHub Copilot & GitHub Actions extensions installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise), Azure/AWS Sandbox. |
| SQL Server Engine | SQL Server 2025 (Developer) or Azure SQL Database Sandbox. |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com and your test server. |
| OS | Windows 11 / Server 2022, or macOS/Linux for cross-platform DBAs. |
🇪🇺 European Compliance Callout (GDPR): As you instruct the AI to build this architecture, you must explicitly prompt it to include data masking and encryption-at-rest configurations for any table columns designated for user data. The AI must architect privacy by design, not as an afterthought.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Your CI/CD pipeline generated by the AI must include strict separation of duties. The service principal deploying the DDL changes cannot be the same account used for the automated PowerShell health checks. Ensure the AI documents this in the deployment README.
Welcome to the finish line, folks. Take a deep breath. Over the last 29 days, we've broken down every component of SQL Server administration and rebuilt it using AI.
Today, we stop typing. Today, you are no longer a mechanic; you are the factory floor manager. Your job is to orchestrate. We are going to execute a complete business requirement from scratch without writing a single line of syntax manually.
The biggest risk today is Agent Drift. When you ask an LLM to generate 3 tables, 2 procs, a PowerShell script, and a YAML pipeline all at once, its context window will fragment. The YAML file will try to execute a script that the PowerShell agent named differently, or the stored procedure will reference a column the schema agent forgot to build.
You must act as the State Manager. You will use the AI Orchestrator workflow, moving step-by-step and pinning generated files to the workspace context so the next prompt has a deterministic foundation.
[ Business Requirement ] -> Human Architect Defines Parameters
|
v
[ 1. Schema Agent ] -> Generates Tables & Keys -> Saves to #file:schema.sql
|
v
[ 2. Logic Agent ] -> Reads schema.sql -> Generates Stored Procs -> Saves to #file:procs.sql
|
v
[ 3. Ops Agent ] -> Reads both -> Generates PS Health Check -> Saves to #file:monitor.ps1
|
v
[ 4. CI/CD Agent ] -> Orchestrates all files -> Generates #file:deploy.yml
|
v
[ Human Data Architect ] -> Approves Chain of Thought -> Merges PR -> Deploys
🎙️ Field Note
I tried doing a zero-typing deployment for a client's inventory microservice last year. I got cocky and asked Copilot to generate everything in one massive prompt. The code looked beautiful. But when I ran it, the PowerShell script was authenticating usingsa, the stored procs lackedSET NOCOUNT ON, and the CI/CD pipeline had no rollback step. It was a disaster waiting to happen. AI is your exoskeleton, not your replacement. You still own the blast radius. Segment your prompts and audit everything.
Today is about chaining context. You will use a master workspace directory.
| Feature / Syntax | DBA Practical Use Case |
|---|---|
Chain of Thought Prompting |
"Before writing the code, explain your step-by-step logic for how the foreign keys will interact with the CI/CD deployment order." |
@workspace /new |
Ask Copilot to scaffold the entire empty directory structure for your capstone project before generating code. |
Strict adherence to #file:[X] |
Forcing the AI to use the exact naming conventions it generated in Step 1 when it writes the code for Step 3. |
Have Copilot generate this empty structure first:
📂 capstone-deployment
┣ 📂 01_schema
┣ 📂 02_logic
┣ 📂 03_ops
┗ 📂 .github
┗ 📂 workflows
Alright, hands off the keyboard (mostly). Your job is to prompt, review, and approve.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Zero-Typing System Deployment | Sandbox Instance | 120 Minutes | 3 Tables, 2 Procs, 1 PS Script, 1 YAML |
You have been handed this requirement by the Dev Team:
Build a basic 'Audit Logging' microservice. We need a Users table, an Applications table, and an AuditLogs table. We need one stored proc to insert logs quickly, and one to purge logs older than 90 days. We need a PowerShell script to alert if the table exceeds 10GB. Finally, we need a GitHub Action to deploy this to our test server.
Open Copilot Chat.
Prompt:
@workspace Scaffold a directory structure for an Audit Logging database project. Then, generate the T-SQL to create theUsers,Applications, andAuditLogstables. Enforce strict Foreign Keys, Clustered/Non-Clustered indexes appropriate for high-insert logging, and default constraints. Do not use any deprecated data types. Save this as 01_schema/tables.sql.
🔍 Pause & Inspect Checkpoint
Look at the generated schema. Did it use DATETIME2 instead of DATETIME? Did it put a clustered index on an ever-increasing identity column in the AuditLogs table to prevent page splits? If not, push back and tell the AI to fix its architecture.
Now, force context for the next step.
Prompt:
@workspace Read #file:01_schema/tables.sql. Based STRICTLY on those column names, write two stored procedures:usp_InsertAuditLog(must use Try/Catch and Transaction management) andusp_PurgeOldLogs(must batch deletes in chunks of 5000 to prevent transaction log bloat). Save to 02_logic/procs.sql.
Next, the ops script:
Prompt:
@workspace Create a PowerShell script using theSqlServermodule to check the size of theAuditLogstable. If it exceeds 10GB, write a warning to the Windows Event Log. Save to 03_ops/healthcheck.ps1.
Finally, string it together.
Prompt:
@workspace Create a GitHub Actions YAML file that triggers on push to themainbranch. It must sequentially deploytables.sql, thenprocs.sqlusing theazure/sql-action. It must use GitHub Secrets for the connection string. Save to .github/workflows/deploy.yml.
⚡ Lab Micro-Challenge
Finished early? Ask your Auditor Agent to review the entire workspace and generate a Rollback script (undo.sql) that safely drops the procs and tables in the correct dependency order.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Proc references invalid column | Agent Drift. AI forgot the schema from Step 1. | Always include #file:01_schema/tables.sql in your prompt for Step 2. |
| Deletes cause transaction log full | AI wrote a blind DELETE FROM AuditLogs. |
Instruct the AI explicitly to "batch deletes in chunks of 5000 with a WAITFOR DELAY". |
| Pipeline fails on deployment | YAML file executes procs before tables. | Explicitly dictate deployment order in your prompt: "Step 1: Schema, Step 2: Logic." |
| PowerShell script hangs | AI used Invoke-Sqlcmd without a timeout parameter. |
Prompt the AI to "Enforce strict QueryTimeout and ConnectionTimeout parameters." |
| Loss of formatting in files | You copy-pasted badly from the chat window. | Use the "Insert at Cursor" or "Save to File" buttons directly in the Copilot UI. |
Before you declare victory and claim your certification, verify:
- I successfully deployed 100% of the architecture using only prompts.
- I utilized the Auditor Agent pattern to review the schemas and procedures for performance bottlenecks (like page splits or blocking).
- I enforced CI/CD best practices, ensuring secrets were never hardcoded in the AI-generated YAML.
- I maintained the role of Data Architect, rejecting sub-optimal AI output and forcing recalculation.
- The full deployment successfully executed in the sandbox environment.
Congratulations. You have completed the 30-day transformation. You are no longer just keeping the lights on; you are writing the code that automates the power grid. Keep practicing, keep challenging the AI's output, and always remember: the machine types fast, but you are the architect.
Stay connected with the alumni network, and happy optimizing.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Basic familiarity with SQL Server Management Studio (SSMS), Azure Data Studio (ADS), and dynamic management views (DMVs).
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Establish a secure, enterprise-compliant AI development environment within SSMS and Azure Data Studio, mastering context injection to force the LLM to generate highly specific, metadata-aware T-SQL rather than generic textbook syntax.
By the end of this session, you will be able to:
- Articulate the architectural difference between public AI chatbots and secure IDE-integrated AI assistants.
- Construct an enterprise-grade AI workspace within Azure Data Studio and SSMS 22 / Azure Data Studio (latest).
-
Enforce strict context boundaries using
#fileand@workspacemarkers to prevent PII/metadata leakage. - Diagnose hallucinated T-SQL by scrutinizing AI-generated dynamic management view (DMV) joins.
- Validate your setup by successfully prompting Copilot to generate a complex, schema-aware database discovery report.
| Requirement | Specification |
|---|---|
| IDE | SSMS 22.x (latest build) OR Azure Data Studio (ADS) 1.48+ |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise preferred for telemetry block) |
| SQL Server Engine | SQL Server 2019/2022 Developer Edition or local container |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com and Microsoft auth endpoints |
| OS | Windows 10/11 / Server 2022 (macOS/Linux applicable for ADS only) |
🇪🇺 European Compliance Callout (GDPR): The biggest risk of AI in the database layer is accidental context leakage. You must verify that your Copilot Business/Enterprise tier has the "Snippet Telemetry" option disabled in the GitHub organization portal. This ensures Microsoft does not use your proprietary table schemas or DDL to train future models.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): When feeding metadata into the AI context window, do not include sample data or column definitions that contain PHI (Protected Health Information). Mask your local .sql files to replace columns like SSN or PatientDOB with generic identifiers before using the #file context marker.
Welcome to Day 1, everyone. Grab a coffee, grab a seat. We are starting a 30-day journey to fundamentally change how you interact with the SQL Server engine.
The biggest pain point I hear from senior DBAs is: "AI is a toy. I ask it for a query, and it gives me generic SELECT * FROM Table1 garbage."
They are right. Out-of-the-box, an LLM doesn't know if you are running a 5MB blog database or a 50TB partitioned financial ledger. If you don't feed it your enterprise context, it will feed you textbook answers. Our goal today is to bridge your specific database metadata with the LLM's reasoning engine securely.
Here is the deterministic architecture of how Copilot Chat interacts with your IDE:
[ IDE (SSMS 22 / Azure Data Studio (latest) / ADS) ]
|
|-- (User highlights script or specifies #file)
v
[ Copilot Extension Context Manager ] -> Filters out ignored files (.gitignore)
|
|-- (Packages prompt + active code + relevant schema into tokens)
v
[ TLS 1.2/1.3 Encrypted Tunnel ]
|
v
[ GitHub Copilot LLM Endpoint ] -> (Evaluates query, generates T-SQL)
|
v
[ Copilot UI ] -> DBA Reviews, Audits, and Executes
🎙️ Field Note
I had a DBA at a healthcare client get fired last year. Why? They copied an entire 4,000-line stored procedure into a public, free-tier ChatGPT window to ask for performance tuning. That procedure contained hardcoded linked server passwords and patient PII schema definitions. Public web chatbots are poison for enterprise DBAs. You must do this inside a locked-down IDE with an enterprise Copilot license where your data is isolated.
Stop typing long paragraphs explaining your database to the AI. Use IDE context markers to inject exact schema definitions.
| Feature / Marker | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Workspace Context | @workspace |
Forces Copilot to read the files in your currently open folder (e.g., your database source control repo) to understand naming conventions. |
| File Injection | #file:MySchema.sql |
The single most powerful tool for DBAs. Binds a specific DDL file to the prompt so Copilot writes queries against your exact tables. |
| Selection Focus | #selection |
Tells Copilot to only analyze the lines of T-SQL you have highlighted, ignoring the rest of the 2,000-line script. |
For this series, organize your local machine like this to maintain context:
📂 DBA-Copilot-Sandbox
┣ 📂 metadata
┃ ┗ 📜 schema_export.sql (Cleaned of PII)
┣ 📂 scratchpad
┃ ┗ 📜 daily_queries.sql
┗ 📂 outputs
Let's get this running. Open Azure Data Studio (or SSMS 22 / Azure Data Studio (latest)). Follow my screen closely. Raise your hand if you hit an authentication loop.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Connect Copilot & Generate Admin Script |
localhost / Sandbox |
60 Minutes | IDE Configured, 1 Discovery Script |
- In Azure Data Studio, click the Extensions icon (Ctrl+Shift+X).
- Search for
GitHub CopilotandGitHub Copilot Chat. Install both. - You will be prompted to sign in to GitHub. Use the account tied to your Enterprise/Business license.
- Verify the Copilot Chat icon appears in your left-hand activity bar.
We need to give Copilot something to chew on. Connect to a test database (e.g., AdventureWorks or any sandbox DB). Right-click a few tables, script them as CREATE TO, and save the file as schema_export.sql in your workspace.
Open a new .sql file. Open the Copilot Chat pane.
Do not ask: "Write a query to find missing clustered indexes."
Ask this:
Prompt:
@workspace Read #file:schema_export.sql. Write a comprehensive T-SQL script compatible with SQL Server 2025 that finds all tables referenced in this schema file that are missing a clustered index (heap tables). Join againstsys.dm_db_index_physical_statsto calculate the current fragmentation percentage and page count for these heaps. Exclude system tables and format the output for easy reading. Include a TRY/CATCH block.
Before you click "Insert at Cursor", read the output. Pause for 5 seconds.
🔍 Pause & Inspect Checkpoint
Look closely at the JOIN conditions generated by the AI:
- Did it correctly cross apply
sys.indexeswithsys.dm_db_index_physical_stats? - Did it pass
DB_ID()as the first parameter to the DMV, or did it hallucinate a hardcoded database ID? - Are there filters for
is_ms_shipped = 0to exclude system tables?
Insert the code into your IDE, highlight it, and execute it against your test database.
⚡ Lab Micro-Challenge
Finished early? Ask Copilot to modify the script so that instead of just reporting the fragmented heaps, it dynamically generates (using PRINT statements) the CREATE CLUSTERED INDEX syntax for each one, using a standardized naming convention like CIX_[TableName]_ID.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Copilot extension fails to authenticate | Corporate proxy blocking api.github.com. |
Request networking to whitelist GitHub Copilot endpoints or configure IDE HTTP proxy settings. |
| "I cannot access files outside the workspace" | You used #file but the file isn't in your open folder. |
Use File > Open Folder in ADS to open your DBA-Copilot-Sandbox directory first. |
| AI uses deprecated syntax or DMVs | The LLM defaulted to an older SQL Server version. | Explicitly state "Compatible with SQL Server 2025 (Compatibility Level 170)" in your system prompt. |
| SSMS 22 Copilot features missing | Preview features are not enabled. | Ensure you are on the latest SSMS 22 build and check Tools > Options for Copilot integration toggles. |
| Token Limit Truncation | Your schema_export.sql is 50,000 lines long. |
Only export the schemas for the specific tables/modules you are tuning today, not the entire ERP system. |
Ensure you have completed and understood the following before logging off today:
- I have successfully authenticated GitHub Copilot inside Azure Data Studio or SSMS 22 / Azure Data Studio (latest).
- I understand why pasting raw enterprise code into a public web browser AI is a security violation.
- I successfully used the
#filemarker to force Copilot to read my local T-SQL schema. - I reviewed the AI's DMV joins for accuracy before executing the discovery report.
- I understand how to bypass the "generic query" problem by providing explicit schema context.
Tomorrow, we move from administration to optimization. In Day 2: AI-Assisted Query Refactoring & Anti-Pattern Detection, we will learn how to feed 2,000-line legacy "spaghetti code" stored procedures into Copilot and instruct it to hunt for implicit conversions, cursor loops, and deprecated JOIN syntax without altering the underlying business logic.
Homework: Find a notoriously slow, massive stored procedure in your non-production environment. Sanitize it of any PII, and bring it to class tomorrow.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Day 1, working knowledge of SQL Server Execution Plans, SARGability, and Index structures.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transform your AI Co-Pilot into an on-demand senior performance tuning mentor capable of parsing dense Execution Plan XMLs in seconds to pinpoint missing indexes, implicit conversions, and non-SARGable predicates.
By the end of this session, you will be able to:
- Articulate how an LLM parses and interprets XML execution plan nodes compared to a traditional graphical plan viewer.
-
Construct precise prompts that force Copilot to extract the top three performance bottlenecks from a raw
.sqlplanfile. - Enforce strict SARGability rules by directing the AI to rewrite legacy query predicates without altering the underlying business logic.
- Diagnose implicit conversion warnings hidden deep within complex plan XMLs that traditional DMVs might obscure.
-
Validate AI-generated
CREATE INDEXrecommendations against existing table metadata to prevent index duplication and insert-contention.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) or Azure Data Studio with GitHub Copilot extension installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise). |
| SQL Server Engine | SQL Server 2019/2022 Developer Edition or Azure SQL Sandbox. |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com. |
| OS | Windows 10/11 / Server 2022 (macOS/Linux applicable for ADS only). |
🇪🇺 European Compliance Callout (GDPR): Execution plans capture the actual parameter values passed during query execution. If a developer searches for @Email = '[email protected]', that email is baked into the XML. You must use a script to sanitize/scrub parameter values from your .sqlplan files before feeding them into the AI context window.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Tuning queries on production systems based on AI recommendations carries risk. The AI does not know your storage IOPS limits. Ensure any CREATE INDEX statement generated by Copilot is deployed first to a staging environment mimicking production data volume to validate the impact on transaction log generation.
Welcome back, everyone. Take your seats. Yesterday, we got the engine running. Today, we put it to work.
Raise your hand if you've ever stared at a 50-step execution plan in SSMS for an hour, scrolling left, right, up, and down, trying to find where the estimated rows diverged from the actual rows. It is like reading a wiring diagram for a skyscraper. The graphical view is great for humans, but under the hood, it is just dense, structured XML.
And you know what LLMs are exceptionally good at? Parsing structured text.
When you feed an execution plan XML into Copilot, it doesn't get distracted by the visual layout. It reads the raw <RelOp> nodes, the <MissingIndexes> elements, and the <Warnings> attributes. It can instantly highlight that a VARCHAR to NVARCHAR implicit conversion on Step 42 is causing a massive Index Scan.
Here is the analytical flow we are executing today:
[ Slow Application Query ] -> SSMS / ADS
|
v
[ Engine Generates XML ] -> Save as "bad_query.sqlplan"
|
v
[ VS Code / ADS Workspace ] <== #file:bad_query.sqlplan
|
v
[ Copilot Analysis Prompt ]
1. Identifies Top 3 Cost Nodes
2. Detects Non-SARGable Predicates
3. Generates Remediation T-SQL
|
v
[ DBA Validates & Deploys ] -> Refactored Query & Indexes
🎙️ Field Note
Let me give you a warning from the trenches. I fed a massive execution plan to an AI, and it enthusiastically recommended a 5-column composite covering index. It looked brilliant on paper. It eliminated the Key Lookup entirely. But the table was our core transactionalOrderstable taking 5,000 inserts a second. The new index was so wide it caused massive page splits andPAGEIOLATCH_EXwaits, bringing the app to its knees. The AI only sees the read query you feed it; it is blind to your write workload. Always validate the physical cost of a new index!
To get the AI to act as a senior tuning mentor, you must constrain its focus. Do not just paste the XML and say "fix this."
| Feature / Marker | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Direct File Injection | #file:query.sqlplan |
Safely passes the raw XML of the execution plan into the context window for deep parsing. |
| System Rules | Ignore missing index warnings... |
You can tell the AI to ignore the "low hanging fruit" (like the standard green text missing index) and force it to look for implicit conversions or residual predicates. |
| Refactoring Request | Rewrite this for SARGability |
Commands the AI to fix queries that wrap columns in functions (e.g., WHERE YEAR(Date) = 2023). |
Set up your folder for today's lab so Copilot has the right context.
📂 dba-tuning-lab
┣ 📂 plans
┃ ┗ 📜 slow_report.sqlplan
┣ 📂 schema
┃ ┗ 📜 table_metadata.sql
┗ 📂 scripts
┗ 📜 refactored_code.sql
Alright, open your IDEs. Let's feed the machine some bad code.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Parse XML & Refactor Query | Sandbox Instance | 90 Minutes | 1 Analysis Report, 1 Refactored Script, 1 Index Script |
First, we need a bad query. Run this in your sandbox to generate a terrible plan (assuming a standard Orders table with a DATETIME column):
-- Turn on Actual Execution Plan (Ctrl+M in SSMS)
SELECT OrderID, CustomerID, TotalAmount
FROM Orders
WHERE CONVERT(VARCHAR(10), OrderDate, 120) = '2023-10-01'
AND CustomerID LIKE '%123%';Right-click the graphical plan, select "Save Execution Plan As..." and save it into your workspace as slow_report.sqlplan.
Open Copilot Chat. We are going to treat it like a senior DBA looking over our shoulder.
Prompt:
@workspace Read #file:slow_report.sqlplan. Act as an expert SQL Server Performance Tuner. Analyze this execution plan XML. Identify the top 3 bottlenecks in the plan (look specifically for scans, implicit conversions, or residual IO). Do not just give me the missing index warning. After identifying the bottlenecks, suggest the exact T-SQL CREATE INDEX statements needed, ensuring they do not conflict with best practices.
Before you copy-paste the output, stop and read it.
🔍 Pause & Inspect Checkpoint Look closely at the AI's response:
- Did it catch that
CONVERT(VARCHAR...)on theOrderDatecolumn is destroying the ability to use an index seek? - Did it notice the leading wildcard in the
LIKEclause? - If it suggested an index, is it a clustered or non-clustered index? Did it include
INCLUDEcolumns?
The index alone won't fix this because the query is non-SARGable (Search Argumentable). Let's have Copilot fix the code.
Prompt:
Based on your analysis, refactor the original T-SQL query to ensure strict SARGability. Remove the function wrapped around the OrderDate column and rewrite it using a proper date range. Explain why this rewrite allows the SQL Server Optimizer to perform an Index Seek.
Your expected AI output should look something like:
SELECT OrderID, CustomerID, TotalAmount
FROM Orders
WHERE OrderDate >= '2023-10-01 00:00:00'
AND OrderDate < '2023-10-02 00:00:00'
AND CustomerID LIKE '%123%'; -- Note: Leading wildcards still force a scan, but the date is now SARGable.⚡ Lab Micro-Challenge
Finished early? Take the CREATE INDEX script Copilot generated. Open a new chat prompt and ask Copilot: "Write a T-SQL script using sys.dm_db_partition_stats to estimate how many megabytes this new index will consume based on the current row count of the table."
Watch out for these issues when analyzing execution plans with AI:
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| "Token Limit Exceeded" | The .sqlplan file is for a 5,000-line ERP query and the XML is 20MB. |
Isolate the exact sub-query or statement node causing the issue. Only pass that specific XML block to Copilot. |
AI suggests NOLOCK to fix blocking |
The LLM learned bad habits from old StackOverflow posts. | Strictly add to your prompt: Do not suggest changing the isolation level or using NOLOCK hints.
|
| AI recommends duplicate indexes | The AI doesn't know what indexes already exist on the table. | Always inject a #file:table_indexes.sql containing your existing index DDL so it can consolidate them. |
| XML parsing hallucination | Copilot invents node names or costs that don't exist. | Force precision: Quote the exact XML node and StatementId where you found this bottleneck.
|
| Refactored query returns different data | SARGable rewrite mishandled timezone or time boundaries (e.g., missed milliseconds). | Verify the > vs >= logic in date range rewrites carefully. |
Ensure you have completed and understood the following before logging off:
- I understand how wrapping a column in a function destroys SARGability and causes Index Scans.
- I successfully loaded a
.sqlplanfile into the AI context window. - I prompted the AI to find implicit conversions and residual predicates rather than just basic missing indexes.
- I forced the AI to rewrite a bad query without changing the business logic.
- I know to always validate an AI-generated index against my write-workload (Inserts/Updates/Deletes).
Tomorrow, we move from reactive tuning to proactive maintenance. In Day 3: Automated Baseline Generation & Anomaly Detection, we will use Copilot to write complex Extended Events (XE) sessions and parse the resulting .xel files to establish a performance baseline, automatically detecting when a new deployment degrades your server's health.
Homework: Make sure your local SQL Agent is running, and brush up on your Extended Events syntax. You will need it.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1 & 2. Deep understanding of SQL Server STATISTICS IO, execution plans, Window Functions, and Common Table Expressions (CTEs).
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Empower senior DBAs to utilize AI to safely deconstruct, comprehend, and refactor monolithic, undocumented procedural T-SQL (cursors/loops) into highly optimized, set-based architectures.
By the end of this session, you will be able to:
- Articulate the performance penalties of RBAR (Row-By-Agonizing-Row) processing and how LLMs map procedural logic to declarative sets.
- Construct iterative Copilot prompts that first decipher legacy business logic in plain English before attempting code transformation.
-
Enforce strict syntax standards by directing the AI to implement
TRY/CATCHblocks, Window Functions, and CTEs. - Diagnose functional regressions in AI-generated code by tracking data state changes step-by-step.
-
Validate the physical engine benefits of the refactored code by benchmarking logical reads and CPU time using
SET STATISTICS IO, TIME ON.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) or Azure Data Studio with GitHub Copilot extension installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise). |
| SQL Server Engine | SQL Server 2019/2022 (Developer Edition) or Azure SQL Database. |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com. |
| OS | Windows 10/11 / Server 2022, or macOS/Linux for cross-platform DBAs. |
🇪🇺 European Compliance Callout (GDPR): Legacy stored procedures often contain hardcoded references to PII logic (e.g., IF @EmployeeName = 'John Doe'). Scrub your legacy procedures of hardcoded identities or specific financial thresholds before highlighting the code and sending it to the Copilot context window via #selection.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Refactoring a SOX-in-scope financial calculation procedure changes the architectural execution, even if the math remains the same. You must retain the original Copilot chat transcripts ("Chain of Thought") as artifacts for your Change Advisory Board (CAB) to prove the transformation logic did not alter the intended financial output.
Welcome back to the classroom, everyone. Grab a seat. Today, we put on our surgical gloves.
Raise your hand if you've ever inherited an undocumented, 1,000-line stored procedure written ten years ago by a developer who thought SQL was just C# with tables. You open it up and immediately see DECLARE my_cursor CURSOR... followed by 300 lines of FETCH NEXT, nested loops, and temporary table thrashing.
We call this RBAR: Row-By-Agonizing-Row. The relational engine hates it. It saturates tempdb, spikes the CPU, and kills concurrency. But we are terrified to touch it because we don't understand the undocumented business logic buried inside the loop.
This is where your AI Co-Pilot transitions from a "code generator" to an "architectural editor." We are going to use the AI to translate the loop into plain English, and then rewrite it into declarative, set-based T-SQL.
Here is the workflow:
[ Legacy 1,000-Line Procedure ] -> Loaded in IDE
|
v
[ AI Context: #selection ] -> Highlight the Cursor Block
|
v
[ Prompt 1: /explain ] -> AI outputs business rules in plain English
|
v
[ Prompt 2: Refactor ] -> AI generates set-based CTE / Window Function
|
v
[ SSMS / ADS Execution ] -> Benchmark old vs new with STATISTICS IO
🎙️ Field Note
Three years ago, we had an "end-of-month billing calculation" that took 14 hours to run. It was a massive nested cursor. We fed it to an LLM, asked for a set-based rewrite, and it gave us a beautiful query utilizingSUM() OVER(PARTITION BY...). The runtime dropped from 14 hours to 12 seconds. We felt like gods. Then accounting called. The AI had subtly mishandled aNULLcoalescence rule deep in anIFstatement inside the old cursor. We under-billed clients by $40,000. Never, ever trust the AI's translation of business rules without rigorous A/B testing on boundary data.
When dealing with massive legacy scripts, you cannot ask the AI to rewrite the whole file at once. You will hit token limits, and the AI will hallucinate. You must use the #selection marker.
| Feature / Marker | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Focus Highlight | #selection |
Forces Copilot to read only the highlighted 200 lines of the cursor, ignoring the 800 lines of parameters and logging around it. |
| Code Comprehension | /explain |
Translates messy procedural T-SQL into a bulleted list of business requirements. |
| Architectural Directives | Rewrite using Window Functions |
Explicitly bans the AI from writing a WHILE loop and forces modern T-SQL constructs. |
📂 dba-legacy-refactor
┣ 📂 original_code
┃ ┗ 📜 sp_CalculateMonthlyTotals_Legacy.sql
┣ 📂 ai_translations
┃ ┗ 📜 logic_explanation.md
┗ 📂 refactored_code
┗ 📜 sp_CalculateMonthlyTotals_V2.sql
Alright, open SSMS 22 / Azure Data Studio (latest) or VS Code. We are going to surgically remove a cursor.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Deconstruct & Refactor Cursor | Sandbox Instance | 90 Minutes | 1 Plain-English Spec, 1 Set-Based Script, 1 I/O Benchmark |
Run this script in your sandbox to create our "legacy" table and populate it with dummy data. Then, review the awful cursor code below it.
-- The Setup (Run this)
CREATE TABLE AccountTransactions (
TxID INT IDENTITY(1,1) PRIMARY KEY,
AccountID INT,
TxDate DATETIME,
Amount DECIMAL(10,2)
);
GO
INSERT INTO AccountTransactions (AccountID, TxDate, Amount)
SELECT TOP (10000)
ABS(CHECKSUM(NEWID())) % 50, GETDATE() - (ABS(CHECKSUM(NEWID())) % 1000), (ABS(CHECKSUM(NEWID())) % 1000) - 500
FROM sys.all_columns c1 CROSS JOIN sys.all_columns c2;
GO
-- The Legacy Cursor (Save as legacy_cursor.sql)
-- GOAL: Calculate running total per account.
DECLARE @AccID INT, @TxAmt DECIMAL(10,2), @RunTotal DECIMAL(10,2)
DECLARE @CurrentAcc INT = -1
CREATE TABLE #TempTotals (AccountID INT, TxAmount DECIMAL(10,2), RunningTotal DECIMAL(10,2))
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT AccountID, Amount FROM AccountTransactions ORDER BY AccountID, TxDate
OPEN cur
FETCH NEXT FROM cur INTO @AccID, @TxAmt
WHILE @@FETCH_STATUS = 0
BEGIN
IF @CurrentAcc <> @AccID
BEGIN
SET @RunTotal = 0
SET @CurrentAcc = @AccID
END
SET @RunTotal = @RunTotal + @TxAmt
INSERT INTO #TempTotals VALUES (@AccID, @TxAmt, @RunTotal)
FETCH NEXT FROM cur INTO @AccID, @TxAmt
END
CLOSE cur; DEALLOCATE cur;
SELECT * FROM #TempTotals;
DROP TABLE #TempTotals;Highlight the entire cursor block in your IDE. Open Copilot Chat.
Prompt:
@workspace Read the #selection. Explain the exact business logic this procedural T-SQL is attempting to accomplish in plain English. Break it down step-by-step so a non-technical project manager can understand it.
Read the output. It should correctly identify that this is calculating a "running total partitioned by AccountID, ordered by Transaction Date."
Now, keep the text highlighted and give the architectural directive.
Prompt:
Based on the business logic you just identified, rewrite this #selection as a single, set-based T-SQL query. You must use modern Window Functions (e.g., SUM OVER). Do not use cursors, WHILE loops, or temporary tables. Wrap the final query in a standard TRY/CATCH block.
🔍 Pause & Inspect Checkpoint Before you hit Tab, pause for 5 seconds. Look at the code.
- Did the AI use
SUM(Amount) OVER (PARTITION BY AccountID ORDER BY TxDate)? - Did it remove the
#TempTotalstable completely? - Did it wrap it cleanly in
BEGIN TRY...END TRY?
Now, let's prove the AI is right. Open a new SSMS window.
Run SET STATISTICS IO, TIME ON; at the top.
Execute the old cursor script. Look at the Messages tab. You will see thousands of logical reads.
Now, execute the AI's set-based rewrite:
BEGIN TRY
SELECT
AccountID,
Amount AS TxAmount,
SUM(Amount) OVER (PARTITION BY AccountID ORDER BY TxDate ROWS UNBOUNDED PRECEDING) AS RunningTotal
FROM AccountTransactions;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCHLook at the Messages tab again. One scan, vastly fewer logical reads, and zero tempdb thrashing.
⚡ Lab Micro-Challenge Finished early? Ask Copilot to refactor its own set-based query to use a Common Table Expression (CTE) to filter the results, showing only accounts where the final running total is negative.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| AI rewrite drops complex IF/ELSE logic | Token truncation or deep nesting inside the cursor confused the LLM. | Ask Copilot to explicitly list all IF conditions from the cursor and map them to a CASE expression. |
| "Windowed functions do not support..." | AI hallucinated invalid syntax for ORDER BY inside an aggregate. |
Remind the AI to strictly adhere to SQL Server 2025 Window Function compatibility guidelines. |
| Massive tempdb bloat during rewrite execution | The set-based query lacks supporting indexes for the PARTITION BY and ORDER BY clauses. |
Prompt AI: "Generate the optimal supporting index for this window function query." |
| Logic translation is completely wrong | You highlighted 1,500 lines at once. | Break the procedure into smaller logical chunks. Use /explain on one block at a time. |
| A/B Testing shows mismatched row counts | The legacy cursor filtered NULL values silently; the set-based query includes them. |
Always use EXCEPT clauses to compare old cursor outputs vs. new set-based outputs during testing. |
- I can explain why Window Functions are architecturally superior to cursors for calculating running totals.
- I successfully used the
#selectionmarker to focus Copilot on a specific block of bad code. - I utilized the
/explaincommand to verify business logic before attempting a code rewrite. - I validated the performance improvements of the AI's code using
SET STATISTICS IO ON. - I understand the absolute necessity of boundary and A/B testing when replacing legacy business logic.
Tomorrow, we pivot to Disaster Recovery. In Day 4: AI-Driven Corruption Analysis & Page Restores, we will use Copilot to parse dense DBCC CHECKDB error logs, identify exactly which pages are torn, and auto-generate the exact, surgical page-level restore commands required to bring the database back online without a full file restore.
Homework: Familiarize yourself with the syntax for page-level restores in T-SQL, and ensure you have a full backup file ready in your sandbox.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-3. Proficiency in fundamental PowerShell concepts and familiarity with the dbatools module.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transition DBAs from writing manual syntax to defining architectural intent, leveraging AI to scaffold production-ready PowerShell scripts, dbatools integrations, and Pester unit tests in seconds.
By the end of this session, you will be able to:
- Articulate the shift from procedural script writing to intent-based AI scaffolding for enterprise database automation.
-
Construct top-level intent comments and precise Copilot prompts to generate complex
dbatoolsfleet health checks. -
Enforce defensive programming standards by instructing the AI to natively include
Try/Catchblocks, logging, and-ErrorAction Stoplogic. -
Diagnose AI hallucinations where the LLM invents non-existent PowerShell cmdlets or incorrect
dbatoolsparameters. - Validate AI-generated automation scripts by prompting Copilot to build automated Pester unit tests before execution.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) with PowerShell and GitHub Copilot extensions installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise). |
| SQL Server Engine | SQL Server 2019/2022 (Developer Edition) registered in a local CMS (Central Management Server) or sandbox. |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com and PowerShell Gallery (for dbatools/Pester). |
| OS | Windows 10/11 / Server 2022 (for native Active Directory authentication). |
🇪🇺 European Compliance Callout (GDPR): Fleet health checks often output HTML reports containing server names, IP addresses, and database names (which might contain customer identifiers). Ensure the AI-generated scripts do not broadcast this data via unencrypted SMTP. Instruct Copilot to save reports to a secured, RBAC-controlled internal network share.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): AI-generated scripts are incredibly efficient, but they must adhere to the principle of least privilege. Any PowerShell script hitting your Central Management Server (CMS) to evaluate SOX-in-scope databases must run under a Group Managed Service Account (gMSA). Never allow the AI to hardcode or prompt for interactive credential objects (Get-Credential) in an automated pipeline.
Alright everyone, find your seats. Today is going to save you hundreds of hours this year.
For the last decade, if we wanted to build a fleet-wide health check, we started with a blank PowerShell screen. We spent 20% of our time writing the core dbatools logic, and 80% of our time fighting HTML formatting, writing Try/Catch blocks, handling connection timeouts, and fixing syntax errors.
Today, you become an Automation Architect. You no longer write the boilerplate. You define the intent. The AI writes the syntax.
However, we must understand the LLM's weakness: Cmdlet Hallucination. AI knows what PowerShell should look like. If it doesn't know the exact dbatools command for backup ages, it will confidently invent Get-DbaBackupAge (which doesn't exist; the command is Get-DbaLastBackup). You must guide it and verify its output.
Here is the deterministic flow we are building today:
[ DBA Defines Intent ] -> # Write a script using dbatools to check backups...
|
v
[ Copilot Context Engine ] -> Evaluates Intent & Workspace
|
v
[ AI Code Generation ]
1. Scaffolds Params & CmdletBinding
2. Writes dbatools logic (Get-DbaLastBackup)
3. Wraps in Try/Catch with Logging
4. Formats to HTML
|
v
[ AI Test Generation ] -> Copilot writes Pester tests to validate logic
|
v
[ DBA Reviews & Deploys ] -> Production-Ready Automation Pipeline
🎙️ Field Note
Early in my automation career, I wrote a PowerShell script to drop empty tables. I missed a standard-ErrorAction Stopinside the loop. When the network blipped, the script lost its context variable, defaulted to$null, and proceeded to blindly drop every table it could reach. Never deploy an AI-generated PowerShell script that lacks strict error handling. Today, we will force Copilot to code defensively by default.
To get Copilot to generate complete scripts rather than mere snippets, we use Top-Level Intent Comments.
| Feature / Syntax | DBA Practical Use Case |
|---|---|
| Top-Level Intent |
# script: ... at the top of an empty .ps1 file to guide inline autocomplete. |
| Pester Generation |
@workspace /tests in Chat to automatically build a Describe block for your active script. |
| System Constraints | Use strictly dbatools cmdlets, enforce strict mode, and add standard logging. |
Set up your folder so Copilot understands this is a modular project:
📂 dba-automation-fleet
┣ 📂 scripts
┃ ┗ 📜 Get-FleetBackupHealth.ps1
┣ 📂 tests
┃ ┗ 📜 Get-FleetBackupHealth.Tests.ps1
┗ 📂 output
┗ 📜 (HTML reports go here)
Open VS Code. Verify your PowerShell extension is active. Let's build a reporting tool that would normally take three hours, in about ten minutes.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Generate CMS Backup Report & Tests | Local CMS / Sandbox | 90 Minutes | 1 PS Script, 1 HTML Report, 1 Pester File |
Open a new file named Get-FleetBackupHealth.ps1. Do not open the chat yet. At the very top of the file, type this exact comment block and press Enter:
<#
.SYNOPSIS
Checks backup health across a Central Management Server (CMS) using dbatools.
.DESCRIPTION
This script connects to a CMS, retrieves all registered SQL Servers, and uses Get-DbaLastBackup
to find databases without a full backup in the last 24 hours.
It outputs a styled HTML report to the C:\temp directory.
Requirements:
- Use strict error handling (Try/Catch).
- Use dbatools module exclusively for SQL interactions.
- Exclude system databases (master, model, msdb, tempdb).
#>Wait 3-5 seconds. Copilot's inline ghost text (gray text) should start scaffolding the CmdletBinding() and param() block. Press Tab to accept it piece by piece.
If the inline generation stalls or hallucinates, switch to the Copilot Chat window.
Prompt:
@workspace Based on the intent comment in #file:Get-FleetBackupHealth.ps1, generate the complete PowerShell script. Ensure you use Get-DbaRegServer to query the CMS and Get-DbaLastBackup for the backup checks. Format the HTML output using ConvertTo-Html with a basic CSS string so it highlights missing backups in red.
🔍 Pause & Inspect Checkpoint
Before you run this code, scrutinize the Get-DbaLastBackup call:
- Did Copilot remember to filter out system databases as requested in the intent?
- Did it handle connection failures to offline servers gracefully, or will the script crash?
-
Trust, but
Get-Command. Verify any suspicious cmdlets actually exist in thedbatoolsmodule.
A script isn't production-ready until it's tested. Open a new file named Get-FleetBackupHealth.Tests.ps1.
Prompt:
@workspace Write a Pester v5 test script for #file:Get-FleetBackupHealth.ps1. Mock the Get-DbaRegServer and Get-DbaLastBackup commands so the test can run without a live SQL Server connection. Test that the script correctly identifies a database with a backup older than 24 hours.
⚡ Lab Micro-Challenge Finished early? The AI gave you a basic HTML report. Ask Copilot Chat to modify the script to inject a charting library (like Chart.js) via CDN into the HTML header, turning your simple table into a visual dashboard showing compliant vs. non-compliant databases.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| "The term 'Get-DbaBackupStatus' is not recognized" | LLM hallucinated a cmdlet that sounds real but isn't in dbatools. |
Correct the AI in chat: "The correct cmdlet is Get-DbaLastBackup. Rewrite it." |
| Script hangs indefinitely | An offline server in the CMS caused WMI/SQL connection timeouts. | Prompt AI to add -ConnectionTimeout 5 to the dbatools commands. |
| Pester tests fail immediately | Copilot generated Pester v4 syntax, but you have Pester v5 installed. | Explicitly specify "Generate Pester v5 syntax using BeforeAll and It blocks" in your prompt. |
| HTML output is unreadable raw text | The AI piped complex objects into ConvertTo-Html without selecting properties. |
Instruct the AI to Select-Object Server, Database, LastFullBackup before piping to HTML. |
| Hardcoded SA credentials in script | AI defaulted to standard SQL auth examples. | Reject the code. Prompt: "Rewrite to strictly use Windows Authentication / Integrated Security." |
- I can explain the difference between typing syntax and defining architectural intent in PowerShell.
- I successfully used top-level comment blocks to guide Copilot's inline generation.
- I verified that the AI utilized genuine
dbatoolscmdlets instead of hallucinating functions. - I enforced defensive coding practices (Try/Catch, strict modes) via my AI prompts.
- I successfully generated a mocked Pester unit test to validate the script logic safely.
Tomorrow, we combine everything we've learned about architecture and security. In Day 5: Security Auditing & Automated RBAC Generation, we will use Copilot to parse complex Active Directory group structures and automatically generate idempotent T-SQL Role-Based Access Control (RBAC) scripts to enforce the Principle of Least Privilege across your entire database fleet.
Homework: Review the concepts of Contained Database Users and Server Roles. Have a sandbox database ready with a few dummy schemas created.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-4. Solid understanding of Always On Availability Groups, Windows Server Failover Clustering (WSFC), and system DMVs.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Equip senior DBAs to instantly generate context-aware T-SQL diagnostic scripts and customized emergency operational runbooks during High Availability/Disaster Recovery (HA/DR) incidents, drastically reducing Mean Time to Recovery (MTTR).
By the end of this session, you will be able to:
- Articulate the strategy for injecting cluster topology metadata into the LLM context window without exposing sensitive infrastructure details.
-
Construct Copilot prompts that generate dynamic T-SQL scripts specifically tailored to query
sys.dm_hadr_database_replica_statesand build remediation commands. - Enforce deterministic outcomes in AI-generated runbooks by providing strict scaffolding and requiring step-by-step validation checks.
- Diagnose suspended replication states dynamically, moving away from static wiki pages to on-the-fly, environment-specific script generation.
-
Validate AI-generated HA/DR commands (like
ALTER DATABASE ... SET HADR RESUME) in a sandbox environment before emergency execution.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) or Azure Data Studio with GitHub Copilot extension installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise). |
| SQL Server Engine | SQL Server 2019/2022 (Developer Edition) configured with a simulated or real Availability Group. |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com. |
| OS | Windows Server 2022 (Cluster environment preferred) or standard Windows 10/11 sandbox. |
🇪🇺 European Compliance Callout (GDPR): Server names, database names, and IP addresses in your cluster topology might contain client-specific prefixes (e.g., FR_ClientName_SQL01). When asking the AI to generate a runbook, alias these names (e.g., PrimaryNode, SecondaryNode) to prevent proprietary infrastructure mapping from entering the AI's training telemetry, even with Enterprise protections enabled.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Emergency failovers on SOX-in-scope databases must be meticulously documented. Instruct the AI to explicitly include steps in your runbook for capturing pre-failover LSNs (Log Sequence Numbers) and ticketing system updates. AI scripts that dynamically execute RESUME or FAILOVER commands must be heavily scrutinized for least-privilege execution.
Welcome back, everyone. Take your seats. Today, we are dealing with the most stressful part of our job: the 2 AM page.
Raise your hand if you've been woken up because an Always On Availability Group database suspended replication. You log in, blurry-eyed. You know you need to query the DMVs, but you can't remember the exact join between sys.dm_hadr_database_replica_states and sys.availability_replicas. You spend 15 critical minutes searching your company's disorganized Confluence wiki for the diagnostic script, while the transaction log drive on the primary replica rapidly fills up.
This is a failure of tooling, not a failure of knowledge.
Today, we change the paradigm. We will use Copilot as our HA/DR Commander. Instead of hunting for static scripts, we will teach the AI our cluster topology and ask it to dynamically generate the exact diagnostic queries and remediation commands we need, instantly. Furthermore, we will have it write the step-by-step markdown runbook for the junior DBAs on shift.
Here is the deterministic architectural flow for today's lab:
[ 2:00 AM: PagerDuty Alert ] -> AG Suspended
|
v
[ VS Code Workspace ] -> Contains #file:cluster_topology.json (Obfuscated)
|
v
[ Prompt 1: Diagnostics ] -> AI writes T-SQL to find suspended DBs and generate RESUME commands.
|
v
[ Prompt 2: Runbook ] -> AI generates a Markdown failover guide specific to this cluster.
|
v
[ DBA Executes ] -> Issue resolved in 3 minutes instead of 30.
🎙️ Field Note
Early in my career, during a catastrophic SAN failure, we had to fail over our primary AG. The "Official Runbook" on our SharePoint site was three years out of date. It referenced servers that had been decommissioned, and the manual T-SQL commands threw syntax errors. We lost two hours of RTO just trying to figure out the current state of the cluster. Static runbooks rot. Dynamic, AI-generated runbooks—fed with real-time metadata—are the future of incident response.
To get the AI to generate accurate infrastructure scripts, we must feed it the topology without exposing sensitive data.
| Feature / Syntax | DBA Practical Use Case |
|---|---|
| Topology Injection | #file:topology.json |
| Dynamic SQL Prompting | Generate dynamic T-SQL that prints the ALTER commands... |
| Formatting Directives | Format as a Markdown incident runbook |
📂 dba-hadr-response
┣ 📂 config
┃ ┗ 📜 cluster_topology.json
┣ 📂 scripts
┃ ┗ 📜 Get-SuspendedAGs.sql
┗ 📂 runbooks
┗ 📜 Emergency_Failover_Guide.md
Open your IDEs. Let's simulate a suspended AG scenario and generate our response tools.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Generate AG Diagnostics & Runbook | Sandbox Workspace | 90 Minutes | 1 Topology JSON, 1 Dynamic T-SQL Script, 1 Markdown Runbook |
Create a file named cluster_topology.json in your workspace. We use this so the AI knows our environment.
{
"AvailabilityGroupName": "AG_Finance_Prod",
"PrimaryReplica": "SQL-NODE-01",
"SecondaryReplicas": ["SQL-NODE-02", "SQL-NODE-DR"],
"ListenerName": "LST-FIN-PROD",
"Databases": ["LedgerDB", "PayrollDB"]
}Open Copilot Chat. We need a script that finds the problem and writes the fix.
Prompt:
@workspace Read #file:cluster_topology.json. I need a T-SQL script compatible with SQL Server 2025 to troubleshoot this Availability Group. Write a query against sys.dm_hadr_database_replica_states joined to sys.availability_databases_cluster to find any databases that are in a 'SUSPENDED' state. The script must dynamically generate and PRINT the exact ALTER DATABASE [DBName] SET HADR RESUME commands so I can easily copy and execute them.
🔍 Pause & Inspect Checkpoint Look at the generated T-SQL before you save it:
- Did it correctly join on
group_database_idordatabase_id? - Did it check
suspend_reason_descso you know why it suspended? - Always verify dynamic SQL strings for correct spacing and quote escaping.
Now, let's create the documentation for the NOC team.
Prompt:
@workspace Based on #file:cluster_topology.json, write a comprehensive Markdown runbook for performing a manual emergency failover of this AG. Include prerequisites, the exact T-SQL commands to execute on the target secondary replica to force failover (allowing data loss if necessary), and post-failover validation queries using DMVs. Use bold warnings for the data loss steps.
⚡ Lab Micro-Challenge
Finished early? Ask Copilot to write a PowerShell script using the dbatools module (e.g., Resume-DbaAgDatabase) that achieves the exact same result as your T-SQL script in Step 2, complete with Try/Catch logging.
Watch out for these issues when generating HA/DR scripts with AI:
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Generated script targets sys.databases instead of AG DMVs | Prompt was too vague about HA/DR context. | Explicitly list sys.dm_hadr_database_replica_states in your prompt instructions. |
| Runbook suggests clustering GUI instead of T-SQL | AI defaults to SSMS GUI tutorials for beginners. | Add constraint: "Strictly use T-SQL commands; do not reference WSFC or SSMS GUI." |
| Dynamic SQL lacks schema brackets | AI wrote ALTER DATABASE LedgerDB instead of [LedgerDB]. |
Prompt: "Ensure all database names in the dynamic SQL are wrapped in QUOTENAME()." |
| Failover command is for standard mirror, not AG | AI confused Database Mirroring with Always On. | Verify the runbook uses ALTER AVAILABILITY GROUP ... FAILOVER. |
| Topology data leakage | You pasted real IP addresses into the chat. | Always use sanitized cluster_topology.json files with aliased names. |
Ensure you have completed and understood the following before logging off:
- I understand how to inject infrastructure metadata (JSON/YAML) into Copilot to ground its responses.
- I successfully generated a T-SQL script that produces dynamic
RESUMEcommands. - I verified the join conditions between the HA/DR dynamic management views in the AI's output.
- I generated a customized Markdown runbook tailored specifically to my simulated cluster topology.
- I recognize the danger of executing AI-generated HA/DR commands without peer review during a live outage.
Tomorrow, we dive into Security Auditing & Automated RBAC Generation. We will use Copilot to parse complex Active Directory group structures and automatically generate idempotent T-SQL Role-Based Access Control (RBAC) scripts to enforce the Principle of Least Privilege across your entire database fleet.
Homework: Review the concepts of Contained Database Users and Server Roles. Have a sandbox database ready with a few dummy schemas created.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-5. Understanding of SQL Server security principals, Server/Database roles, and SQL Server Audit features.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Transform grueling, multi-day compliance audits (SOC2, HIPAA, ISO) into 15-minute, AI-assisted reviews by dynamically generating security discovery reports, automated least-privilege remediation scripts, and robust SQL Server Audit specifications.
By the end of this session, you will be able to:
- Articulate the difference between static security checklists and dynamic, AI-generated privilege remediation workflows.
-
Construct Copilot prompts that securely query system catalogs to identify orphaned users,
sysadminsprawl, and excessivedb_ownermappings. - Enforce the Principle of Least Privilege (PoLP) by instructing the AI to generate custom database roles and migration scripts.
- Diagnose compliance gaps by reviewing AI-generated output for inherited or nested permissions that standard DMVs often obscure.
- Validate future security boundaries by deploying an AI-generated SQL Server Audit Specification to track all elevated privilege assignments in real-time.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) or Azure Data Studio with GitHub Copilot extension installed. |
| Subscriptions | Active GitHub Copilot License (Business or Enterprise). |
| SQL Server Engine | SQL Server 2019/2022 (Developer/Enterprise) or Azure SQL Database (Note: Audit specs differ slightly in Azure SQL). |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com. |
| OS | Windows 10/11 / Server 2022 (for local file system audit logging). |
🇪🇺 European Compliance Callout (GDPR): Security audit scripts frequently pull sys.server_principals, which may contain employee names (e.g., DOMAIN\Jane.Doe). Ensure that when passing output back into the AI for remediation planning, you obfuscate these names. Your goal is to pass the roles and object types, not the human identities, into the LLM context.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Auditors for SOX and SOC2 require proof that access is regularly reviewed and right-sized. Do not just run the AI-generated remediation scripts blindly. The output of Copilot's "Discovery Phase" must be saved as a read-only artifact (CSV/TXT) and attached to your ticketing system as proof of the audit state before the automated remediation is applied.
Welcome back, everyone. Take your seats. Today, we are dealing with the auditors.
Raise your hand if you look forward to a SOC2 or ISO 27001 audit. Exactly. Nobody does. The process usually involves spending three days running separate scripts to find orphaned users, checking who has sysadmin, mapping out db_owner group members, and pasting it all into a massive Excel spreadsheet for compliance officers.
Why are we doing this manually? SQL Server's security catalog is highly structured. AI thrives on structured data. We can use Copilot as our Security Sentinel to not only find the vulnerabilities but to write the exact T-SQL required to lock the doors we left open.
However, be warned about probabilistic AI behavior: if you tell an AI to "fix orphaned users," its first instinct is often to write a DROP USER command. In the enterprise, dropping a user without checking dependencies breaks legacy applications. We must command the AI to report and remediate gracefully, not destroy.
Here is the deterministic architectural flow for today's automated audit:
[ SQL Server Security Catalog ]
|
v
[ AI Discovery Script Execution ] -> Queries sys.server_principals / sys.database_principals
|
v
[ Raw Audit Output ] -> (Human DBA Reviews Findings)
|
v
[ AI Remediation Prompt ] -> "Move these users to a custom db_executor role."
|
v
[ SQL Server Audit Engine ] <== AI writes Server Audit Spec to track future changes
|
v
[ Windows Security Log / File ] -> Real-time tracking of Privilege Escalation
🎙️ Field Note
I once took over an environment for a major retailer. To prep for an audit, I used a quick script and found 45 accounts mapped todb_owner. I told a junior DBA to clean it up. He used an AI prompt that just dropped and recreated the users withdb_datareader. It turned out one of those "users" was the service account for the payment gateway, which neededEXECUTEpermissions. We took down e-commerce for 20 minutes. Never let AI apply security remediations directly to production without a staging test. Least privilege means giving them exactly what they need, which requires application context the AI doesn't inherently possess.
To turn multi-day audits into 15-minute tasks, you must chain your prompts logically. Discovery first, Remediation second, Monitoring third.
| Feature / Marker | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| System Rules | Use strictly standard catalog views |
Prevents the AI from using deprecated system tables (like sysusers or syslogins). |
| Output Formatting | Format the output as dynamic SQL |
Forces Copilot to not just give you the list, but write the script that fixes the list. |
| Security Context | Implement the Principle of Least Privilege |
Guides the LLM to default to GRANT EXECUTE and GRANT SELECT rather than db_owner. |
Set up your folder for today's lab to keep your audit artifacts organized:
📂 dba-security-audit
┣ 📂 01_discovery
┃ ┗ 📜 Find_Elevated_Access.sql
┣ 📂 02_remediation
┃ ┗ 📜 Build_Custom_Roles.sql
┗ 📂 03_monitoring
┗ 📜 Setup_Audit_Spec.sql
Open your IDEs. Let's run a security audit on your local instance.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| End-to-End Compliance Audit | Sandbox Instance | 90 Minutes | 1 Discovery Script, 1 Remediation Script, 1 Audit Spec |
Open Copilot Chat. We need to build our diagnostic tool.
Prompt:
Write a comprehensive T-SQL script compatible with SQL Server 2025 to identify security risks. The script must return three separate result sets: 1) All logins holding the 'sysadmin' server role (excluding standard MS/System accounts). 2) All users in the current database mapped to the 'db_owner' role (excluding dbo). 3) All orphaned users in the current database (users without corresponding server logins). Use standard sys.server_principals and sys.database_principals catalog views.
Before you hit execute, let's look at the damage.
🔍 Pause & Inspect Checkpoint Look closely at the code the AI generated:
- Did it use
sp_change_users_loginfor the orphaned users? That's deprecated! If it did, correct the AI and force it to usesys.database_principalsjoined withsys.server_principals. - Did it properly filter out
sa,NT SERVICE\, andNT AUTHORITY\accounts to reduce noise?
Now that you have your list of offenders, let's build the fix. Assuming you found users that shouldn't be db_owner, let's prompt the AI to build a custom least-privilege role.
Prompt:
Write a T-SQL remediation script that creates a new custom database role named 'db_executor_reader'. Grant this role SELECT permissions on all schemas, and EXECUTE permissions on all stored procedures. Then, write dynamic SQL that will loop through all non-system users currently in 'db_owner', drop them from 'db_owner', and add them to this new 'db_executor_reader' role.
Execute this in a sandbox. You just right-sized your database security in 30 seconds.
Fixing it is only half the battle. Auditing requires tracking future changes.
Prompt:
Write a T-SQL script to create a SQL Server Audit named 'PrivilegeEscalationAudit' that writes to the file system at 'C:\SQLAudit\'. Then, create a Server Audit Specification that tracks the SERVER_ROLE_MEMBER_CHANGE_GROUP. Enable both the audit and the specification.
⚡ Lab Micro-Challenge
Finished early? Ask Copilot to write a PowerShell script that parses the .sqlaudit files generated in Step 3, looks for anyone granting sysadmin, and formats the output into a Slack/Teams webhook alert.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Deprecated System Procs | AI relies on outdated internet tutorials for orphaned users. | explicitly ban sp_change_users_login in your prompt and require ALTER USER ... WITH LOGIN. |
| "Cannot alter the role 'db_owner', because it does not exist..." | AI hallucinated dynamic SQL syntax for role member removal. | Ensure the AI uses the modern ALTER ROLE [role] DROP MEMBER [user] syntax (SQL 2012+). |
| Audit fails to start | SQL Server Service account lacks NTFS permissions to C:\SQLAudit\. |
Pre-create the directory and grant Full Control to the SQL Engine service account. |
| Remediation breaks applications | Moving a user from db_owner to db_executor_reader missed INSERT/UPDATE rights. |
Always ask the AI to map the new custom role to specific application needs, not just generic read/exec. |
| Azure SQL Compatibility | Server Audits write to Blob Storage or Log Analytics in Azure, not the C: drive. | Tell Copilot: "Modify the Audit script for Azure SQL Database targeting an Azure Storage URL." |
Ensure you have completed and understood the following before logging off today:
- I understand how to use AI to rapidly query system catalogs for compliance reporting.
- I successfully forced Copilot to avoid deprecated T-SQL commands during discovery.
- I generated an automated remediation script that applies the Principle of Least Privilege without relying on destructive
DROPcommands. - I deployed a SQL Server Audit Specification to proactively track privilege escalation.
- I realize that AI-generated security remediations must always be reviewed alongside application context to prevent downtime.
Tomorrow, we are moving into the realm of data engineering. In Day 7: AI-Assisted ETL & Data Pipeline Refactoring, we will use Copilot to analyze clunky, row-by-row SSIS packages and legacy bulk inserts, transforming them into highly parallelized, set-based Azure Data Factory pipelines or modern T-SQL OPENROWSET architectures.
Homework: Try to locate a slow-running ETL script or a data import process that takes longer than it should. Obfuscate any proprietary data in the script.
Author: Ahsan Kabir, Principal Consultant IT, Country Formation Inc.
Instructor Profile: Senior SQL Server DBA & Microsoft AI Integration Specialist
Audience: Experienced SQL Server DBAs (US & Europe)
Prerequisites: Completion of Days 1-6. Familiarity with cloud migrations, Git branch management, and basic command-line interface (CLI) operations.
Estimated Completion Time: 4 Hours (Theory: 90 mins | Focus & Workflow: 60 mins | Lab: 90 mins)
Module Objective: Reframe your career trajectory by shifting from manual, line-by-line migration scripting to orchestrating autonomous AI agents that analyze, refactor, and package hundreds of database objects for cloud deployment.
By the end of this session, you will be able to:
- Articulate the architectural difference between a single-prompt AI interaction and a multi-agent orchestrated pipeline.
- Construct systemic prompts capable of bulk-processing dozens of SQL scripts simultaneously for schema refactoring.
-
Enforce modern cloud data standards by instructing agents to automatically convert deprecated types (e.g.,
TEXTtoVARCHAR(MAX)) across an entire codebase. - Diagnose dependency mapping failures by analyzing the phased deployment manifests generated by your AI agents.
- Validate AI-generated Pull Requests (PRs) by assuming the role of the "Auditor Agent" prior to deployment approval.
| Requirement | Specification |
|---|---|
| IDE | VS Code (latest) with GitHub Copilot, Copilot Chat, and GitHub Pull Requests extensions. |
| Subscriptions | Active GitHub Copilot Business or Enterprise license (required for regulated environments). |
| SQL Server Engine | Azure SQL Database or AWS RDS (Target Cloud Environment). |
| Network / Endpoints | Outbound HTTPS (TCP 443) to api.github.com and your Git repository. |
| OS | Windows 10/11, Server 2022, or macOS/Linux. |
🇪🇺 European Compliance Callout (GDPR): When migrating hundreds of legacy scripts, it is highly likely that developer comments, old sample INSERT statements, or view definitions contain hardcoded PII. Before unleashing an agent on a folder of 50 scripts, run a local RegEx scrubbing tool to strip out sample data to ensure PII does not leak into the LLM context window.
🇺🇸 US Compliance Callout (SOC2 / HIPAA / SOX): Autonomous code generation requires extreme separation of duties. The AI acts as the "Developer." You must act as the "Reviewer." Under no circumstances should a multi-agent pipeline have the authorization to automatically merge and execute its own deployment manifest against a production or SOX-in-scope database.
Welcome back, everyone. Take your seats. Today is the day we graduate from mechanics to factory managers.
Raise your hand if you’ve ever been handed a "Lift and Shift" cloud migration project. You are given 500 legacy stored procedures, tables, and views. You spend three weeks manually mapping foreign key dependencies so they deploy in the right order. You spend another two weeks doing Find/Replace for deprecated data types. It is soul-crushing, error-prone work.
This is where the 10x Orchestrator mentality comes in. You don't write the scripts. You write the instructions for the agents that write the scripts. We use a multi-agent workflow where one AI prompt feeds into the next.
Here is the deterministic flow of a multi-agent migration:
[ Legacy SQL Folder (50 Files) ] -> In VS Code Workspace
|
v
[ Agent 1: The Mapper ] -> "Analyze these files. Output a JSON array of FK dependencies."
|
v
[ Agent 2: The Refactorer ] -> "Read Agent 1's output. Refactor TEXT to VARCHAR(MAX). Add TRY/CATCH."
|
v
[ Agent 3: The Packager ] -> "Generate a YAML deployment manifest in dependency order."
|
v
[ Human DBA: The Auditor ] -> Reviews the Pull Request -> Approves for Deployment
🎙️ Field Note
We had a massive migration to Azure SQL last year. The legacy system heavily used cross-database queries (which Azure SQL DB doesn't support natively without Elastic Queries). Instead of finding them manually, we built an AI agent to scan 2,000 files, flag every three-part naming convention, and rewrite them to use external tables. What would have taken four months took three days. But remember: the AI generated a circular dependency on two views that broke the initial deployment. The AI does the heavy lifting; you do the dependency validation.
To process files in bulk, you must use systemic prompts that establish strict operational boundaries.
| Feature / Marker | Syntax / Usage | DBA Practical Use Case |
|---|---|---|
| Workspace Context | @workspace |
Essential for large migrations. Forces the AI to look at the entire folder of legacy scripts, not just the active file. |
| Terminal/CLI Agent | @terminal |
Ask Copilot to write the Git commands to branch, stage, commit, and push the bulk-refactored code. |
| Systemic Rule | Output a phased deployment manifest |
Forces the AI to logically order the scripts (Tables first, Views second, Procs third). |
📂 dba-cloud-migration
┣ 📂 01_legacy_source
┃ ┣ 📜 table_customers.sql
┃ ┣ 📜 proc_get_orders.sql
┃ ┗ 📜 ... (48 more files)
┣ 📂 02_refactored_target
┣ 📂 03_deployment
┃ ┗ 📜 manifest.yml
Open your IDEs. Let's execute a bulk migration refactoring.
Lab Overview Table
| Goal | Target Instance | Duration | Deliverables |
|---|---|---|---|
| Bulk Refactor & Package | Azure SQL Sandbox | 90 Minutes | 50 Refactored Scripts, 1 Manifest, 1 Pull Request |
If you don't have 50 scripts handy, create a folder named 01_legacy_source and generate 3-4 dummy .sql files that contain deprecated TEXT data types, missing TRY/CATCH blocks, and a few foreign keys.
Open Copilot Chat. We are going to orchestrate a massive pipeline in one prompt.
Prompt:
@workspace Analyze all SQL scripts in the /01_legacy_source/ folder. Act as a multi-agent migration pipeline. Step 1: Map all foreign key dependencies between the tables. Step 2: Refactor all instances of the deprecated 'TEXT' and 'NTEXT' data types to 'VARCHAR(MAX)' and 'NVARCHAR(MAX)'. Step 3: Wrap all stored procedure bodies in standard TRY/CATCH blocks. Step 4: Output the refactored code to the /02_refactored_target/ folder. Step 5: Generate a deployment manifest file detailing the exact execution order (Tables first, Views second, Procs last) to avoid dependency errors.
Before you let it run wild, evaluate its plan.
🔍 Pause & Inspect Checkpoint Look at the proposed deployment order in the manifest.
- Did it catch the foreign key between
OrdersandCustomersand putCustomersfirst? - Did it correctly identify
TEXTtypes in variable declarations as well as table definitions? - If the AI tries to write all 50 files into the chat window, tell it to save them directly to the file system using Python or bash scripts if Copilot workspace edits stall.
Now, use the @terminal agent to package this up.
Prompt:
@terminal Write the git commands to create a new branch named 'migration-refactor', stage the /02_refactored_target/ folder, commit with a descriptive message, and push to origin.
Go to GitHub/Azure DevOps. Open the Pull Request. Put on your Architect hat. Do not merge blindly. Review the AI's diffs. Did it break any legacy business logic when adding the TRY/CATCH blocks?
⚡ Lab Micro-Challenge
Finished early? Write a prompt that commands Copilot to generate a dbatools PowerShell script that will read the AI-generated deployment manifest and sequentially execute the 50 refactored scripts against your sandbox instance.
| Issue / Error Message | Root Cause | Field-Tested Fix |
|---|---|---|
| Context Window Exceeded | 50 scripts contained 100,000 lines of code. | Batch the migration. Prompt the AI to process Tables first, clear context, then process Procs. |
| Circular Dependency Error | Manifest deployed a view before the underlying table. | Ask Copilot to explicitly draw a dependency graph before generating the manifest. |
| TRY/CATCH swallowed errors | AI generated empty CATCH blocks. | Enforce a strict rule: All CATCH blocks must use THROW or log to an error table.
|
| Git Push fails | Terminal command generated by AI assumes wrong remote name. | Verify your Git remotes using git remote -v before executing AI terminal commands. |
Ensure you have completed and understood the following before logging off today:
- I understand the mindset shift from writing manual code to orchestrating AI agents.
- I successfully used systemic prompts to bulk-refactor deprecated data types across multiple files.
- I generated a logically ordered deployment manifest that respects foreign key dependencies.
- I used the terminal agent to automate the Git branching and commit process.
- I successfully performed an "Auditor" review of the AI's Pull Request.
These seven labs are designed for real-world workshops, internal corporate training, or blog series. They are production-grade exercises that map directly to the 30-day roadmap.
Secure environment setup, .copilotignore configuration, and first high-value completions.
Capture actual execution plans, feed them to Copilot, and generate precise index recommendations.
Convert nested cursors and procedural logic into clean set-based T-SQL with full Auditor review.
Intent-based scripting, error handling, credential safety, and HTML reporting.
Live DMV diagnosis, automated resume commands, and customized failover runbooks.
Elevated permission discovery, custom role creation, and SQL Server Audit specifications.
Writer + Auditor agent pipelines for bulk modernization and safe deployment manifests.
- Agent Mode: GitHub Copilot mode that can propose and (with human approval) execute multi-step tool calls and code changes.
- Ask Mode: Conversational mode for questions and explanations without autonomous tool execution.
- Context Window: The maximum number of tokens an LLM can process in a single request.
-
DMV (Dynamic Management View): SQL Server system views that expose runtime state (e.g.,
sys.dm_exec_requests). - Hallucination: When an AI model generates plausible but incorrect or non-existent code, objects, or explanations.
- HAMS: Hierarchical and Auditable Multi-Agent Systems – separating Writer and Auditor agents.
- Inline Completion: Ghost-text suggestions that appear as you type in the editor.
- RAG (Retrieval-Augmented Generation): Providing external context (schema DDL, files) so the LLM answers accurately for your environment.
- SARGable: Search Argument Able – predicates that allow the optimizer to use index seeks.
- System Prompt / Rules File: Pre-conditioning the AI with enterprise coding standards before generation.
- Token: Approximate unit of text processed by LLMs (roughly ¾ of an English word).
- VECTOR / Vector Search: SQL Server 2025 native support for storing and searching embeddings.
-
.copilotignore: File that excludes paths from Copilot context and telemetry (analogous to
.gitignore).
Schema & Query Generation
Referencing #file:schema_context.sql, write a high-performance query joining Orders and Customers that calculates total spend per customer in 2026.Rewrite this query to be SARGable so SQL Server can perform an Index Seek on OrderDate.
Performance & Plans
Analyze this execution plan XML. Identify the top 3 bottlenecks and suggest exact T-SQL CREATE INDEX statements.Identify the victim process, winning process, locked resources, and provide the T-SQL indexing script to prevent this deadlock.
Administration & Automation
Write a dynamic T-SQL script using sys.dm_db_index_physical_stats that loops through user tables, checks fragmentation, and rebuilds only indexes with > 30% fragmentation and > 1000 pages.Write a PowerShell script using dbatools to query a list of SQL Servers from a CMS, check for databases without a full backup in the last 24 hours, and output a styled HTML report.
Security & Compliance
Write a T-SQL script to audit all users with sysadmin, db_owner, or CONTROL SERVER rights across all databases, excluding system accounts. Generate a remediation script that creates least-privilege custom roles.Write a T-SQL script that checks non-synchronized AG databases and generates the dynamic ALTER DATABASE ... SET HADR RESUME commands.
Multi-Agent & Migration
Act as Writer Agent: modernize this legacy procedure to set-based T-SQL with TRY/CATCH. Then act as Auditor Agent: reject anything that violates our standards (no cursors, explicit schema, no dynamic SQL without sp_executesql).@workspace Analyze all SQL scripts in /legacy. Map foreign-key dependencies, convert TEXT/NTEXT to VARCHAR(MAX)/NVARCHAR(MAX), add TRY/CATCH, and output a phased deployment manifest.
Vector / SQL Server 2025
Using the table that contains a VECTOR(1536) column, write a cosine similarity search that returns the top 5 most similar rows. Target SQL Server 2025 only.
- Official GitHub Copilot documentation and enterprise governance guides
https://docs.github.com/en/copilot - Microsoft Learn: SQL Server Dynamic Management Views, Always On Availability Groups, Query Store
https://learn.microsoft.com/en-us/sql/ - SQL Server 2025 Vector Search and AI features (Microsoft documentation)
- dbatools community module documentation
https://docs.dbatools.io/ - SQL Server execution plan analysis and SARGability guidance from the SQL Server community (MVPs, blogs)
- Enterprise compliance considerations for AI tools under GDPR, HIPAA, SOX, and SOC 2
Agent Mode, Ask Mode, Always On Availability Groups, .copilotignore, Compatibility Level 170, Context Window, Deadlock, dbatools, Execution Plan, GDPR, Hallucination, HAMS, HIPAA, Index Maintenance, Least Privilege, MCP, Multi-Agent, Parameter Sniffing, Query Store, RAG, SARGable, Schema Context, SOX, SQL Server 2025, SSMS 22, TempDB, Vector Search, Verification Pipeline
Ahsan Kabir is a Principal Consultant IT at Country Formation Inc. and a Senior SQL Server DBA with deep expertise in Microsoft AI integrations, GitHub Copilot, and modern database tooling. He has worked hands-on across United States and European enterprises, mentoring teams through the transition from traditional DBA practices to AI-augmented data platform architecture. This book captures the practical, safety-first training framework he uses with clients facing real change control, regulatory pressure, and 2 a.m. accountability.
End of Book
AI‐Powered SQL Server DBA: Automating Your Work with GitHub Copilot (Fourth Edition)
© 2026 Ahsan Kabir, Country Formation Inc.
Always test AI-generated code in non-production environments before deployment.