1. ホーム
  2. sql

[解決済み] プロシージャまたは関数!!!に指定された引数が多すぎます。

2022-02-10 07:05:01

質問

SQL Server 2008で初めてのストアドプロシージャを開発しているのですが、エラーメッセージについてアドバイスが必要です。

プロシージャまたは関数 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, Level 16, State 2, Procedure etl_M_Update_Promo, Line 0
プロシージャまたは関数 etl_M_Update_Promo は、指定された引数が多すぎます。

QUESTION : このエラーメッセージは正確には何を意味しているのでしょうか?つまり、どこにtoo many argumentsがあるのでしょうか?また、それらをどのように識別するのでしょうか?

このエラーメッセージについて質問しているスレッドをいくつか見つけたのですが、提供されたコードはすべて私のものとは異なっていました(他の言語でない場合は C# ということです。) そのため、どの回答も、私の SQL のクエリ(つまりSP)になります。

注:以下に、2つの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

解決方法は?

2つのパラメータ(@GenIdと@Description)を指定して、関数を呼び出します。

EXEC etl.etl_M_Update_Promo @GenID, @Description

しかし、あなたはこの関数を1つの引数を取るように宣言しています。

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

SQL Server は、以下のことを伝えています。 [etl_M_Update_Promo] は1つのパラメータしか取らない ( @GenId )

を指定することで、2つのパラメータを受け取るようにプロシージャを変更することができます。 @Description .

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

.... Rest of your code.