Процедура или функция !!! слишком много аргументов указано

Я разрабатываю свою первую хранимую процедуру в SQL Server 2008 R2 и нуждаюсь в совете относительно сообщения об ошибках.

Процедура или функция xxx слишком много аргументов

который я получаю после выполнения хранимой процедуры [dbo].[M_UPDATES] которая вызывает другую хранимую процедуру, называемую etl_M_Update_Promo.

При вызове [dbo].[M_UPDATES] (код см. Ниже) с помощью щелчка правой кнопкой мыши и "Выполнение хранимой процедуры запрос, который появляется в окне запроса:

USE [Database_Test]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[M_UPDATES]

SELECT  'Return Value' = @return_value

GO

Выход

Msg 8144, уровень 16, состояние 2, процедура etl_M_Update_Promo, строка 0
Процедура или функция etl_M_Update_Promo содержит слишком много аргументов.

ВОПРОС: Что означает это сообщение об ошибке, т.е. где слишком много аргументов? Как их идентифицировать?

Я нашел несколько потоков, спрашивающих об этом сообщении об ошибке, но предоставленные коды были разными для моего (если не на другом языке, таком как C# любом случае). Поэтому ни один из ответов не решил проблему моего SQL запроса (например, SP).

Примечание: ниже я предоставляю код, используемый для двух SP, но я изменил имена базы данных, имена таблиц и имена столбцов. Поэтому, пожалуйста, не беспокойтесь о соглашениях об именах, это только имена примеров!

Заранее благодарим за любые советы и мысли!

(1) Код для 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) Код для 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

Ответ 1

Вы вызываете функцию с двумя параметрами (@GenId и @Description):

EXEC etl.etl_M_Update_Promo @GenID, @Description

Однако вы заявили, что функция принимает один аргумент:

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

SQL Server сообщает вам, что [etl_M_Update_Promo] принимает только 1 параметр (@GenId)

Вы можете изменить процедуру, чтобы принять два параметра, указав @Description.

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

.... Rest of your code.

Ответ 2

Этот ответ основан на названии, а не на конкретном случае в исходном сообщении.

У меня была процедура вставки, которая продолжала бросать эту досадную ошибку, и хотя ошибка говорит: "процедура.... содержит слишком много аргументов", факт состоит в том, что в процедуре НЕ было достаточно аргументов.

В таблице был инкрементный столбец id, и поскольку он инкрементный, я не стал добавлять его в качестве переменной/аргумента в proc, но оказалось, что это необходимо, поэтому я добавил его как @Id и viola, как они скажем... это работает.

Ответ 3

Перед их определением используйте следующую команду:

cmd.Parameters.Clear()

Ответ 4

В дополнение ко всем ответам, предоставленным до сих пор, другая причина возникновения этого исключения может произойти, когда вы сохраняете данные из списка в базу данных с помощью ADO.Net.

Многие разработчики ошибочно будут использовать for цикла или foreach и оставить SqlCommand для выполнения вне цикла, чтобы избежать этого, убедитесь, что у вас есть этот пример кода, например:

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

Ответ 5

Для тех, у кого может быть та же проблема, что и у меня, я получил эту ошибку, когда используемая БД была фактически master, а не БД, которую я должен был использовать.

Просто поместите use [DBName] поверх сценария или вручную измените базу данных, используемую в графическом интерфейсе SQL Server Management Studio.