3

关于子句,我有一个类似于这个 MySQL 问题IN的案例,但适用于 SQL Server。

具体来说,我正在构建一个可执行的 SQL 字符串,其中可能包含一个非常长的枚举项列表,以便在IN子句中使用(IE 1000+)。

这是从标准动态列表构建过滤器的有效方法,还是应该将标准数据插入临时表,然后将JOIN其插入导出表以进行过滤操作?

如果答案不是很直截了当,我们将不胜感激每种方法的优缺点。

如果有人问过这个问题,我很抱歉。链接的 MySQL 问题相当古老。我想这是 SQL Server 的副本,但我找不到它。

4

2 回答 2

3

您忘记告诉我们您使用的是什么版本的 SQL Server。当然,对于每个新版本,我们都会获得帮助我们以更有效的方式解决问题的能力。

在 SQL Server 2005+ 中,您可以使用这样的简单表值函数来实现连接:

CREATE FUNCTION [dbo].[SplitInts]
(
   @List       VARCHAR(MAX),
   @Delimiter  CHAR(1)
)
RETURNS TABLE
AS
   RETURN ( SELECT Item FROM ( SELECT Item = x.i.value('(./text())[1]', 'int') FROM 
            ( SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>') 
              + '</i>').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)
          ) AS y WHERE Item IS NOT NULL
   );
GO

现在传入你的大名单并加入:

CREATE PROCEDURE dbo.GetData
    @List VARCHAR(MAX)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT t.col1, t.col2 --, ...
      FROM dbo.DataTable AS t
      INNER JOIN dbo.SplitInts(@List, ',') AS i
      ON t.ColumnID = i.Item;
END
GO

这不是很好(我在这里写了关于各种方法的性能的博客,在 5000 值以下几乎没有区别),但可能比临时IN (...huge list...)查询表现得更好。

在 SQL Server 2008+ 中,您可以使用表值参数。与上面类似,您可以将 DataTable 或 C# 中的任何结构传递到存储过程并执行连接。如果您使用的是 2008 或更高版本,我也可以为此添加一个示例。

于 2012-03-08T19:12:37.257 回答
1

我建议使用临时表方法,并使用一个where exists(...)子句,例如

select * from Employees e
where exists(select 1 from BigEmplCriteriaTable where criteria=e.EmployeeLoc)
于 2012-03-08T19:27:10.183 回答