0

我有以下查询,它是标量变量函数的一部分,但是尝试运行查询时得到了相同的结果,因此问题似乎出在串联和/或变量的使用中。

DECLARE @useCompTitle BIT
SET @useCompTitle = (SELECT z.useComplianceTitle FROM dbo.tblConfiguration z WHERE z.id = 1)
DECLARE @Output as VARCHAR(MAX) = '';
DECLARE @ReturnValue as VARCHAR(MAX)='';
SELECT @Output = @Output + 
                '<tr><td style="vertical-align:top">' + 
                p.ProcessNumber + 
                '</td><td>' + 
                (IIF(@useCompTitle = 0, p.Process, p.title)) + 
                '</td><td style="vertical-align:top">' + 
                CASE p.recordStatus 
                    WHEN 1 THEN N'Active' 
                    WHEN 2 THEN N'Inactive' 
                END  + 
                '</td></tr>'
FROM dbo.tblProcess p
CROSS JOIN dbo.Security_Compliance_Record_List(1, 0, 0) AS p1
INNER JOIN dbo.tblERLinkedRecords l ON p.id = l.recID
WHERE l.eventID = 1172 
AND l.linkType = 'C' 
AND p.id = p1.id 
AND p.recordStatus < 3
ORDER BY p.ProcessNumber
PRINT @OutputThe result should return multiple values in @Output but I am only getting the last record in the set.

我也尝试了一个具有相同结果的 CASE 语句。如果我用一个简单的字段名称替换 IIF(或 CASE),我会得到正确数量的值。如果将 IIF 替换为简单的字段值(例如标题),则 p.RecordStatus 的 CASE 可以正常工作。我们在许多存储过程中使用@useCompTitle 过程,但这是第一次在串联查询中。

4

3 回答 3

0

使用IIFCONCAT

演示

declare @mytable table (processnumber int, recordstatus smallint,process varchar(20), title varchar(20))

insert into @mytable 
values 
(1,1,'Proc1','Title1'),
(2,2,'Proc2','Title2'),
(3,1,'Proc3','Title3'),
(4,2,'Proc4','Title4'),
(5,1,'Proc5','Title5')



DECLARE @useCompTitle BIT
SET @useCompTitle = 1
DECLARE @Output as VARCHAR(MAX) = '';
DECLARE @ReturnValue as VARCHAR(MAX)='';

SELECT @Output = concat(@Output, 
                '<tr><td style="vertical-align:top">', 
                p.ProcessNumber,
                '</td><td>', 
                IIF(@useCompTitle = 0, p.Process, p.title),     -- as per @useCompTitle will always display Title when 1
                '</td><td style="vertical-align:top">',
                IIF( p.recordStatus  = 1,'Active','Inactive' ),
                '</td></tr>') 
from @mytable p


print  @Output
于 2018-04-30T04:34:30.907 回答
0

感谢所有的投入。经过更多测试后,我发现问题出在 ORDER BY 中,并且是一个已知问题。那是一篇很棒的文章。我通过根据建议将功能更改为解决问题,并且一切正常。

  CREATE FUNCTION [dbo].[CR_Events_Linked_Compliance] 

(@parameter1 INT,@parameter2 BIT = 0,@recID INT,@useCompTitle BIT)返回 VARCHAR(MAX) 开始声明 @Output 作为 VARCHAR(MAX) = '';将@ReturnValue 声明为 VARCHAR(MAX)=''; SELECT @Output = (SELECT '' + p.ProcessNumber + '' + IIF(@useCompTitle = 0, p.Process, p.title) + '' + IIF(p.recordStatus = 1, 'Active', 'Inactive' ) + '' FROM dbo.tblProcess p CROSS JOIN dbo.Security_Compliance_Record_List(@parameter1, @parameter2, 0) AS p1 INNER JOIN dbo.tblERLinkedRecords l ON p.id = l.recID WHERE l.eventID = @recID AND l.linkType = 'C' AND p.id = p1.id AND p.recordStatus < 3 ORDER BY p.ProcessNumber FOR XML PATH(''), TYPE ).value('.','varchar(max)') IF @Output =''进程状态' + @Output + '' RETURN @ReturnValue END

于 2018-04-30T06:12:26.517 回答
-1

如果查询返回一行,则 SQL Server 将该值存储在变量中。但是,如果有多行,那真的没有意义。一个变量保存一个值,但有多个值要存储在其中。它可能会出错,但微软选择让它简单地存储最后一个值。它也可以存储第一个,但这不是他们决定的。一般来说,这不是值得依赖的好行为,因为从语义角度来看它是不合理的。

事实上,我认为这就是你被赶上的地方。虽然可以认为查询是表和行的 for 循环,但实际上并非如此。这是对一组元组(行)的一系列操作。从概念上讲,结果是一次“到达”的一组行。没有行的执行顺序(就像刚刚存在的数组的执行顺序一样)。因此,这没有任何意义。

现在,你想要达到目标本身就是合理的。您需要一个字符串,该字符串通过本质上连接返回多行的查询结果来构建。想象一下,您有一个更简单的查询,您只想总结一些数字而不是连接字符串。您只需使用SUM()聚合,可能带有GROUP BY子句。结果可以存储到变量中。由于聚合会使结果集中只有一行,因此您不必担心哪一行保存了该值。字符串聚合的工作方式相同。除了...SQL Server 没有STRING_SUM()操作直到 SQL Server 2017。也就是说,在所有版本的 SQL Server 中仍然可以执行此操作。您可以使用 XML 技巧,也可以编写自己的自定义聚合函数(使用 .NET 语言)。有关如何执行此操作的更多信息,请参阅我需要在 SQL Server 中编写类似 group_concat 的查询。

希望这足以让你继续前进!

于 2018-04-30T04:01:59.987 回答