Объявления параметров со спецификациями системного типа данных можно идентифицировать с помощью этого запроса представления каталога:
SELECT
QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + N'.' + QUOTENAME(o.name) AS object_name
, o.type_desc
, p.name
FROM sys.objects AS o
JOIN sys.parameters AS p ON o.object_id = p.object_id
WHERE system_type_id = user_type_id;
Для идентификации объявлений переменных с типами системы потребуется анализ базового кода T-SQL. Один из способов сделать это - использовать библиотеку DOM T-SQL Script (Microsoft.SqlServer.TransactSql.ScriptDom.dll), которая является частью прикладной платформы уровня данных Microsoft SQL Server (DacFx). Библиотека доступна как часть этого пакета NuGet .
Ниже приведены примеры сценариев PowerShell, которые можно настроить по мере необходимости. Основной сценарий (Find-SystemDataTypeDeclarations.ps1) загружает пакет NuGet, анализирует код для существующих объектов, используя TSqlParser , а затем идентифицирует SqlDataTypeReference
фрагменты, используя шаблон посетителя. с пользовательским классом посетителей (определенным в отдельном файле сценария SqlDataTypeReference.ps1).
Сценарий класса посетителя PowerShell находится в отдельном файле сценария, поскольку необходимо загрузить сборку до того, как ее можно будет скомпилировать (он происходит из TSqlConcreteFragmentVisitor
, определенного в DLL). Сохраните оба сценария PowerShell в одной папке с указанными именами файлов и выполните указанную ниже команду после ваших настроек.
powershell -File "Find-SystemDataTypeDeclarations.ps1"
SqlDataTypeReference.ps1 сценарий:
# visitor for SqlDataTypeReference fragments
class SqlDataTypeReferenceVisitor: Microsoft.SqlServer.TransactSql.ScriptDom.TSqlConcreteFragmentVisitor {
[void]Visit ([Microsoft.SqlServer.TransactSql.ScriptDom.SqlDataTypeReference] $fragment) {
Write-Host "`tSystem type $($fragment.SqlDataTypeOption) variable declaration found at line $($fragment.StartLine), column $($fragment.StartColumn)"
}
}
Find-SystemDataTypeDeclarations. Скрипт ps1:
# Add type from Microsoft.SqlServer.TransactSql.ScriptDom.dll assembly
Function Add-TSqlScriptDomType() {
$dacFxNuGetUrl = "https://www.nuget.org/api/v2/package/Microsoft.SqlServer.DacFx.x64"
$scriptDomAssemblyPath = "$PSScriptRoot\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
if(![System.IO.File]::Exists($scriptDomAssemblyPath)) {
# assembly doesn't exist in this script folder; download latest DacFx package from NuGet and extract the T-SQL Script DOM assembly here
$response = Invoke-WebRequest -Uri $dacFxNuGetUrl
if ($response.StatusCode -ne 200) {
throw "Unable to download Microsoft.SqlServer.TransactSql.ScriptDom NuGet package: $($response.StatusCode) : $($response.StatusDescription)"
}
# decompress NuGet package to temp folder
$tempZipFilePath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName() + ".zip")
[System.IO.File]::WriteAllBytes($tempZipFilePath, $response.Content)
$response.BaseResponse.Dispose()
$tempUnzipFolderPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
Expand-Archive -Path $tempZipFilePath -DestinationPath $tempUnzipFolderPath
$tempZipFilePath | Remove-Item
# copy Microsoft.SqlServer.TransactSql.ScriptDom.dll assembly and remove temp files
Copy-Item "$tempUnzipFolderPath\lib\net*\Microsoft.SqlServer.TransactSql.ScriptDom.dll" $scriptDomAssemblyPath
$tempUnzipFolderPath | Remove-Item -Recurse
}
# load assembly for use in this PowerShell session
Add-Type -Path $scriptDomAssemblyPath
}
# find system type declarations in specified script
Function Find-SystemDataTypeDeclarations($script) {
$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)
$fragment = $parser.Parse($stringReader, [ref]$parseErrors)
if($parseErrors.Count -gt 0) {
throw "$($parseErrors.Count) parsing errors: $(($parseErrors | ConvertTo-Json))"
}
$visitor = [SqlDataTypeReferenceVisitor]::new()
$fragment.Accept($visitor)
}
# ############
# ### MAIN ###
# ############
$connectionString = "Data Source=.;Initial Catalog=AdventureWorks2014;Integrated Security=SSPI"
try {
# load T-SQL script DOM assembly
Add-TSqlScriptDomType
# dot source visitor class definition
. ".\SqlDataTypeReferenceVisitor.ps1"
$query = @"
SELECT
QUOTENAME(OBJECT_SCHEMA_NAME(sm.object_id)) + '.' + QUOTENAME(OBJECT_NAME(sm.object_id)) AS object_name
, o.type_desc
, sm.definition
FROM sys.sql_modules AS sm
JOIN sys.objects AS o ON o.object_id = sm.object_id
WHERE o.type <> 'V';
"@
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$command = New-Object System.Data.SqlClient.SqlCommand($query, $connection)
$connection.Open()
$reader = $command.ExecuteReader()
while($reader.Read()) {
Write-Host "Processing $($reader["type_desc"]) $($reader["object_name"])"
Find-SystemDataTypeDeclarations -script $reader["definition"]
}
$connection.Close()
}
catch {
throw
}
Вот пример фрагмента вывода из базы данных AdventureWorks:
Processing SQL_SCALAR_FUNCTION [dbo].[ufnGetAccountingStartDate]
System type DateTime variable declaration found at line 3, column 9
System type DateTime variable declaration found at line 6, column 20
Processing SQL_SCALAR_FUNCTION [dbo].[ufnGetAccountingEndDate]
System type DateTime variable declaration found at line 3, column 9
System type DateTime variable declaration found at line 6, column 45
Processing SQL_TABLE_VALUED_FUNCTION [dbo].[ufnGetContactInformation]
System type Int variable declaration found at line 2, column 60
System type Int variable declaration found at line 6, column 16
System type NVarChar variable declaration found at line 7, column 17
System type NVarChar variable declaration found at line 8, column 16
System type NVarChar variable declaration found at line 9, column 13
System type NVarChar variable declaration found at line 10, column 26
Processing SQL_SCALAR_FUNCTION [dbo].[ufnGetProductDealerPrice]
System type Int variable declaration found at line 4, column 61
System type DateTime variable declaration found at line 4, column 79
System type Money variable declaration found at line 5, column 9
System type Money variable declaration found at line 9, column 26
System type Money variable declaration found at line 10, column 29
System type DateTime variable declaration found at line 19, column 90