有没有办法在select语句中为多列使用变量?

时间:2013-03-28 14:02:35

标签: sql sql-server

我有一个动态的SQL。运行大约需要4分钟。如果我改为使其成为静态SQL,则需要大约20秒。

相当多,这两个查询是:

@myVar = 1
SELECT *
FROM TABLE
WHERE someColumn = myVar

VS

@myQuery = '
SELECT *
FROM TABLE
WHERE someColumn = myVar'

EXEC sp_executesql @myQuery,
    N'@myVar INT,
    @myVar

我的真实查询要复杂得多。查看统计信息,动态统计信息的读取次数超过10x。我想让这个查询静态来解决这个问题。它的动态的全部原因是我的插入和选择是使用变量。

我有类似的东西:

@someVar1 = "column1, column2, column3"
@someVar2 = "column4, column5, column6"

然后会有

@myQuery = 'INSERT INTO '+ @someVar1 + 
           'SELECT ' + @someVar2 + ' FROM ....'

我有什么方法可以做类似的事情:

INSERT INTO @myVar1
SELECT @myVar2
FROM
...

我不知道如何修复此查询,并且迫切需要修复。

编辑我做了一些更改。我忘了提到动态的东西也在插入语句中。这就是我刚刚醒来后发帖的情况。

1 个答案:

答案 0 :(得分:1)

你在追逐独角兽。 SQL Server不允许您在非动态查询中将@var替换为column1, column2。语法只是不支持您希望它做什么(不是它会改善情况)。

所以你需要以其他方式解决这个“问题”。我发现很难相信同一查询的动态版本会导致读取中的10倍位移。如果是这种情况(并且您不仅仅夸大效果 - 请显示证据),几乎可以肯定是由于参数嗅探,其中缓存的(静态)查询使用了导致一个计划形状的参数,并且该计划对于具有不同查询文本或不同参数或两者的其他(动态)查询,shape不是最佳的。您可以通过在运行时强制RECOMPILE并确保查询文本每次都相同(包括空格,大小写等)来在一定程度上抵消这种情况。

SET @myQuery = N'INSERT dbo.DestinationTable(' 
  + @DestinationColumns + ')
  SELECT ' + @SourceColumns + '
  FROM dbo.SourceTable
  WHERE someColumn = @myVar OPTION (RECOMPILE);';

但我也不相信这是你的问题。我认为这可能比实际观察更多的感知/恐惧。

正如我在评论中提到的,如果您要构建许多不同的动态SQL语句,您应该考虑启用optimize for ad hoc workloads设置,这将阻止您的计划缓存因您赢得的计划而变得臃肿'再次使用。

SQL Sentry Plan Explorer的免费版本将允许您在大约半秒内轻松地完成您的计划,甚至可以让您将它们上传到我们可以查看它们的位置。这不会让我们剖析实际的查询文本,但是它会显示查询本身的计划存在差异 - 如果查询是动态构造还是不构建,那就不重要了,只是它不同。 免责声明:我为SQL Sentry工作。