2009-07-01 18 views
2

Ich habe eine Tabelle mit Anrufdatensätzen eine für jeden Anruf mit Anrufdaten und eines der Felder ist die CallerId, die wir beim Abfragen der DB verwenden."Array Parameter" TSQL

Wir verwenden die folgenden TSQL, um einen Array-Parameter zu simulieren, ist dies der Weg zu gehen oder sind wir weg?

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 

Ich verwende eine Tabellenvariable, um die temporäre Tabelle zu speichern, die ich spalte und | Begrenzte Zeichenfolge, die wir als Parameter übergeben. Die SplitDelimitedVarChar-SQL-Funktion schlitzt einen VarChar und gibt eine Table-Variable zurück. Die Zeit- und Datumswerte werden als Ints gespeichert.

Alle in der WHERE-Klausel verwendeten Felder sind indiziert.

Dies funktioniert gut, wenn der Begrenzungszeichenfolgenparameter kurz ist, aber wenn er groß wird (bis zu mehreren hundert Strings, die durch | begrenzt sind), dauert es ziemlich lange, die Abfrage auszuführen.

Da ich anscheinend kein SQL-Guru bin, habe ich das Gefühl, dass es wahrscheinlich jemanden gibt, der mir sagen kann, ob ich wirklich schlecht bei SQL bin oder nur einen Teil falsch verstanden habe? Jeder Vorschlag ist willkommen

Vielen Dank im Voraus Johan

Antwort

1

2008 Verwendung Tabellenwertparameter

+0

Für SQL Server 2008 siehe http://stackoverflow.com/questions/43249/t-sql-stored-procedure-that-accepts-multiple-id-values. –

0

hier mein Versuch an Refactoring es:

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 

Auch, stellen Sie sicher, dass Ihre Split-Funktion ist die schnellste es sein kann, see my code here

0

Betrachten Sie this article für ein paar ausführliche Beispiele zum Übergeben großer Datenmengen an eine gespeicherte Prozedur.