webentwicklung-frage-antwort-db.com.de

Prozedur oder Funktion !!! hat zu viele Argumente angegeben

Ich entwickle meine allererste gespeicherte Prozedur in SQL Server 2008 R2 und brauche Rat bezüglich der Fehlermeldung.

Prozedur oder Funktion xxx zu viele Argumente angegeben

das bekomme ich nach der Ausführung der gespeicherten Prozedur [dbo].[M_UPDATES], die eine andere gespeicherte Prozedur namens etl_M_Update_Promo aufruft.

Beim Aufruf von [dbo].[M_UPDATES] (Code siehe unten) über die rechte Maustaste und "Gespeicherte Prozedur ausführen" wird folgende Abfrage im Abfragefenster angezeigt:

USE [Database_Test]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[M_UPDATES]

SELECT  'Return Value' = @return_value

GO

Die Ausgabe ist 

Meldung 8144, Ebene 16, Status 2, Prozedur etl_M_Update_Promo, Zeile 0
Für die Prozedur oder Funktion etl_M_Update_Promo wurden zu viele Argumente angegeben.

QUESTION: Was bedeutet diese Fehlermeldung genau, d. h. wo sind zu viele Argumente? Wie identifiziere ich sie?

Ich habe mehrere Threads gefunden, die nach dieser Fehlermeldung gefragt haben, aber die bereitgestellten Codes waren alle anders als meine (falls nicht in einer anderen Sprache wie C#). Daher löste keine der Antworten das Problem meiner SQL-Abfrage (d. H. SPs).

Hinweis: Im Folgenden gebe ich den Code für die beiden SPs an, aber ich habe die Datenbanknamen, Tabellennamen und Spaltennamen geändert. Machen Sie sich also keine Gedanken über Namenskonventionen, dies sind nur Beispielnamen!

Vielen Dank im Voraus für alle Ratschläge und Gedanken!

(1) Code für 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 für 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
user2006697

Sie rufen die Funktion mit 2 Parametern auf (@GenId und @Description):

EXEC etl.etl_M_Update_Promo @GenID, @Description

Sie haben jedoch die Funktion für 1 Argument erklärt:

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

SQL Server sagt Ihnen, dass [etl_M_Update_Promo] nur einen Parameter (@GenId) benötigt.

Sie können das Verfahren ändern, um zwei Parameter zu übernehmen, indem Sie @Description angeben.

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

.... Rest of your code.
35
Darren

Diese Antwort bezieht sich auf den Titel und nicht auf den konkreten Fall im ursprünglichen Beitrag. 

Ich hatte eine Einfügungsprozedur, die diesen ärgerlichen Fehler immer wieder auslöste, und obwohl der Fehler lautet: "Prozedur ... hat zu viele Argumente angegeben", die Tatsache ist, dass die Prozedur NICHT genügend Argumente hatte.

Die Tabelle hatte eine inkrementelle ID-Spalte, und da sie inkrementell ist, habe ich mir nicht die Mühe gemacht, sie als Variable/Argument der Prozedur hinzuzufügen, aber es stellte sich heraus, dass sie benötigt wird, also fügte ich sie wie @Id und Viola hinzu sage ... es funktioniert.

2
usefulBee

Verwenden Sie den folgenden Befehl, bevor Sie sie definieren:

cmd.Parameters.Clear()
2
FEOL

Für diejenigen, die das gleiche Problem wie ich haben könnten, habe ich diesen Fehler erhalten, als die von mir verwendete DB eigentlich master war und nicht die DB, die ich verwenden sollte. 

Fügen Sie einfach use [DBName] oben in Ihr Skript ein oder ändern Sie die in der Benutzeroberfläche von SQL Server Management Studio verwendete Datenbank manuell.

0
Ray Lionfang

Neben allen bisher bereitgestellten Antworten kann ein weiterer Grund für das Auslösen dieser Ausnahme auftreten, wenn Sie Daten mit ADO.Net von der Liste in die Datenbank speichern.

Viele Entwickler verwenden fälschlicherweise for loop oder foreach und lassen die SqlCommand außerhalb der Schleife ausführen, um zu vermeiden, dass Sie dieses Codebeispiel verwenden. Beispiel:

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
Ashraf Abusada