Procédure ou fonction! a trop d'arguments spécifiés

je développe ma première procédure stockée dans SQL Server 2008 R2 et besoin de conseils concernant les messages d'erreurs.

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

que j'obtiens après avoir exécuté la procédure stockée [dbo].[M_UPDATES] qui appelle une autre procédure stockée appelée etl_M_Update_Promo.

quand on appelle [dbo].[M_UPDATES] (code voir ci-dessous) via le clic droit 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, la Procédure etl_M_Update_Promo, la Ligne 0

Procédure ou fonction etl_M_Update_Promo a trop d'arguments spécifiés.

QUESTION: que signifie exactement ce message d'erreur, c'est-à-dire où sont trop d'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 (si pas dans une autre langue comme C# en tout cas). Si aucune réponse n'a résolu le problème de mon SQL requête (c.-à-d. SPs).

Note: ci-dessous je fournis le code utilisé pour les deux SPs, mais j'ai changé les noms de base de données, les noms de table et les noms de colonne. Alors, s'il vous plaît, ne vous souciez pas des conventions de nommage, ce ne sont que des exemples de noms!

Merci d'avance pour vos conseils et vos réflexions!

(1) Code pour SP1 [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 for SP2 [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
30
demandé sur Darren 2013-06-25 12:35:25

5 réponses

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] prend seulement 1 paramètre (@GenId)

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

ALTER PROCEDURE [etl].[etl_M_Update_Promo]
    @GenId bigint = 0,
    @Description NVARCHAR(50)
AS 

.... Rest of your code.
31
répondu Darren 2013-06-25 08:37:57

Cette réponse est basée sur le titre et pas le cas dans le post original.

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 incrémentielle id, et puisqu'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é qu'elle est nécessaire, donc je l'ai ajouté comme @Id et alto comme ils disent...il fonctionne.

2
répondu usefulBee 2015-11-10 20:23:19

Utilisez la commande suivante avant de les définir:

cmd.Parameters.Clear()
2
répondu FEOL 2016-06-22 02:22:03

en plus de toutes les réponses fournies jusqu'à présent, une autre raison de causer cette exception peut se produire lorsque vous sauvegardez des données d'une liste à une base de données en utilisant ADO.Net.

beaucoup de développeurs utiliseront par erreur for boucle ou foreach et laisser le SqlCommand pour exécuter en dehors de la boucle, pour éviter cela assurez-vous 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();
        }
    }
0
répondu Ashraf Abusada 2017-05-30 22:10:56

pour ceux qui pourraient avoir le même problème que moi, j'ai eu cette erreur quand le DB que j'utilisais était en fait maître, et non pas la DB que je devrais utiliser.

mettre use [DBName] en haut de votre script, ou bien changer manuellement la base de données utilisée dans L'interface graphique SQL Server Management Studio.

0
répondu Ray Lionfang 2018-07-20 02:35:06