{"id":4606,"date":"2025-05-08T08:32:24","date_gmt":"2025-05-08T15:32:24","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=4606"},"modified":"2025-05-08T08:34:11","modified_gmt":"2025-05-08T15:34:11","slug":"sql-analysis-dotnet-tool","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/sql-analysis-dotnet-tool\/","title":{"rendered":"Avoid T-SQL anti-patterns with the free T-SQL analysis tool"},"content":{"rendered":"<p><div class=\"alert alert-info\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Guest Post<\/strong><\/p>Erik Ejlskov Jensen is a Principal Specialist at Delegate A\/S with over 30 years of experience in .NET Data development, EF Core, and Azure SQL Database\/SQL Server. He is the author of the well-known EF Core Power Tools and is now introducing his latest tool T-SQL Analyzer in this blog post. Thanks Erik!<\/div><\/p>\n<p>T-SQL Analyzer is a free, open-source, cross platform command line tool for identifying, and reporting the presence of anti-patterns and design issues in SQL Server T-SQL scripts. As a database developer, you can catch any potential bad practices and design problems very early in the project process &#8211; this ensures a frictionless path to deployment from development and test environments to production.<\/p>\n<p>The tool evaluates your scripts with more than <a href=\"https:\/\/github.com\/ErikEJ\/SqlServer.Rules\/blob\/master\/docs\/readme.md\">140 rules<\/a> for design, naming and performance issues. The rules are created by Microsoft and the SQL Server community.<\/p>\n<p>If you already maintain your SQL scripts in a SQL Database project, use build analysis as described in the <a href=\"https:\/\/erikej.github.io\/dacfx\/codeanalysis\/sqlserver\/2024\/04\/02\/dacfx-codeanalysis.html\">blog post here.<\/a><\/p>\n<h2>Installation<\/h2>\n<p>The tool is a .NET 8 tool, and requires the .NET 8 runtime to be installed.<\/p>\n<p class=\"highlight\"><code>dotnet tool <span class=\"nb\">install<\/span> <span class=\"nt\">--global<\/span> ErikEJ.DacFX.TSQLAnalyzer.Cli\n<\/code><\/p>\n<h2>Usage<\/h2>\n<p>Once installed, you can start using the tool right away. Running the tool from the command prompt in any folder will analyze all .sql files in that folder and sub-folders<\/p>\n<p><code>tsqlanalyze<\/code><\/p>\n<p>The tool will output a summary of the rules that were violated, and the line numbers where the violations occurred.<\/p>\n<pre class=\"highlight\"><code><span class=\"k\">CREATE<\/span> <span class=\"k\">TABLE<\/span> <span class=\"p\">[<\/span><span class=\"n\">dbo<\/span><span class=\"p\">].[Demo<\/span><span class=\"n\">Table<\/span><span class=\"p\">]<\/span>\r\n<span class=\"p\">(<\/span>\r\n    <span class=\"p\">[<\/span><span class=\"n\">Id<\/span><span class=\"p\">]<\/span> <span class=\"nb\">INT<\/span> <span class=\"k\">NOT<\/span> <span class=\"k\">NULL<\/span><span class=\"p\">,<\/span> \r\n    <span class=\"p\">[<\/span><span class=\"n\">Sample<\/span><span class=\"p\">]<\/span> <span class=\"nb\">NCHAR<\/span><span class=\"p\">(<\/span><span class=\"mi\">500<\/span><span class=\"p\">)<\/span> <span class=\"k\">NOT<\/span> <span class=\"k\">NULL<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"p\">[<\/span><span class=\"n\">Data<\/span><span class=\"p\">]<\/span> <span class=\"nb\">NCHAR<\/span><span class=\"p\">(<\/span><span class=\"mi\">10<\/span><span class=\"p\">)<\/span> <span class=\"k\">NOT<\/span> <span class=\"k\">NULL<\/span>\r\n<span class=\"p\">)<\/span><\/code><\/pre>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/analyze.png\"><img decoding=\"async\" class=\"aligncenter wp-image-4610 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/analyze.png\" alt=\"analyze image\" width=\"1474\" height=\"496\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/analyze.png 1474w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/analyze-300x101.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/analyze-1024x345.png 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/analyze-768x258.png 768w\" sizes=\"(max-width: 1474px) 100vw, 1474px\" \/><\/a><\/p>\n<p>To get help on the options available in the tool, use the help feature:<\/p>\n<p><code>tsqlanalyze --help<\/code><\/p>\n<p>For example, to analyze a single file, use this syntax:<\/p>\n<p><code>tsqlanalyze -i C:\\code\\demotable.sql<\/code><\/p>\n<h2>Advanced usage<\/h2>\n<p>Let me highlight some of the more advanced options the tool supports.<\/p>\n<h3>Ignore rules<\/h3>\n<p>If you would like to ignore some of the rules, you can add a rule exclusion filter to the command line.<\/p>\n<p><code>tsqlanalyze -i C:\\code\\sproc.sql -r Rules:-SqlServer.Rules.SRD0005;-Smells.*<\/code><\/p>\n<p>This will cause the tool to ignore the SRD0005 rule and any rules in the Smells rule set.<\/p>\n<h3>Format script<\/h3>\n<p>The tool can also help you format your script, with the -f option.<\/p>\n<p><code>tsqlanalyze -i C:\\code\\sproc.sql -f<\/code><\/p>\n<p>The available formatting options can be customized in an <a href=\"https:\/\/github.com\/madskristensen\/SqlFormatter?tab=readme-ov-file#editorconfig-support\">.editorconfig file<\/a>.<\/p>\n<h3>And much more&#8230;<\/h3>\n<p>There are multiple other advanced options, including the ability to analyze a .dacpac file or a live database, output analysis results as xml, integration with SQL Server management Studio and Visual Studio.<\/p>\n<p>You can also bring your own rules and use the analysis engine from your own code! Read more the the <a href=\"https:\/\/github.com\/ErikEJ\/SqlServer.Rules\/tree\/master\/tools\/SqlAnalyzerCli\">readme file<\/a> for the tool.<\/p>\n<h2>VS Code MCP Server (preview)<\/h2>\n<p dir=\"auto\">You can use the tool to ask GitHub Copilot analyze your SQL Server CREATE scripts in Visual Studio Code, just add the built-in <a href=\"https:\/\/code.visualstudio.com\/docs\/copilot\/chat\/mcp-servers\" rel=\"nofollow\">MCP server<\/a>\u00a0to your VS Code configuration.<\/p>\n<p dir=\"auto\">Paste this link in you browser to prompt VS Code to configure the MCP Server.<\/p>\n<p dir=\"auto\">vscode:mcp\/install?%7B%22name%22%3A%22tsqlanalyzer%22%2C%22command%22%3A%22tsqlanalyze%22%2C%22args%22%3A%5B%22-mcp%22%5D%7D<\/p>\n<p dir=\"auto\">or install manually:<\/p>\n<pre>{\r\n    <span class=\"pl-ent\">\"servers\"<\/span>: {\r\n        <span class=\"pl-ent\">\"tsqlanalyzer\"<\/span>: {\r\n            <span class=\"pl-ent\">\"type\"<\/span>: <span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>stdio<span class=\"pl-pds\">\"<\/span><\/span>,\r\n            <span class=\"pl-ent\">\"command\"<\/span>: <span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>tsqlanalyze<span class=\"pl-pds\">\"<\/span><\/span>,\r\n            <span class=\"pl-ent\">\"args\"<\/span>: [\r\n                <span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>-mcp<span class=\"pl-pds\">\"<\/span><\/span>\r\n            ]\r\n        }\r\n    }\r\n}<\/pre>\n<p dir=\"auto\">You can now ask GitHub Copilot in Agent mode to help you check your SQL script for bad practices.<\/p>\n<p dir=\"auto\">You will get the results presented by Copilot, who will even offer to fix the script for you!<\/p>\n<p dir=\"auto\"><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/image.png\"><img decoding=\"async\" class=\"aligncenter wp-image-4613 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/image.png\" alt=\"image image\" width=\"582\" height=\"829\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/image.png 582w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2025\/05\/image-211x300.png 211w\" sizes=\"(max-width: 582px) 100vw, 582px\" \/><\/a><\/p>\n<h2 dir=\"auto\">Parting words<\/h2>\n<p>I hope you will find this free tool to be a useful addition to your developer toolbox. Please reach out via the <a href=\"https:\/\/github.com\/ErikEJ\/SqlServer.Rules\/issues\">GitHub repository<\/a> with and feedback and ideas you may have, and happy SQL coding.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>T-SQL Analyzer is a free, open-source, cross platform command line tool for identifying, and reporting the presence of anti-patterns and design issues in SQL Server T-SQL scripts. As a database developer, you can catch any potential bad practices and design problems very early in the project process &#8211; this ensures a frictionless path to deployment [&hellip;]<\/p>\n","protected":false},"author":7621,"featured_media":4610,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[444,1,619,625],"tags":[666],"class_list":["post-4606","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-azure-sql","category-t-sql","category-vs-code","tag-best-pratices"],"acf":[],"blog_post_summary":"<p>T-SQL Analyzer is a free, open-source, cross platform command line tool for identifying, and reporting the presence of anti-patterns and design issues in SQL Server T-SQL scripts. As a database developer, you can catch any potential bad practices and design problems very early in the project process &#8211; this ensures a frictionless path to deployment [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/4606","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/users\/7621"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=4606"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/4606\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/4610"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=4606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=4606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=4606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}