Как определить запрос запроса имеет подзапрос в нем? - PullRequest
3 голосов
/ 31 мая 2019

Разработка проекта C # для обучения SQL и предоставление различных упражнений на основе обучения по каждой теме. Одним из упражнений является написание запроса с использованием подзапроса. который необходимо оценить, использовал ли пользователь / реализовал подзапрос в Стандарте запроса.

Q: Напишите SQL-запрос для отображения SalesOrderID, LineTotal, среднего LineTotal из таблицы Sales.SalesOrderDetail с использованием подзапроса

Select SalesOrderID,LineTotal [LineTotal],
(Select AVG(LineTotal) from Sales.SalesOrderDetail) as [AverageLineTotal] 
from Sales.SalesOrderDetail 

[AverageLineTotal] это подзапрос.

Можем ли мы идентифицировать это любым способом ?? как план выполнения или SP, чтобы идентифицировать его, имеет подзапрос в операторе

Есть ли способ идентифицировать его по планам выполнения ??

Ответы [ 2 ]

0 голосов
/ 31 мая 2019

Анализ специальных сценариев по своей сути сложен из-за множества конструкций и опций T-SQL. При этом надежным методом для целевых вариантов использования является синтаксический анализ сценариев с Microsoft.SqlServer.TransactSql.ScriptDom .

Ниже приведен пример сценария PowerShell, который использует сборку DOM сценария из официального пакета Microsoft Dacfx NuGet , загружая и распаковывая его при необходимости.

# Add TSqlScript DOM assembly reference, downloading and extracting to the specified location if needed
$scriptDomAssemblyPath = "C:\Temp\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
$scriptDomNuGetUrl = "https://www.nuget.org/api/v2/package/Microsoft.SqlServer.DacFx.x64/150.4384.2"
if(![System.IO.File]::Exists($scriptDomAssemblyPath)) {
    $response = Invoke-WebRequest -Uri $scriptDomNuGetUrl
    if ($response.StatusCode -ne 200) {
        throw "Unable to download Microsoft.SqlServer.TransactSql.ScriptDom NuGet package: $response.StatusCode : $response.StatusDescription"
    }
    $tempZipFilePath = "$([System.IO.Path]::GetTempPath())/$([System.IO.Path]::GetRandomFileName()).zip"
    [System.IO.File]::WriteAllBytes($tempZipFilePath, $response.Content)
    $response.BaseResponse.Dispose()
    $tempUnzipFolderPath = "$([System.IO.Path]::GetTempPath())/$([System.IO.Path]::GetRandomFileName())"
    Expand-Archive -Path $tempZipFilePath -DestinationPath $tempUnzipFolderPath
    $tempZipFilePath | Remove-Item
    Move-Item "$tempUnzipFolderPath\lib\net46\Microsoft.SqlServer.TransactSql.ScriptDom.dll" "$scriptDomAssemblyPath"
    $tempUnzipFolderPath | Remove-Item -Recurse
}
Add-Type -Path $scriptDomAssemblyPath

# script to be parsed
$scriptText = @"
Select SalesOrderID,LineTotal [LineTotal],
(Select AVG(LineTotal) from Sales.SalesOrderDetail) as [AverageLineTotal] 
from Sales.SalesOrderDetail
"@

#parse script
$parser = New-Object Microsoft.SqlServer.TransactSql.ScriptDom.TSql150Parser($true)
$parseErrors = New-Object System.Collections.Generic.List[Microsoft.SqlServer.TransactSql.ScriptDom.ParseError]
$scriptReader = New-Object System.IO.StringReader($scriptText)
$script = $parser.Parse($scriptReader, [ref]$parseErrors)
if($parseErrors.Count -gt 0) {
    throw "$($parseErrors.Count) parsing errors"
}

# sanity check for expected SELECT query
if(($script.Batches.Count -ne 1) -or ($script.Batches[0].Statements.Count -ne 1) -or ($script.Batches[0].Statements[0].QueryExpression -eq $null)) {
    throw "script with single SELECT statement expected"
}

# find scalar subquery expression in select list
$subQueryFound = $false
foreach($selectElement in $script.Batches[0].Statements[0].QueryExpression.SelectElements) {
    if($selectElement.Expression.ToString() -eq "Microsoft.SqlServer.TransactSql.ScriptDom.ScalarSubquery") {
        $subQueryFound = $true
        break
    }
}

# show if subquery was used
if($subQueryFound) {
    Write-Host "A subquery is used"
}
else {
    Write-Host "A subquery is not used"
}
0 голосов
/ 31 мая 2019

Если это проект c #, вы можете проанализировать запрос с помощью регулярного выражения, чтобы найти, содержит ли запрос (выберите {любой другой текст}).

public static void Main()
{
    var sql = @"Select SalesOrderID,LineTotal [LineTotal],(Select AVG(LineTotal) from Sales.SalesOrderDetail) as [AverageLineTotal] from Sales.SalesOrderDetail";
    Console.WriteLine(DoesSqlContainSubquery(sql));
}

public bool DoesSqlContainSubquery(string sql)
{
    var regexTest = new Regex(@"\( *Select .*\)", RegexOptions.IgnoreCase);
    var containsSubquery = regexTest.IsMatch(sql);
    return containsSubquery;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...