Это минимальный пример кода, используемого в контексте генерации динамических c SQL, следовательно, замен. Ожидаемый результат состоит в том, что все данные представлены в результате и в одной текстовой переменной (объединение нескольких строк).
Очевидное решение этого примера - использовать найденные нами «хаки», но это код используется в существующем коде в нескольких местах (в производственном коде), так что это НЕОБХОДИМОЕ решение, чтобы решить путем «исправления» кода, в противном случае у нас было бы решение, см. взломы / исправления. Надежда состоит в том, что есть настройка на уровне сервера, которая помогает этой проблеме или другим, у которых были подобные проблемы с их результатами и результатами.
DROP TABLE IF EXISTS #Table1,#Table2,#Table3
GO
SELECT ManagerID,EmployeeID
INTO #Table1
FROM (VALUES(1,1),(1,2)) A(ManagerID,EmployeeID)
SELECT ManagerID,[Name]
INTO #Table2
FROM (VALUES(1,'EvilDoer' )) A(ManagerID,[Name])
SELECT EmployeeID,[Name]
INTO #Table3
FROM (VALUES(1,'SlaveA' ),(2,'SlaveB' )) A(EmployeeID,[Name])
/*
Tested on SQL Server 14.0.3257.3 on both compatibility level 110 and 140;
The issue here is, likely?; the execution plan.
If you have the two replaces then the plan is "Incorrect", i.e. ComputeScalar is before sort => 1 row (Last)
If you remove the one or two of the replaces then the plan is "Correct", i.e. ComputeScalar is after sort => All rows
Alternative 1, usage of TOP(X) yields a "Correct" result
Alternative 2, Removal of the "ORDER BY"-clause yields a "Correct" result
*/
DECLARE @SQL varchar(max) = ''
SELECT --TOP 1000000
@SQL = @SQL + '
EXECUTE sp_MyProc
@Manager = '''+REPLACE(T2.[Name],CHAR(39),CHAR(39) + CHAR(39))+'''
,@Worker = '''+REPLACE(T3.[Name],CHAR(39),CHAR(39) + CHAR(39))+'''
'
FROM #Table1 T1
INNER JOIN #Table2 T2
ON T1.ManagerID = T2.ManagerID
INNER JOIN #Table3 T3
ON T1.EmployeeID = T3.EmployeeID
ORDER BY T2.[Name], T3.[Name]
SELECT @SQL /* EXECUTE (@SQL)*/
Неверный результат (пропущенные данные):
EXECUTE sp_MyProc
@Manager = 'EvilDoer'
,@Worker = 'SlaveB'
План выполнения с неверным результатом:
Ожидаемый результат (все данные):
EXECUTE sp_MyProc
@Manager = 'EvilDoer'
,@Worker = 'SlaveA'
EXECUTE sp_MyProc
@Manager = 'EvilDoer'
,@Worker = 'SlaveB'
План выполнения с TOP (N):