2010-12-07 18 views
0

Ich möchte eine Stored Procedure erstellen, die mindestens 2 erforderliche Parameter hat, aber auch mit 2,3,4,5 ... und so weiter Parametern aufgerufen werden kann. Der Grund: Ich habe mehrere Tabellen, die Schlüssel-Wert-Paare haben, aber dann kann dieser Schlüssel-Wert eine Gruppe zu einer anderen Liste von Schlüssel-Wert-Paaren sein. Damit ist der erste der übergeordnete Schlüssel zur nächsten Liste. Dies ist ein Beispiel von zwei Tabellen, die mit dem gleichen Verfahren genannt werden, die später detailliert beschrieben wird:Gespeicherte SQL-Prozedur mit unendlichen optionalen Parametern

--MyListTableAlpha 
    +- Key1 (ValueA) 
    +- Key2 (ValueB) 
    +- Key3 (ValueC) 
    +- Key4 (ValueD) 

--MyListTableBravo 
    +- Parent Uno 
    +- Key1 (Value1A) 
    +- Key2 (Value1B) 
    +- Parent Dos 
    +- Key1 (Value2A) 
    +- Key2 (Value2B) 
    +- Key3 (Value3C) 

Der Code für SQL Server sein muss 2008.

Dies ist, was habe ich für die 2 paremeter Stored Procedure:

CREATE PROCEDURE [dbo].[SPListValue] 
    -- Add the parameters for the stored procedure here 
    @listName nvarchar(100) = null, 
    @keyVal nvarchar(100) = null 
    -- optional parameters go here?!? 
AS 
BEGIN 
    SET NOCOUNT ON; 

    SELECT [value_string] from [tablenames] 
    JOIN [keyvalues] on [tablenames].[id] = [keyvalues].[tableid] 
    WHERE [dbo].[keyvalues].[key] = @keyVal 
END 

Tabelle [keyvalues] hat die Spalten: id, tableid, parentkeyid, key, value. Dabei wird parentkeyid verwendet, wenn die Werte gruppiert sind, um zu wissen, zu welcher Gruppe sie gehören.

Dies ist, wie ich MyListTableAlpha von meinem Java-Code (Hinweis 2 s?) Nennen möchte:

CallableStatement cs1 = conn1.prepareCall("{call SPListValue(?,?}"); //notice 2 ?s 
cs1.setString(1, "MyListTableAlpha"); 
cs1.setString(2, "Key1"); 
ResultSet rs1 = cs1.executeQuery(); 
rs1.next(); 
value = rs1.getString("value_string"); // Prints ValueA 

Dies ist, wie ich MyListTableBravo von meinem Java-Code aufrufen möchten (Hinweis 3 s?) :

CallableStatement cs1 = conn1.prepareCall("{call SPListValue(?,?,?}"); //notice 3 ?s 
cs1.setString(1, "MyListTableBravo"); 
cs1.setString(2, "Parent Uno"); 
cs1.setString(3, "Key2"); 
ResultSet rs1 = cs1.executeQuery(); 
rs1.next(); 
value = rs1.getString("value_string"); // Prints Value1B 
+5

wie Sie ein schlecht gebrochenes DB-Design haben Sieht aus. – Oded

+0

Das DB-Design funktioniert so, dass ich die gruppierten Schlüsselwerte haben kann, falls gewünscht. Es wurde verdummt, um diese Frage zu stellen. Meine Frage ist, wie man der SQL Stored Procedure unendlich viele Parameter hinzufügen kann. – elcool

+0

Sie haben eine bessere Chance auf Erfolg, wenn Sie eine obere Grenze etwas weniger als unendlich wählen. – AShelly

Antwort

0

So habe ich es gelöst.

Stattdessen unendliche Parameter zu haben, ich mich beschränken auf maximal 4

CREATE PROCEDURE [dbo].[SPListValue] 
    @listName nvarchar(100) = null, 
    @key1Val nvarchar(100) = null, 
    @key2Val nvarchar(100) = null, 
    @key3Val nvarchar(100) = null, 
    @key4Val nvarchar(100) = null 
AS 
BEGIN 

SET NOCOUNT ON; 

if @key4Val is not null 

    SELECT fourCE.[value_string] from [tablenames] as fourCE   
    JOIN [keyvalues] as fourLS ON fourCE.[object_id] = fourLS.[parent_id] 

    JOIN [tablenames] as threeCE ON threeCE.[object_id] = fourCE.[parent_id]   
    JOIN [keyvalues] as threeLS on threeCE.[object_id] = threeLS.[parent_id] 

    JOIN [tablenames] as twoCE ON twoCE.[object_id] = threeCE.[parent_id]  
    JOIN [keyvalues] as twoLS on twoCE.[object_id] = twoLS.[parent_id] 

    JOIN [tablenames] as oneCE ON oneCE.[object_id] = threeCE.[parent_id]  
    JOIN [keyvalues] as oneLS on oneCE.[object_id] = oneLS.[parent_id] 

    JOIN [Cvl] on oneCE.[parent_cvl_id] = [Cvl].[object_id] 
    WHERE oneLS.[text] = @key1Val 
    AND twoLS.[text] = @key2Val 
    AND threeLS.[text] = @key3Val 
    AND fourLS.[text] = @key4Val 
    AND [Cvl].[display_name] = @listName 

else if @key3val is not null 

    SELECT threeCE.[value_string] from [tablenames] as threeCE  
    JOIN [keyvalues] as threeLS ON threeCE.[object_id] = threeLS.[parent_id] 

    JOIN [tablenames] as twoCE ON twoCE.[object_id] = threeCE.[parent_id]  
    JOIN [keyvalues] as twoLS on twoCE.[object_id] = twoLS.[parent_id] 

    JOIN [tablenames] as oneCE ON oneCE.[object_id] = twoCE.[parent_id]  
    JOIN [keyvalues] as oneLS on oneCE.[object_id] = oneLS.[parent_id] 

    JOIN [Cvl] on oneCE.[parent_cvl_id] = [Cvl].[object_id] 
    WHERE oneLS.[text] = @key1Val 
    AND twoLS.[text] = @key2Val 
    and threeLS.[text] = @key3Val 
    AND [Cvl].[display_name] = @listName 

else if @key2Val is not null 

    SELECT twoCE.[value_string] from [tablenames] as twoCE  
    JOIN [keyvalues] as twoLS ON twoCE.[object_id] = twoLS.[parent_id] 

    JOIN [tablenames] as oneCE ON oneCE.[object_id] = twoCE.[parent_id]  
    JOIN [keyvalues] as oneLS on oneCE.[object_id] = oneLS.[parent_id] 

    JOIN [Cvl] on oneCE.[parent_cvl_id] = [Cvl].[object_id] 
    WHERE oneLS.[text] = @key1Val AND twoLS.[text] = @key2Val 
    AND [Cvl].[display_name] = @listName 

else 

    SELECT [value_string] from [tablenames] 
    JOIN [keyvalues] ON [tablenames].[object_id] = [keyvalues].[parent_id] 
    JOIN [Cvl] on [tablenames].[parent_cvl_id] = [Cvl].[object_id] 
    WHERE [keyvalues].[text] = @key1Val 
    AND [Cvl].[display_name] = @listName 

END 

:-)

2

Sie sollten überlegen, einen dritten Parameter zu erstellen, der XML enthält. Dann können Sie so viele Informationen eingeben, wie Sie möchten.

+2

Eine bessere Alternative zu XML sind Tabellenwertparameter, die in SQL Server 2008 eingeführt wurden. Http://msdn.microsoft.com/en-us/library/bb510489.aspx – Oded

+0

Wenn Sie Tabellenwertparameter arbeiten können, stimme ich zu. Nicht sicher über den Kontext, in dem @elcool diesen Sproc aufruft. – wcm

+0

Übrigens, ich habe nicht gesagt, dass ich an diese Lösung gedacht und sie abgelehnt habe. Es war mir nicht eingefallen. Sie sollten es als Antwort posten. – wcm

Verwandte Themen