2013-06-25 17 views
24

Sto sviluppando la mia prima stored procedure in SQL Server 2008 R2 e ho bisogno di consigli sul messaggio di errore.Procedura o funzione !!! ha troppi argomenti specificati

procedura o funzione xxx troppi argomenti specificati

che ricevo dopo l'esecuzione della stored procedure [dbo].[M_UPDATES] che chiama un altro stored procedure chiamata etl_M_Update_Promo.

Quando si chiama [dbo].[M_UPDATES] (codice vedi sotto) attraverso il tasto destro del mouse-click e 'Esegui stored procedure' la query che appare nella query-finestra è:

USE [Database_Test] 
GO 

DECLARE @return_value int 

EXEC @return_value = [dbo].[M_UPDATES] 

SELECT 'Return Value' = @return_value 

GO 

L'uscita è

Messaggio 8144, livello 16, stato 2, procedura etl_M_Update_Promo, riga 0
La procedura o la funzione etl_M_Update_Promo contiene troppi argomenti specificati.

DOMANDA: Cosa messaggio di errore significa esattamente, vale a dire dove sono troppi argomenti? Come identificarli?

Ho trovato diversi thread che chiedevano questo messaggio di errore, ma i codici forniti erano tutti diversi dai miei (se non in un'altra lingua come C# in ogni caso). Quindi nessuna delle risposte ha risolto il problema della mia query SQL (ad esempio SP).

Nota: qui di seguito fornisco il codice utilizzato per i due SP, ma ho modificato i nomi dei database, i nomi delle tabelle e i nomi delle colonne. Quindi, per favore, non preoccuparti di nominare le convenzioni, questi sono solo nomi di esempio!

Grazie in anticipo per eventuali consigli e pensieri!

(1) Codice per 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) Codice di 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 

risposta

30

si richiama la funzione con 2 parametri (@GenId e @Description):

EXEC etl.etl_M_Update_Promo @GenID, @Description 

Tuttavia avete dichiarato la funzione di prendere 1 argomento:

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

SQL Server vi sta dicendo che [etl_M_Update_Promo] richiede solo 1 parametro (@GenId)

È possibile modificare la procedura di prendere due parametri specificando @Description.

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

.... Rest of your code. 
+1

Eccellente! Funziona dopo aver eliminato @Description NVARCHAR (50) dalla sezione declare. Grazie per aver risposto in modo veloce e chiaro! – user2006697

+1

@Darren Esiste un meccanismo per ignorare i parametri imprevisti? –

+2

@AliAdlavaran aggiungere loro un valore predefinito – CiucaS

1

Questa risposta è basata sul titolo e non sul caso specifico nel post originale.

Avevo una procedura di inserimento che continuava a lanciare questo fastidioso errore, e anche se l'errore dice "la procedura .... ha troppi argomenti specificati", il fatto è che la procedura NON aveva abbastanza argomenti.

La tabella aveva una colonna ID incrementale e poiché è incrementale, non mi sono preoccupato di aggiungerla come variabile/argomento al proc, ma si è scoperto che è necessaria, quindi l'ho aggiunta come @Id e viola come dicono ... funziona.

+0

Ho avuto lo stesso. Aggiunto il @ID con un valore predefinito = 0 alla procedura, ma l'oggetto VBA non lo sta usando nella sua chiamata, né è utilizzato nell'INSERTO ma sì, ora funziona bene. Stranamente, quando ho eseguito l'EXEC in SQL, andava bene, ma non quando chiamato dal mio progetto VBA. Deve essere un bug! – CarloC

1

Utilizzare il seguente comando prima di definire:

cmd.Parameters.Clear() 
0

In aggiunta a tutte le risposte fornite finora, un altro motivo per aver causato questa eccezione può accadere quando si sta salvando i dati dalla lista di database utilizzando ADO.Net .

Molti sviluppatori saranno erroneamente utilizzare for loop o foreach e lasciare il SqlCommand di eseguire fuori del ciclo, per evitare che assicuratevi di avere come questo esempio di codice, ad esempio:

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(); 
     } 
    } 
Problemi correlati