Базовый тип данных SQL - PullRequest
       0

Базовый тип данных SQL

0 голосов
/ 26 октября 2019

Мне нужно получить список всех хранимых процедур и функций, в которых вместо определенного пользователем типа данных используется базовый тип данных SQL Server. Есть ли способ извлечь эти данные из SQL Server?

1 Ответ

1 голос
/ 27 октября 2019

Объявления параметров со спецификациями системного типа данных можно идентифицировать с помощью этого запроса представления каталога:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...