Какой API в Microsoft Tsql Scriptdom позволит мне получать / сохранять ВСЕ ссылки на таблицы из сценария SQL?
Вот документ MS, на который я ссылаюсь: https://docs.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
Мне нужен вывод:Table1Table2
Эта последняя часть не обязательно важна, но только для контекста. Я пытаюсь расширить функциональность проекта TSQLLint с открытым исходным кодом, и это даст мне возможность проверять очень активные имена таблиц в нашей компании, которые использует разработчик. без намека NOLOCK.
1 ответ
Вы можете идентифицировать все NamedTableReference
фрагменты в скрипте с использованием шаблона посетителя. ФрагментSchemaObject.BaseIdentifier.Value
- имя таблицы, на которую указывает ссылка.
Ниже приведен пример PowerShell, производный от 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
}
Выход:
Found NamedTableReference at line 1, column 15. Table name: Table1.
Found NamedTableReference at line 1, column 33. Table name: Table2.
В 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"