【问题标题】:Variable in query doesn't work查询中的变量不起作用
【发布时间】:2016-11-16 01:44:54
【问题描述】:

我遇到了一些 SQL 查询问题,我正在创建一个变量:

 declare @material varchar(500)
 declare @typ varchar(200)
 declare @strsql varchar(max)
 set @typ = 'papier'

 select @material = (SELECT + rtrim(ltrim([grupa])) + ','
                     FROM [test].[dbo].[GT] 
                     WHERE (typ = @typ) FOR XML PATH(''))
 set @material =  left(@material, len(@material)-1)
 set @material  = replace(@material, ',' ,''',''')
 set @material = '''' + @material + ''''

 select @material

变量的输出是:

'test','test2'

这是我主要代码的一小部分:

 SELECT
     Number,
     isnull(sum((case 
                    when [Group] in ('test','test2') 
                       then isnull(cast([Quantity] as int), 0) 
                 end)), 0) as other
 FROM
     [dbo].[test-table]

这是正确的,但是当我尝试这样做时:

 SELECT
     Number,
     isnull(sum((case 
                    when [Group] in (@material) 
                       then isnull(cast([Quantity] as int), 0) 
                  end)), 0) as other
 FROM
     [dbo].[test-table]

输出错误(不同)。谁能告诉我为什么?有点像。

【问题讨论】:

  • Output is wrong, can anyone tell me, why? 输出是什么?
  • 输出与第一个查询不同 - 它应该是相同的
  • 您正在尝试将逗号分隔的 VARCHAR 列表放入变量中。如果没有动态 SQL,您将无法在 SQL 中执行此操作。请参阅此原始帖子:stackoverflow.com/questions/2944511/…
  • 您必须声明 SqlParameter NVARCHAR(MAX),然后您必须使用 EXEC sp_exeutesql SQL、SqlParameter。您可以通过链接了解更多信息 msdn.microsoft.com/en-us/library/ms188001.aspx
  • 您可以将搜索值放入临时表或表变量中 - 然后执行 select ... where [group] in (select field form #tempTable)

标签: sql sql-server


【解决方案1】:

有点像,但又不一样。你想要得到的是:in ('test','test2'),你得到的是:in (''test','test2'')

您必须动态构建查询的其余部分,例如:

DECLARE @SQL NVARCHAR(MAX) = 'SELECT
 Number
 ,isnull(sum((case when [Group] in ('+ @material + ') 
 then isnull(cast([Quantity] as int),0) end)),0) as other
 from [dbo].[test-table]'

EXEC sys.sp_executesql @SQL

如果您说输出错误,最好显示实际输出以及错误的原因。在大多数情况下,说“输出与第一个查询相比不同 - 它应该相同”是不够的。

编辑:

如果你不想使用动态 sql(这很有意义),你可以这样做(实际上比动态更具可读性):

SELECT      Number
,           ISNULL(SUM(data),0) as other
FROM        (
                SELECT  Number
                ,       CASE WHEN [Group] IN (SELECT grupa FROM [dbo].[GT] WHERE typ = @typ) 
                                THEN ISNULL(CAST([Quantity] AS INT), 0) 
                         END data
                FROM    [dbo].[test-table] 
            ) TT
GROUP BY    Number

不过,我在这里对您的目标、架构和数据做出了很多假设。没有更多信息,这可能是我能做的最好的了......(可能需要做一些性能调整,但这是本质)

【讨论】:

  • 我之前已经测试过了,当我像你一样做它时它可以工作,但是我有大量的子查询,所以我有点不能声明这么多变量(我的意思是我可以但它毫无意义),有吗有机会更正我的代码。例如,如果变量的输出是 test','test2 而不是 'test','test2' 那么它会正常工作吗?
  • 当我按照您在编辑中添加的方式执行此操作时,它会显示错误:无法对包含聚合或子查询的表达式执行聚合函数。此 SUM 的原因
  • @Pro100 请参阅进一步的编辑。显然,必须定义 group by。我加了一个,但是因为你用大小写求和,可能更多的属性必须添加到group by。再想一想,这可能是一个不同的问题......我会回到那个
  • 在我评论之前我已经分组了,所以这不是问题。
  • @Pro100,更新答案
【解决方案2】:

尝试使用函数来拆分字符串:

CREATE FUNCTION [dbo].[FN_SplitString](@String nvarchar(4000), @Delimiter char(1))
RETURNS @Results TABLE (Items nvarchar(4000))
AS
    BEGIN
    IF @String IS NULL RETURN
    IF LTRIM(RTRIM(@String)) = '' RETURN
    DECLARE @INDEX INT
    DECLARE @SLICE nvarchar(4000)
    SELECT @INDEX = 1
    WHILE @INDEX !=0
        BEGIN   
            SELECT @INDEX = CHARINDEX(@Delimiter,@STRING)

        IF @INDEX !=0
            SELECT @SLICE = LEFT(@STRING,@INDEX - 1)
        ELSE
            SELECT @SLICE = @STRING
        INSERT INTO @Results(Items) VALUES(@SLICE)
        SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX)
        IF LEN(@STRING) = 0 BREAK
END
RETURN

然后这样使用:

SELECT
 Number
 ,isnull(sum((case when [Group] in (SELECT  Items, FROM FN_SplitString(@material,',')) 
 then isnull(cast([Quantity] as int),0) end)),0) as other
 from [dbo].[test-table]

【讨论】:

  • 我强烈建议不要使用这个分离器。这里根本不需要循环。这里还有许多其他选项,它们的性能将优于 nibbler 样式的循环拆分器。 sqlperformance.com/2012/07/t-sql-queries/split-strings
  • 感谢 Sean Lange 的性能说明。这是解决方案之一,但正如您所说,还有许多其他选择。
【解决方案3】:

SQL Server 中,如果您将comma 分隔列表作为IN Clause 中的变量传递给T-SQL,它不会给出error,但您甚至不会得到预期的结果。

有两种解决方案可以解决这个问题:

  1. 使用动态查询
  2. 使用拆分功能

【讨论】:

    猜你喜欢
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多