Microsoft Tsql Scriptdom 中的哪个 API 允许我从 SQL 脚本检索/存储所有表引用?

Dat*_*ill 2 c# sql-server scriptdom

这是我引用的MS文档:https://learn.microsoft.com/en-us/dotnet/api/microsoft.sqlserver.transactsql.scriptdom ?view=sql-dacfx-140.3881.1

我已经看过好几次了,但似乎找不到在哪里可以检索 sql 脚本中每个表引用的实际名称。NamedTableReference 是我发现的最接近的东西,但它只允许您查看表的别名,而我想要实际名称。

例子:

SELECT * FROM Table1 INNER JOIN Table2 ON Table1.ID = Table2.ID
Run Code Online (Sandbox Code Playgroud)

我想要的输出为: Table1 Table2

最后一部分不一定重要,但只是为了上下文。我正在尝试扩展开源 TSQLLint 项目的功能,这将使我能够检查我们公司中开发人员正在使用的非常活跃的表名称没有 NOLOCK 提示。

Dan*_*man 6

您可以使用访问者模式NamedTableReference来识别脚本中的所有片段。该片段是引用的表名称。SchemaObject.BaseIdentifier.Value

下面是一个源自TSqlConcreteFragmentVisitor. 这可以适应您选择的 .NET 语言。

$script = @"
SELECT * FROM Table1 INNER JOIN Table2 as t2 ON Table1.ID = Table2.ID
"@

class MyVisitor: Microsoft.SqlServer.TransactSql.ScriptDom.TSqlConcreteFragmentVisitor {

    [void]Visit ([Microsoft.SqlServer.TransactSql.ScriptDom.NamedTableReference] $fragment) {
            Write-Host "Found $($fragment.GetType().Name) at line $($fragment.StartLine), column $($fragment.StartColumn). Table name: $($fragment.SchemaObject.BaseIdentifier.Value)"
    }

}

# ############
# ### MAIN ###
# ############

try {

    $parser = New-Object Microsoft.SqlServer.TransactSql.ScriptDom.TSql150Parser($true)
    $parseErrors = New-Object System.Collections.Generic.List[Microsoft.SqlServer.TransactSql.ScriptDom.ParseError]
    $stringReader = New-Object System.IO.StringReader($script)

    $frament = $parser.Parse($stringReader, [ref]$parseErrors)
    if($parseErrors.Count -gt 0) {
        throw "$($parseErrors.Count) parsing errors: $(($parseErrors | ConvertTo-Json))"
    }

    $visitor = [MyVisitor]::new()

    $frament.Accept($visitor)

}
catch {
    throw
}
Run Code Online (Sandbox Code Playgroud)

输出:

Found NamedTableReference at line 1, column 15. Table name: Table1.
Found NamedTableReference at line 1, column 33. Table name: Table2.
Run Code Online (Sandbox Code Playgroud)

在 PowerShell 中,必须首先使用 Add-Type 将定义基类型的外部程序集加载到应用程序域中,以便可以编译具有派生类的脚本。这可以通过一个包装脚本来完成,该脚本对实际脚本进行点源处理,如下所示:

# example wrapper script to load script DOM assembly and execute the visitor script
Add-Type -Path "C:\DacFxAssemblies\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
. "C:\Scripts\Find-NamedTableReferences.ps1"
Run Code Online (Sandbox Code Playgroud)