在sp_executesql中,select语句用于连接变量本身和临时表中列的值。
当我将索引应用于此临时表并在上述select语句中使用排序时,这会产生奇怪的结果。
仅当临时表的行数大于50行时才会发生这种情况。
我不喜欢粘贴大代码示例,但我无法进一步减少它。
如果@maxjob> = 8,则生成的@htmllog包含67个字符。这是一个意想不到的结果。
如果@maxjob< 8,然后生成的@htmllog总是包含超过67个字符。这是预期的结果。
此外,
当我从#acl_log表中删除索引idx_key时,当@maxjob> = 8时问题就消失了。 要么 当我从@executesql_sql中删除'order by [key] asc'时,问题也会消失。
为什么?
declare @logtable as varchar(max)
set @logtable = '#acl_log'
if (OBJECT_ID('[tempdb]..#acl_log')) is not null
drop table #acl_log
create table #acl_log(
[key] int identity,
[message] nvarchar(max) not null,
index idx_key ([key])
)
declare @job as int
declare @maxjob as int
set @job = 0
set @maxjob = 8
while (@job < @maxjob + 1)
begin
insert into #acl_log([message])
values
('Internet Explorer is currently running without add-ons')
,('All Internet Explorer add-ons, such as ActiveX controls or toolbars, are turned off. Some webpages might not display correctly.')
,('To continue to your home page, click the Home button.')
,('To browse using add-ons, close Internet Explorer and then start it again.')
,('Forward Arrow Check for the latest Windows updates. ')
,('Question Icon How do browser add-ons affect my browsing experience? ')
set @job = @job + 1
end
declare @executesql_sql as nvarchar(max)
declare @executesql_param as nvarchar(max)
declare @htmllog as varchar(max)
set @executesql_sql = '
set @htmllog = ''''
select @htmllog = @htmllog + [message]
from ' + @logtable + '
order by [key] asc'
set @executesql_param = '@htmllog varchar(max) output'
exec master..sp_executesql @executesql_sql, @executesql_param, @htmllog = @htmllog output
select len(@htmllog), @htmllog
答案 0 :(得分:3)
聚合字符串连接的行为未定义,因为它根据Microsoft在this connect item中的注释而依赖于计划:
即使没有ORDER BY,我们也不保证@var = @var + 将为任何语句生成连接值 这会影响多行。表达式的右侧可以 在查询执行期间进行一次或多次评估 我所说的行为取决于计划。
一种解决方法是FOR XML
子句:
DECLARE @logtable AS varchar(MAX);
SET @logtable = '#acl_log';
IF (OBJECT_ID('[tempdb]..#acl_log')) IS NOT NULL
DROP TABLE #acl_log;
CREATE TABLE #acl_log(
[key] int IDENTITY,
[message] nvarchar(max) not null,
INDEX idx_key ([key])
);
DECLARE @job as int;
DECLARE @maxjob as int;
SET @job = 0;
SET @maxjob = 8;
WHILE (@job < @maxjob + 1)
BEGIN
INSERT INTO #acl_log([message])
VALUES
('Internet Explorer is currently running without add-ons')
,('All Internet Explorer add-ons, such as ActiveX controls or toolbars, are turned off. Some webpages might not display correctly.')
,('To continue to your home page, click the Home button.')
,('To browse using add-ons, close Internet Explorer and then start it again.')
,('Forward Arrow Check for the latest Windows updates. ')
,('Question Icon How do browser add-ons affect my browsing experience? ');
SET @job = @job + 1;
END
DECLARE @executesql_sql AS nvarchar(MAX);
DECLARE @executesql_param AS nvarchar(MAX);
DECLARE @htmllog AS varchar(max);
SET @executesql_sql = '
SET @htmllog = (SELECT [message]
FROM ' + @logtable + '
ORDER BY [key]
FOR XML PATH(''''), TYPE).value(''.'', ''varchar(MAX)'');';
set @executesql_param = '@htmllog varchar(max) OUTPUT';
EXEC master..sp_executesql @executesql_sql, @executesql_param, @htmllog = @htmllog output;
SELECT LEN(@htmllog), @htmllog;
GO