2013-06-25 25 views
24

belirtilen çok fazla argümana sahip olduğum ilk saklı yordamımı SQL Server 2008 R2 içinde geliştiriyorum ve hata iletisiyle ilgili bir yardıma ihtiyacım var.Prosedür veya işlev!

Yordam veya işlev xxx çok fazla argüman ben etl_M_Update_Promo adlı başka saklı yordamı çağırır saklı yordamını [dbo].[M_UPDATES] yürüttükten sonra olsun

belirtilmiş.

[dbo].[M_UPDATES] arayarak yoluyla (kod aşağıya bakınız) sağ fare tıklama olduğu sorgu penceresinde görünen sorgu 'saklı yordamını yürütün' ve:

USE [Database_Test] 
GO 

DECLARE @return_value int 

EXEC @return_value = [dbo].[M_UPDATES] 

SELECT 'Return Value' = @return_value 

GO 

çıkış

olduğunu

Msg 8144, Düzey 16, Durum 2, Yordam etl_M_Update_Promo, Satır 0
Prosedür veya işlev etl_M_Update_Promo'nun çok fazla bağımsız değişkeni belirtildi.

SORU: Bu hata mesajı tam olarak ne anlama geliyor, yani çok fazla argüman nerede? Nasıl tanımlanır?

Bu hata iletisini isteyen birkaç ileti buldum, ancak sağlanan kodlar benimkilerden farklıydı (eğer varsa C# gibi başka bir dilde değilse). Yani cevapların hiçbiri benim SQL sorgum (yani SP'ler) sorununu çözmedi.

Not: Aşağıda iki SP için kullanılan kodu veriyorum, ancak veritabanı adlarını, tablo adlarını ve sütun adlarını değiştirdim. Yani, lütfen, adlandırma kurallarına dikkat etmeyin, bunlar sadece örnek isimlerdir!

Her türlü öneri ve düşünceleriniz için şimdiden teşekkür ederiz!

(1) Kod için 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) Kod 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 

cevap

30

Sen (2 parametrelerle işlevini çağırmak için @GenId ve @Description): Eğer 1 argüman almaya fonksiyonunu ilan ettiler Ancak

EXEC etl.etl_M_Update_Promo @GenID, @Description 

:

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

SQL Server [etl_M_Update_Promo] sadece sen @Description belirterek iki parametre alması prosedürü değiştirebilir

1 parametresini (@GenId) sürdüğünü anlatıyor.

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

.... Rest of your code. 
+1

Mükemmel:

Birçok geliştirici yanlışlıkla o örneğin bu kod örneği gibi olduğundan emin olun for döngü veya foreach kullanıp önlemek için, döngü dışında yürütülecek SqlCommand bırakacaktır! Bu, declare bölümünden @Description NVARCHAR (50) sildikten sonra çalışır. Çok hızlı ve net cevap verdiğiniz için teşekkür ederiz! – user2006697

+1

@Darren Beklenmeyen parametreleri yok saymak için bir mekanizma var mı? –

+2

@AliAdlavaran bunları varsayılan bir değer olarak ekle – CiucaS

1

Bu yanıt, özgün gönderideki özel durumu değil başlığı esas alır.

Bu sinir bozucu hatayı atmaya devam eden bir ekleme yordamım vardı ve hatanın "yordam .... belirtilmiş çok fazla argümanı var" şeklinde yazmasına rağmen, bu yordamın yeterli argüman içermediği gerçeğidir.

Tabloda bir artımlı kimlik sütunu vardı ve bu artımlı olduğundan, proc için bir değişken/argüman olarak eklemekten rahatsız olmadım, ancak bunun gerekli olduğu ortaya çıktı, bu yüzden bunu @Id olarak ekledim ve viyola dedikleri gibi ... işe yarıyor.

+0

Aynısını yaptım. @ID prosedürüne bir = 0 = ile eklenir, fakat VBA nesnesi onun çağrısında kullanmaz ve INSERT'de kullanılmaz, ama evet, şimdi iyi çalışıyor. Gerçekten de, EXEC'i SQL'de çalıştırdığımda iyi oldu, ama VBA projemden çağrıldığında değil. Bir böcek olmalı! – CarloC

1

bunları tanımlamadan önce aşağıdaki komutu kullanın: ADO.Net kullanarak veritabanına listesinden veri kaydetme zaman

bugüne kadar sağlanan tüm cevaplara ek olarak
cmd.Parameters.Clear() 
0

, bu durum neden için başka bir neden olabilir .

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