将索引添加到临时 table 会导致单行结果集
Adding index to temporary table results in single row result set
在 sp_executesql 中,select 语句用于将变量本身和临时 table.
中的列的值连接起来
当我将索引应用于此临时 table 并在上述 select 语句中使用排序时,这会产生奇怪的结果。
只有当临时 table 的行数大于 50 行时才会发生这种情况。
我不喜欢粘贴大代码示例,但我无法进一步减少它。
如果@maxjob >= 8,则生成的@htmllog 包含 67 个字符。这是意想不到的结果。
如果@maxjob < 8,则生成的@htmllog 始终包含超过 67 个字符。这是预期的结果。
此外,
当我从 #acl_log table 中删除索引 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
聚合字符串连接的行为未定义,因为根据 Microsoft 在 this connect item:
中的评论,它依赖于计划
Even without ORDER BY, we do not guarantee that @var = @var +
will produce the concatenated value for any statement
that affects multiple rows. The right-hand side of the expression can
be evaluated either once or multiple times during query execution and
the behavior as I said is plan dependent.
一种解决方法是 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
在 sp_executesql 中,select 语句用于将变量本身和临时 table.
中的列的值连接起来当我将索引应用于此临时 table 并在上述 select 语句中使用排序时,这会产生奇怪的结果。
只有当临时 table 的行数大于 50 行时才会发生这种情况。
我不喜欢粘贴大代码示例,但我无法进一步减少它。
如果@maxjob >= 8,则生成的@htmllog 包含 67 个字符。这是意想不到的结果。
如果@maxjob < 8,则生成的@htmllog 始终包含超过 67 个字符。这是预期的结果。
此外,
当我从 #acl_log table 中删除索引 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
聚合字符串连接的行为未定义,因为根据 Microsoft 在 this connect item:
中的评论,它依赖于计划Even without ORDER BY, we do not guarantee that @var = @var + will produce the concatenated value for any statement that affects multiple rows. The right-hand side of the expression can be evaluated either once or multiple times during query execution and the behavior as I said is plan dependent.
一种解决方法是 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