我正在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,Level 16,State 2,Procedure etl_M_Update_Promo,Line 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
答案 0 :(得分:39)
使用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
)
您可以通过指定@Description
来改变过程以获取两个参数。
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
@GenId bigint = 0,
@Description NVARCHAR(50)
AS
.... Rest of your code.
答案 1 :(得分:2)
此答案基于标题而非原始帖子中的具体案例。
我有一个插入程序,不断抛出这个恼人的错误,即使错误说,&#34; procedure ....指定了太多的参数,&#34;事实是该程序没有足够的论据。
该表有一个增量id列,由于它是增量的,我没有把它作为变量/参数添加到proc,但事实证明它是必需的,所以我把它添加为@Id和像他们说的中提琴......它有效。
答案 2 :(得分:2)
在定义之前使用以下命令:
cmd.Parameters.Clear()
答案 3 :(得分:0)
除了目前为止提供的所有答案之外,当您使用ADO.Net将数据从列表保存到数据库时,可能会发生导致此异常的另一个原因。
许多开发人员会错误地使用for
循环或foreach
并让SqlCommand
在循环外执行,以避免这样做,以确保您喜欢此代码示例,例如:< / p>
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();
}
}
答案 4 :(得分:0)
对于那些可能与我有相同问题的人,当我使用的数据库实际上是 master 而不是我应该使用的数据库时,出现此错误。
只需将use [DBName]
放在脚本顶部,或在SQL Server Management Studio GUI中手动更改正在使用的数据库。
答案 5 :(得分:0)
此错误的另一个原因是当您从代码中调用存储过程时,并且代码中的参数类型与存储过程中的类型不匹配。