2010-12-07 47 views
0

Je souhaite effectuer une procédure stockée avec un minimum de 2 paramètres requis, mais elle peut également être appelée avec des paramètres 2,3,4,5 ... et ainsi de suite. La raison: J'ai plusieurs tables qui ont des paires clé-valeur, mais cette valeur-clé peut être un groupe à une autre liste de paires valeur-clé. Alors que le premier est la clé parent à la liste suivante. Ceci est un exemple de 2 tables qui peuvent être appelées à la même procédure, détaillée par la suite:Procédure stockée SQL avec paramètres optionnels infinis

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

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

Le code doit être pour SQL Server 2008.

C'est ce que je le 2 paremeter procédure stockée:

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 

Tableau [keyvalues] comporte les colonnes: id, tableid, parentkeyid, key, value. Où parentkeyid est utilisé lorsque les valeurs sont groupées pour savoir à laquelle elles appartiennent.

Voilà comment je voudrais appeler MyListTableAlpha de mon code Java (avis 2 s?):

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 

Voilà comment je voudrais appeler MyListTableBravo de mon code Java (avis 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

On dirait que vous avez une conception de DB mal cassé. – Oded

+0

La conception DB fonctionne de sorte que je puisse avoir les valeurs-clés groupées si désiré. Il a été réduit à néant pour avoir présenté cette question. Ma question est sur la façon d'ajouter des paramètres infinis à la procédure stockée SQL. – elcool

+0

Vous aurez plus de chances de réussir si vous choisissez une limite supérieure légèrement inférieure à l'infini. – AShelly

Répondre

0

Voici comment je l'ai résolu.

Au lieu d'avoir des paramètres infinis, je me restreint à un maximum de 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

Vous voudrez peut-être envisager de faire un troisième paramètre qui contient XML. Ensuite, vous pouvez mettre autant d'informations que vous le souhaitez.

+2

Une meilleure alternative à XML est les paramètres de table, introduits dans SQL Server 2008. http://msdn.microsoft.com/en-us/library/bb510489.aspx – Oded

+0

Si vous pouvez faire fonctionner les paramètres de valeur de table, alors je suis d'accord. Je ne suis pas sûr du contexte dans lequel @elcool appelle ce sproc. – wcm

+0

BTW, je ne disais pas que j'avais pensé à cette solution et l'a rejeté. Cela ne m'était pas venu à l'esprit. Vous devriez le poster comme une réponse. – wcm