2013-06-25 1 views
24

Je développe ma toute première procédure stockée au SQL Server 2008 R2 et j'ai besoin de conseils concernant le message d'erreurs.Procédure ou fonction !!! a trop d'arguments spécifiés

procédure ou une fonction xxx trop d'arguments spécifiés

que je reçois après l'exécution de la procédure stockée [dbo].[M_UPDATES] qui appelle une autre procédure stockée appelée etl_M_Update_Promo.

Lorsque vous appelez [dbo].[M_UPDATES] (code, voir ci-dessous) par l'intermédiaire droit de la souris de la souris et « Exécuter la procédure stockée » la requête qui apparaît dans la fenêtre de requête est:

USE [Database_Test] 
GO 

DECLARE @return_value int 

EXEC @return_value = [dbo].[M_UPDATES] 

SELECT 'Return Value' = @return_value 

GO 

La sortie est

Msg 8144, niveau 16, état 2, procédure etl_M_Update_Promo, ligne 0
Procédure et fonction etl_M_Update_Promo a trop d'arguments spécifiés.

QUESTION: Qu'est-ce que ce message d'erreur signifie exactement, à savoir où sont trop nombreux arguments? Comment les identifier?

J'ai trouvé plusieurs threads demandant à propos de ce message d'erreur, mais les codes fournis étaient tous différents du mien (sinon dans une autre langue comme C# de toute façon). Donc, aucune des réponses n'a résolu le problème de ma requête SQL (c'est-à-dire SPs). Remarque: ci-dessous, je fournis le code utilisé pour les deux SP, mais j'ai changé les noms de base de données, les noms de table et les noms de colonne. Donc, s'il vous plaît, ne vous préoccupez pas des conventions de nommage, ce ne sont que des exemples de noms!

Merci d'avance pour tous conseils et pensées!

(1) Code pour le Service Pack 1 [dbo]. [M_UPDATES]

USE [Database_Test] 
GO 

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[ M_UPDATES] AS 
declare @GenID bigint 
declare @Description nvarchar(50) 

Set @GenID = SCOPE_IDENTITY() 
Set @Description = 'M Update' 

BEGIN 
EXEC etl.etl_M_Update_Promo @GenID, @Description 
END 

GO 

(2) Code pour le Service Pack 2 [etl_M_Update_Promo]

USE [Database_Test] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [etl].[etl_M_Update_Promo] 
@GenId bigint = 0 
as 

declare @start datetime = getdate() 
declare @Process varchar (100) = 'Update_Promo' 
declare @SummeryOfTable TABLE (Change varchar (20)) 
declare @Description nvarchar(50) 
declare @ErrorNo int 
, @ErrorMsg varchar (max) 
declare @Inserts int = 0 
, @Updates int = 0 
, @Deleted int = 0 
, @OwnGenId bit = 0 

begin try 


if @GenId = 0 begin 
INSERT INTO Logging.dbo.ETL_Gen (Starttime) 
VALUES (@start) 

SET @GenId = SCOPE_IDENTITY() 
SET @OwnGenId = 1 
end 


MERGE [Database_Test].[dbo].[Promo] AS TARGET 
USING OPENQUERY(M ,'select * from m.PROMO') AS SOURCE 
ON (TARGET.[E] = SOURCE.[E]) 


WHEN MATCHED AND TARGET.[A] <> SOURCE.[A] 
    OR TARGET.[B] <> SOURCE.[B] 
    OR TARGET.[C] <> SOURCE.[C] 
    THEN 
UPDATE SET TARGET.[A] = SOURCE.[A] 
    ,TARGET.[B] = SOURCE.[B] 
    , TARGET.[C] = SOURCE.[c] 

WHEN NOT MATCHED BY TARGET THEN 
INSERT ([E] 
    ,[A] 
    ,[B] 
    ,[C] 
    ,[D] 
    ,[F] 
    ,[G] 
    ,[H] 
    ,[I] 
    ,[J] 
    ,[K] 
    ,[L] 
) 
VALUES (SOURCE.[E] 
    ,SOURCE.[A] 
    ,SOURCE.[B] 
    ,SOURCE.[C] 
    ,SOURCE.[D] 
    ,SOURCE.[F] 
    ,SOURCE.[G] 
    ,SOURCE.[H] 
    ,SOURCE.[I] 
    ,SOURCE.[J] 
    ,SOURCE.[K] 
    ,SOURCE.[L] 
) 

OUTPUT $ACTION INTO @SummeryOfTable; 


with cte as (
SELECT 
Change, 
COUNT(*) AS CountPerChange 
FROM @SummeryOfTable 
GROUP BY Change 
) 

SELECT 
@Inserts = 
    CASE Change 
     WHEN 'INSERT' THEN CountPerChange ELSE @Inserts 
    END, 
@Updates = 
    CASE Change 
     WHEN 'UPDATE' THEN CountPerChange ELSE @Updates 
    END, 
@Deleted = 
    CASE Change 
     WHEN 'DELETE' THEN CountPerChange ELSE @Deleted 
    END 
FROM cte 


INSERT INTO Logging.dbo.ETL_log (GenID, Startdate, Enddate, Process, Message, Inserts, Updates, Deleted,Description) 
VALUES (@GenId, @start, GETDATE(), @Process, 'ETL succeded', @Inserts, @Updates,  @Deleted,@Description) 


if @OwnGenId = 1 
UPDATE Logging.dbo.ETL_Gen 
SET Endtime = GETDATE() 
WHERE ID = @GenId 

end try 
begin catch 

SET @ErrorNo = ERROR_NUMBER() 
SET @ErrorMsg = ERROR_MESSAGE() 

INSERT INTO Logging.dbo.ETL_Log (GenId, Startdate, Enddate, Process, Message, ErrorNo, Description) 
VALUES (@GenId, @start, GETDATE(), @Process, @ErrorMsg, @ErrorNo,@Description) 


end catch 
GO 

Répondre

30

vous invoquez la fonction avec 2 paramètres (@GenId et @description):

EXEC etl.etl_M_Update_Promo @GenID, @Description 

Cependant, vous avez déclaré la fonction de prendre 1 argument:

ALTER PROCEDURE [etl].[etl_M_Update_Promo] 
    @GenId bigint = 0 

SQL Server vous dit que [etl_M_Update_Promo] ne prend 1 paramètre (@GenId)

Vous pouvez modifier la procédure de prendre deux paramètres en spécifiant @Description.

+1

Excellent! Cela fonctionne après avoir supprimé @Description NVARCHAR (50) de la section déclarer. Merci d'avoir répondu si vite et si clairement! – user2006697

+1

@Darren Existe-t-il un mécanisme pour ignorer les paramètres inattendus? –

+2

@AliAdlavaran les ajouter une valeur par défaut – CiucaS

1

Cette réponse est basée sur le titre et non le cas spécifique dans le message d'origine.

J'ai eu une procédure d'insertion qui a continué à lancer cette erreur ennuyeuse, et même si l'erreur dit, "procédure .... a trop d'arguments spécifiés", le fait est que la procédure n'a pas assez d'arguments.

La table avait une colonne id incrémentielle, et comme elle est incrémentielle, je n'ai pas pris la peine de l'ajouter comme variable/argument au proc, mais il s'est avéré que c'est nécessaire, donc je l'ai ajouté comme @Id et l'alto comme ils disent ... ça marche.

+0

J'ai eu le même. Ajout du @ID avec un défaut = 0 à la procédure mais l'objet VBA ne l'utilise pas dans son appel et n'est pas utilisé dans l'INSERT mais oui, ça marche bien maintenant. Curieusement, quand j'ai couru l'EXEC en SQL c'était bien, mais pas quand j'ai été appelé depuis mon projet VBA. Doit être un bug! – CarloC

1

Utilisez la commande suivante avant de les définir:

cmd.Parameters.Clear() 
0

En plus de toutes les réponses fournies à ce jour, une autre raison de l'origine de cette exception peut se produire lorsque vous enregistrez des données de la liste à l'aide de la base de données ADO.Net .

De nombreux développeurs utilisent à tort ou boucle forforeach et laisser le SqlCommand à exécuter en dehors de la boucle, pour éviter que vous assurer que vous avez comme cet exemple de code par exemple:

public static void Save(List<myClass> listMyClass) 
    { 
     using (var Scope = new System.Transactions.TransactionScope()) 
     { 
      if (listMyClass.Count > 0) 
      { 
       for (int i = 0; i < listMyClass.Count; i++) 
       { 
        SqlCommand cmd = new SqlCommand("dbo.SP_SaveChanges", myConnection); 
        cmd.CommandType = CommandType.StoredProcedure; 
        cmd.Parameters.Clear(); 

        cmd.Parameters.AddWithValue("@ID", listMyClass[i].ID); 
        cmd.Parameters.AddWithValue("@FirstName", listMyClass[i].FirstName); 
        cmd.Parameters.AddWithValue("@LastName", listMyClass[i].LastName); 

        try 
        { 
         myConnection.Open(); 
         cmd.ExecuteNonQuery(); 
        } 
        catch (SqlException sqe) 
        { 
         throw new Exception(sqe.Message); 
        } 
        catch (Exception ex) 
        { 
         throw new Exception(ex.Message); 
        } 
        finally 
        { 
         myConnection.Close(); 
        } 
       } 
      } 
      else 
      { 
       throw new Exception("List is empty"); 
      } 

      Scope.Complete(); 
     } 
    } 
Questions connexes