SQL脚本分析工具的实现与应用

随着数据库技术的不断发展,SQL脚本变得越来越庞大和复杂。为了更好地管理和分析这些脚本,需要一些工具来帮助理解脚本中的对象和逻辑。本文将介绍一种基于正则表达式和文本处理技巧的SQL脚本分析工具的实现方法,以及如何使用该工具进行数据库对象的搜索和依赖分析。

主要概念

为了实现SQL脚本的分析,需要获取整个数据库对象的单文件SQL脚本,然后使用正则表达式将SQL脚本分割成文本块,最后在这些文本块中搜索特定的文本字符串。

1. 获取所有SQL对象脚本

每个关系数据库管理系统(RDBMS)都提供了生成SQL删除/创建脚本的选项。首先,需要获取所有数据库对象的单个SQL脚本。或者,可以使用示例脚本,如northwind.sql。

2. 使用正则表达式获取所有DDL语句

使用以下正则表达式

\b(create|alter)\s+(unique)*\s*(nonclustered)*\s*(procedure|proc|table|trigger|view|function|index)\b\s([^=<>\s\'\(]+).([^=<>\s\'\(]+)[*\s\b\t]*

FastColoredTextBox提供了强大的正则表达式处理工具,因此使用:

var result = range.GetRangesByLines(regexStr, RegexOptions.IgnoreCase);

首先,构建了一些有用的正则表达式,并将它们收集在一个静态类中:

public static class RegexValues { public static string SqlCmdObjects = @"[\$\(([^=<>\[\]\s\']+)\)]\.\[[^=<>\s\']+\]"; public static string SqlCmdObjectsShort = @"\$\(([^=<>\[\]\s\']+)\)"; public static string DdlObjects = @"\b(create)\s+(procedure|proc|table|trigger|view|function)\b\s\[\$\(([^<>\[\]\s\']+)\)\].\[[^=<>\s\']+\]"; public static string DdlObjectsPrepared = @"\b(create)\s+(procedure|proc|table|trigger|view|function)\b\s\[([^<>\[\]\s\']+)\].\[[^=<>\s\']+\]"; public static string DdlObjects_ = @"\b(create)\s+(procedure|proc|table|trigger|view|function)\b\s\$\(([^<>\[\]\s\']+)\).\[[^=<>\s\']+]"; public static string DdlObjectsPrepared_ = @"\b(create)\s+(procedure|proc|table|trigger|view|function)\b\s([^<>\s\']+).([^=<>\s\'\(]+)[*\s\b\t]*"; public static string DdlObjectsPreparedProcViewTrigger = @"\b(create)\s+(procedure|proc|trigger|view|function)\b\s([^=<>\s\']+).([^=<>\s\'\(]+)[*\s\b\t]*"; public static string DdlObjectsPreparedWithIndex = @"\b(create)\s+(unique)*\s*(nonclustered)*\s*(procedure|proc|table|trigger|view|function|index)\b\s([^=<>\s\']+).([^=<>\s\'\(]+)[*\s\b\t]*"; public static string DdlIndexAll = @"\b(create|alter)\s+(procedure|proc|table|trigger|view|function)\b\s\[([^<>\[\]\s\']+)\].\[[^=<>\s\']+\]"; public static string Variables = @"\@([^=<>\s\'\)\(\,]+)"; public static string SqlCmdVariables = @"\:SETVAR\s+([a-zA-Z_]+)\s+([a-zA-Z_]+)"; }

SqlCmdObjects - 匹配 [$(some_var)].[obj_name] 或 [$(some_var)].[obj_schema].[obj_name]。

SqlCmdObjectsShort - 匹配 $(var)。

DdlObjects - 与SqlCmdObjects相同,但包含CREATE PROC/TABLE/VIEW/FUNC/TRIGGER语句。

DdlObjectsPrepared - 与DdlObjects相同,但移除了$(sqlcmd变量)限制。

DdlObjects_ - 与DdlObjects相同,但移除了包含[]限制。

DdlObjectsPrepared_ - 与DdlObjectsPrepared相同,但移除了包含[]限制。

DdlObjectsPreparedProcViewTrigger - 仅包含proc, views, triggers和functions的DDL语句,即仅代码对象。

DdlObjectsPreparedWithIndex - 与DdlObjectsPrepared_相同,但扩展了index语句。

DdlIndexAll - 与DdlObjectsPrepared_相同,但扩展了alter语句。

Variables - 正则表达式,用于在脚本中查找所有@变量。

SqlCmdVariables - 查找SQL CMD变量(如:SETVAR var1 val1)。

该软件的核心代码如下:

var range = Syncronized(() => fastColoredTextBox1.Selection.Clone()); range.Normalize(); range.Start = new Place(0, 0); range.End = Syncronized(() => new Place(tb.GetLineLength(tb.LinesCount - 1), tb.LinesCount - 1));

只需将SQL脚本加载到FastColoredTextBox中(感谢其作者!),然后对其所有内容应用一些正则表达式。作为输出,得到了RESULT变量,其中包含找到的范围列表。Range是一个强大的类(再次感谢FastColoredTextBox作者)。Range包含SQL脚本中找到的片段的行号和列号。只需将范围列表存储在虚拟列表框中(常见技术),并在SelectedIndexChanged上执行以下操作:

fastColoredTextBox1.Selection = range; fastColoredTextBox1.DoSelectionVisible();

通过这两行代码,可以立即导航到找到的代码片段(即DDL语句)。然后构建另一个范围列表,但不是使用正则表达式字符串,而是放置要找到的对象名称。

最后一步是在第一个范围列表中找到第二个范围列表的出现的。这是在Form1.cs的FindUsage(string regex)方法中完成的。

以上就是全部内容,其余的工作只是常见的.NET编码,将所有内容整合在一起。

以上逻辑的简要说明如下:

使用正则表达式找到所有的create/alter语句,并记住这些行号。使用正则表达式找到所有文本(对象,例如表名)的出现,并记住行号。现在将这两个数据集结合起来,找到文本行在create/alter语句行之间的位置。

结果,得到了一个简单的GUI设计器,可以:

打开一个SQL脚本或整个文件夹(脚本将合并到临时文件中,并作为单个脚本打开)

搜索所有DDL语句(CREATE/ALTER)- 列表将在左侧窗格中构建,支持完整的导航。

选择一些文本(例如,某个SQL对象名称),右键单击并选择“查找用法”- 列表将在右侧窗格中构建-这些是包含选定文本的SQL对象。

另一个好处是,不仅可以在SQL对象中搜索SQL对象的出现,还可以搜索几乎所有的代码片段、文本、注释等。

重要提示

由于这种分析SQL依赖关系的方法基于元数据信息,因此应该始终记住,正在连接两个数据集的行/。因此,有一些限制,或者更好的说法是“特性”:

假设有一个存储过程:

SQL create proc test as declare @somevar int create table #tmp( colum_we_search nvarchar( 255 ), somevar int )

如果应用正则表达式匹配"CREATE TABLE"语句,会匹配到临时表#tmp,以及CREATE PROC。然后,如果尝试搜索"COLUMN_WE_SEARCH"-它将在临时表#tmp中找到,而不是在过程test中。

这可以通过更精确的初始正则表达式来解决。对于这种情况,编写了DdlObjectsPreparedProcViewTrigger正则表达式语句(见上文)。

感兴趣的要点

想添加MSAGL支持以可视化依赖关系。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485