【问题标题】:"Array parameter" TSQL“数组参数”SQL
【发布时间】:2009-07-01 16:25:46
【问题描述】:

我有一个包含通话数据记录的表格,每个通话记录一个通话数据,其中一个字段是我们在查询数据库时使用的 CallerId。

我们使用下面的 TSQL 来模拟一个数组参数,这是要走的路还是要走的路?

ALTER PROCEDURE [dbo].[spStudio_Get_Smdr]
    @beginTime INT,
    @endTime INT,
    @subscribers VARCHAR(MAX) = NULL,
    @exchanges VARCHAR(MAX) = '1:',
    @beginDateValue int, 
    @endDateValue int
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @exch TABLE(Item Varchar(50))   
    INSERT INTO @exch
    SELECT Item FROM [SplitDelimitedVarChar] (@exchanges, '|') ORDER BY Item


    DECLARE @subs TABLE(Item Varchar(19))
    INSERT INTO @subs
    SELECT Item FROM [SplitDelimitedVarChar] (@subscribers, '|') ORDER BY Item

    SELECT
      ,[Level]
      ,[Timestamp]
      ,[EndYear]
      ,[EndDate]
      ,[EndTime]
      ,[CallingNumber]
      ,[DialledNumber]
      ..more fields between
      ,[DateValue]
      ,[TimeValue]
  FROM [SmdrFormat] AS S
    WHERE
        (S.[DateValue] BETWEEN @beginDateValue AND @endDateValue)
    AND
        (S.[TimeValue] BETWEEN @beginTime AND @endTime)
    AND
        EXISTS(SELECT [Item] FROM @exch WHERE [Item] = S.[Level])
    AND
        (@subscribers IS NULL OR (EXISTS(SELECT [Item] FROM @subs WHERE [Item] = S.[CallingNumber]
                                            OR [Item] = S.[DialledNumber])))

END

我正在使用一个表变量来存储我从中拆分出来的临时表和 |我们作为参数传入的分隔字符串。 SplitDelimitedVarChar SQL 函数分割 VarChar 并返回一个 Table 变量。时间和日期值存储为整数。

WHERE 子句中使用的所有字段都已编入索引。

当分隔字符串参数很短时这很好用,但当它变大时(最多数百个由 | 分隔的字符串)执行查询需要相当长的时间。

因为我显然不是 SQL 专家,所以我觉得可能有人可以告诉我我是否真的在 SQL 方面很糟糕,或者只是有些地方出错了?任何建议表示赞赏

提前致谢 约翰

【问题讨论】:

    标签: sql-server-2005 tsql


    【解决方案1】:

    看看 Erland Sommarskog 的 Arrays and Lists in SQL Server

    【讨论】:

    • 是的,马上解决了我的问题......绝对在我的候选名单上,以供将来参考。
    【解决方案2】:

    2008年,使用表值参数

    【讨论】:

    【解决方案3】:

    在这里我尝试重构它:

    ALTER PROCEDURE [dbo].[spStudio_Get_Smdr]
        @beginTime INT,
        @endTime INT,
        @subscribers VARCHAR(MAX) = NULL,
        @exchanges VARCHAR(MAX) = '1:',
        @beginDateValue int, 
        @endDateValue int
    AS
    SET NOCOUNT ON;
    
    
    IF @subscribers IS NULL
    BEGIN
        SELECT
            [Level]
                ,[Timestamp]
                ,[EndYear]
                ,[EndDate]
                ,[EndTime]
                ,[CallingNumber]
                ,[DialledNumber]
                --..more fields between
                ,[DateValue]
                ,[TimeValue]
            FROM [SmdrFormat] AS S
            WHERE (S.[DateValue] BETWEEN @beginDateValue AND @endDateValue)
                AND (S.[TimeValue] BETWEEN @beginTime AND @endTime)
                AND EXISTS (SELECT [Item] FROM [SplitDelimitedVarChar] (@exchanges, '|') WHERE S.[Level]=[Item])
    
    END
    ELSE
    BEGIN
    
        SELECT
            [Level]
                ,[Timestamp]
                ,[EndYear]
                ,[EndDate]
                ,[EndTime]
                ,[CallingNumber]
                ,[DialledNumber]
                --..more fields between
                ,[DateValue]
                ,[TimeValue]
            FROM [SmdrFormat] AS S
            WHERE (S.[DateValue] BETWEEN @beginDateValue AND @endDateValue)
                AND (S.[TimeValue] BETWEEN @beginTime AND @endTime)
                AND EXISTS (SELECT [Item] FROM [SplitDelimitedVarChar] (@exchanges, '|') WHERE S.[Level]=[Item])
                AND EXISTS (SELECT [Item] FROM [SplitDelimitedVarChar] (@subscribers, '|') WHERE S.[Level]=[Item] OR S.[DialledNumber]=u2.[Item])
    END
    
    RETURN 0
    GO
    

    另外,请确保您的拆分功能是最快的,see my code here

    【讨论】:

      【解决方案4】:

      请参考this article,了解几个关于如何将大量数据传递给存储过程的详细示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-08
        • 2023-03-29
        • 2010-10-05
        • 1970-01-01
        • 2016-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多