प्रक्रिया की उम्मीद है कि पैरामीटर की आपूर्ति नहीं की गई थी


106

SQL सर्वर में संग्रहीत कार्यविधि तक पहुँचने पर मुझे त्रुटि मिल रही है

Server Error in '/' Application.
Procedure or function 'ColumnSeek' expects parameter '@template', which was not supplied. 

यह तब हो रहा है जब मैं .net डेटा कनेक्शन के माध्यम से एक पैरामीटर के साथ एक संग्रहीत प्रक्रिया को कॉल करता हूं (System.data.SqlClient), भले ही मैं पैरामीटर की आपूर्ति कर रहा हूं। यहाँ मेरा कोड है।

SqlConnection sqlConn = new SqlConnection(connPath);
sqlConn.Open();

//METADATA RETRIEVAL
string sqlCommString = "QCApp.dbo.ColumnSeek";
SqlCommand metaDataComm = new SqlCommand(sqlCommString, sqlConn);
metaDataComm.CommandType = CommandType.StoredProcedure;
SqlParameter sp = metaDataComm.Parameters.Add("@template",SqlDbType.VarChar,50);
sp.Value = Template;

SqlDataReader metadr = metaDataComm.ExecuteReader();

और मेरी संग्रहीत प्रक्रिया है:

   USE [QCApp]
   GO
   SET ANSI_NULLS ON
   GO
   SET QUOTED_IDENTIFIER ON
   GO

   ALTER PROCEDURE [dbo].[ColumnSeek] 
       @template varchar(50)
   AS
   EXEC('SELECT Column_Name, Data_Type 
   FROM [QCApp].[INFORMATION_SCHEMA].[COLUMNS] 
   WHERE TABLE_NAME = ' + @template);

मैं यह पता लगाने की कोशिश कर रहा हूं कि मैं यहां क्या गलत कर रहा हूं।

संपादित करें: जैसा कि यह पता चला है, खाका अशक्त था क्योंकि मुझे इसका मान URL से गुजरने वाले पैरामीटर से मिल रहा था और मैंने url param passing को खराब कर दिया था (मैं @इसके बजाय प्रयोग कर रहा था &)


बहुत पुराना प्रश्न है, लेकिन मुझे वही समस्या आई, और मेरे मामले में, मैंने नहीं देखा कि मैंने @parameter में से किसी एक में अतिरिक्त स्थान जोड़ा है। डिबगिंग का एक घंटा।
लेयॉन पेलेटियर

संग्रहीत कार्यविधियों को निष्पादित करने और यह त्रुटि प्राप्त करने के लिए stackoverflow.com/a/26374810/1860652 देखें
AlexFoxGill

जो कुछ भी कारण है, वह आज पहले पन्ने पर समाप्त हुआ। लेकिन ऐसा लगता है कि यह SQL इंजेक्शन के लिए कमजोर है अगर "टेम्पलेट" मान क्लाइंट URL से आ रहा है! बहुत कम से कम मैं उपयोग करने का सुझाव QUOTENAME(@template)
दूंगा

जवाबों:


85

मैं अपना आवेदन कोड देखूंगा और देखूंगा कि आप @template को किस मूल्य पर सेट कर रहे हैं। मुझे संदेह है कि यह अशक्त है और इसमें समस्या है।


हाँ, टेम्पलेट शून्य था, मैं इसे पहले सेट करना भूल गया था।
टोनी पीटरसन

35
क्या मैं सिर्फ इतना कह सकता हूं कि DbNull C # का सबसे बेकार "फीचर" है
thaBadDawg

295

अन्य उत्तरों के अलावा, यदि आप लगाना भूल गए हैं:

cmd.CommandType = CommandType.StoredProcedure;

फिर आपको यह त्रुटि भी मिलेगी।


यदि आप इसे विजुअल स्टूडियो से डिबग कर रहे हैं: रिपोर्ट के डेटा टैब पर [लेआउट और पूर्वावलोकन टैब के बगल में] चयनित डेटासेट के नाम के आगे, एक और ड्रॉप डाउन नियंत्रण है जो आपको कमांड टाइप बदलने देता है। का आनंद लें!
सर्जनवेबदेव

2
हाँ, SqlException अजीब है - यह आपको बताता है कि यह इसे एक प्रक्रिया के रूप में जानता है, लेकिन फिर आपको इसे यह बताने के लिए CommandType गुण सेट करना होगा कि यह एक प्रक्रिया है!
ताहिर हसन

@ ताहिर, मुझे लगता है कि यह अधिक है कि त्रुटि "प्रक्रिया" को एक सामान्य शब्द के रूप में उपयोग कर रही है (जैसा कि "या फ़ंक्शन" के अतिरिक्त द्वारा सुझाया गया है), यह अनुमान लगाने के बजाय कि एसक्यूएल डीबी संग्रहीत प्रक्रिया है।
ब्रायन

3
यह उन 99% लोगों के लिए समाधान है,
जिनकी

दमयन्ती, इसका हल आसान क्यों था। धन्यवाद। मुझे पता था कि पैरामीटर अस्तित्व में था और अशक्त नहीं था और यह सब लिया गया था।
बोर्नटुडोस्टफ

27

यह समस्या आमतौर पर एचएलजीईएम के रूप में ऊपर उल्लिखित पैरामीटर मान को शून्य करने के कारण होती है। मैंने सोचा कि मैं इस समस्या के कुछ समाधानों के बारे में विस्तार से बताऊंगा जो मैंने इस समस्या के नए लोगों के लिए उपयोगी पाया है।

समाधान जो मैं पसंद करता हूं वह संग्रहीत प्रक्रिया मापदंडों को NULL (या जो भी आप चाहते हैं) को डिफ़ॉल्ट करना है, जिसका उल्लेख ऊपर sangram द्वारा किया गया था , लेकिन याद किया जा सकता है क्योंकि उत्तर बहुत ही क्रिया है। की तर्ज पर कुछ:

CREATE PROCEDURE GetEmployeeDetails
    @DateOfBirth    DATETIME = NULL,
    @Surname        VARCHAR(20),
    @GenderCode     INT = NULL,
AS

इसका मतलब यह है कि अगर कुछ सिरों के तहत अशक्त करने के लिए पैरामीटर को कोड में सेट किया जा रहा है, तो .NET पैरामीटर सेट नहीं करेगा और संग्रहीत कार्यविधि तब परिभाषित डिफ़ॉल्ट मान का उपयोग करेगी। एक अन्य समाधान, यदि आप वास्तव में कोड में समस्या को हल करना चाहते हैं, तो एक विस्तार विधि का उपयोग करना होगा जो आपके लिए समस्या को संभालती है, कुछ इस प्रकार है:

public static SqlParameter AddParameter<T>(this SqlParameterCollection parameters, string parameterName, T value) where T : class
{
    return value == null ? parameters.AddWithValue(parameterName, DBNull.Value) : parameters.AddWithValue(parameterName, value);
}

मैट हैमिल्टन के यहाँ एक अच्छी पोस्ट है जो इस क्षेत्र के साथ काम करते समय कुछ और बेहतरीन विस्तार विधियों को सूचीबद्ध करती है।


12

मुझे एक समस्या थी कि मुझे पूर्णांक परम को 0 की आपूर्ति करने पर मुझे कहां त्रुटि मिलेगी। और पाया कि:

cmd.Parameters.AddWithValue("@Status", 0);

काम करता है, लेकिन यह नहीं है:

cmd.Parameters.Add(new SqlParameter("@Status", 0));

6
2 का काम नहीं करने का कारण यह है कि कंपाइलर सोचता है कि आप SqlParameter कंस्ट्रक्टर के ओवरलोड (स्ट्रिंग, SqlDbType) को ओवरलोड कर रहे हैं । देखें टिप्पणी यहाँ
कीथ

1
यदि आप Addवाक्यविन्यास का उपयोग करना चाहते हैं , या आप अपने कमांड के लिए ऑब्जेक्ट cmd.Parameters.Add(new SqlParameter("@Status", value: 0));
इनिशलाइज़र का

7

मेरे मामले के लिए, मुझे DBNULL.Valueसंग्रहीत प्रक्रियाओं के पैरामीटर के लिए कोड से (यदि अन्य शर्त का उपयोग करके) पास करना होगा जो परिभाषित नहीं हैं nullलेकिन मूल्य है null


5

मैं संग्रहीत प्रक्रिया को कॉल करते समय समान समस्या आती है

CREATE PROCEDURE UserPreference_Search
    @UserPreferencesId int,
    @SpecialOfferMails char(1),
    @NewsLetters char(1),
    @UserLoginId int,
    @Currency varchar(50)
AS
DECLARE @QueryString nvarchar(4000)

SET @QueryString = 'SELECT UserPreferencesId,SpecialOfferMails,NewsLetters,UserLoginId,Currency FROM UserPreference'
IF(@UserPreferencesId IS NOT NULL)
BEGIN
SET @QueryString = @QueryString + ' WHERE UserPreferencesId = @DummyUserPreferencesId';
END

IF(@SpecialOfferMails IS NOT NULL)
BEGIN
SET @QueryString = @QueryString + ' WHERE SpecialOfferMails = @DummySpecialOfferMails';
END

IF(@NewsLetters IS NOT NULL)
BEGIN
SET @QueryString = @QueryString + ' WHERE NewsLetters = @DummyNewsLetters';
END

IF(@UserLoginId IS NOT NULL)
BEGIN
SET @QueryString = @QueryString + ' WHERE UserLoginId = @DummyUserLoginId';
END

IF(@Currency IS NOT NULL)
BEGIN
SET @QueryString = @QueryString + ' WHERE Currency = @DummyCurrency';
END

EXECUTE SP_EXECUTESQL @QueryString
                     ,N'@DummyUserPreferencesId int, @DummySpecialOfferMails char(1), @DummyNewsLetters char(1), @DummyUserLoginId int, @DummyCurrency varchar(50)'
                     ,@DummyUserPreferencesId=@UserPreferencesId
                     ,@DummySpecialOfferMails=@SpecialOfferMails
                     ,@DummyNewsLetters=@NewsLetters
                     ,@DummyUserLoginId=@UserLoginId
                     ,@DummyCurrency=@Currency;

खोज के लिए क्वेरी का निर्माण गतिशील रूप से मैं एक के ऊपर एक करके कर रहा था:

public DataSet Search(int? AccessRightId, int? RoleId, int? ModuleId, char? CanAdd, char? CanEdit, char? CanDelete, DateTime? CreatedDatetime, DateTime? LastAccessDatetime, char? Deleted)
    {
        dbManager.ConnectionString = ConfigurationManager.ConnectionStrings["MSSQL"].ToString();
        DataSet ds = new DataSet();
        try
        {
            dbManager.Open();
            dbManager.CreateParameters(9);
            dbManager.AddParameters(0, "@AccessRightId", AccessRightId, ParameterDirection.Input);
            dbManager.AddParameters(1, "@RoleId", RoleId, ParameterDirection.Input);
            dbManager.AddParameters(2, "@ModuleId", ModuleId, ParameterDirection.Input);
            dbManager.AddParameters(3, "@CanAdd", CanAdd, ParameterDirection.Input);
            dbManager.AddParameters(4, "@CanEdit", CanEdit, ParameterDirection.Input);
            dbManager.AddParameters(5, "@CanDelete", CanDelete, ParameterDirection.Input);
            dbManager.AddParameters(6, "@CreatedDatetime", CreatedDatetime, ParameterDirection.Input);
            dbManager.AddParameters(7, "@LastAccessDatetime", LastAccessDatetime, ParameterDirection.Input);
            dbManager.AddParameters(8, "@Deleted", Deleted, ParameterDirection.Input);
            ds = dbManager.ExecuteDataSet(CommandType.StoredProcedure, "AccessRight_Search");
            return ds;
        }
        catch (Exception ex)
        {
        }
        finally
        {
            dbManager.Dispose();
        }
        return ds;
    }

फिर सिर खुजलाने के बाद मैंने संग्रहित प्रक्रिया को संशोधित किया:

ALTER PROCEDURE [dbo].[AccessRight_Search]
    @AccessRightId int=null,
    @RoleId int=null,
    @ModuleId int=null,
    @CanAdd char(1)=null,
    @CanEdit char(1)=null,
    @CanDelete char(1)=null,
    @CreatedDatetime datetime=null,
    @LastAccessDatetime datetime=null,
    @Deleted char(1)=null
AS
DECLARE @QueryString nvarchar(4000)
DECLARE @HasWhere bit
SET @HasWhere=0

SET @QueryString = 'SELECT a.AccessRightId, a.RoleId,a.ModuleId, a.CanAdd, a.CanEdit, a.CanDelete, a.CreatedDatetime, a.LastAccessDatetime, a.Deleted, b.RoleName, c.ModuleName FROM AccessRight a, Role b, Module c WHERE a.RoleId = b.RoleId AND a.ModuleId = c.ModuleId'

SET @HasWhere=1;

IF(@AccessRightId IS NOT NULL)
    BEGIN
        IF(@HasWhere=0) 
            BEGIN
                SET @QueryString = @QueryString + ' WHERE a.AccessRightId = @DummyAccessRightId';
                SET @HasWhere=1;
            END
        ELSE                SET @QueryString = @QueryString + ' AND a.AccessRightId = @DummyAccessRightId';
    END

IF(@RoleId IS NOT NULL)
    BEGIN
        IF(@HasWhere=0)
            BEGIN   
                SET @QueryString = @QueryString + ' WHERE a.RoleId = @DummyRoleId';
                SET @HasWhere=1;
            END
        ELSE            SET @QueryString = @QueryString + ' AND a.RoleId = @DummyRoleId';
    END

IF(@ModuleId IS NOT NULL)
BEGIN
    IF(@HasWhere=0) 
            BEGIN   
                SET @QueryString = @QueryString + ' WHERE a.ModuleId = @DummyModuleId';
                SET @HasWhere=1;
            END
    ELSE SET @QueryString = @QueryString + ' AND a.ModuleId = @DummyModuleId';
END

IF(@CanAdd IS NOT NULL)
BEGIN
    IF(@HasWhere=0) 
            BEGIN       
                SET @QueryString = @QueryString + ' WHERE a.CanAdd = @DummyCanAdd';
                SET @HasWhere=1;
            END
    ELSE SET @QueryString = @QueryString + ' AND a.CanAdd = @DummyCanAdd';
END

IF(@CanEdit IS NOT NULL)
BEGIN
    IF(@HasWhere=0) 
        BEGIN
            SET @QueryString = @QueryString + ' WHERE a.CanEdit = @DummyCanEdit';
            SET @HasWhere=1;
        END
    ELSE SET @QueryString = @QueryString + ' AND a.CanEdit = @DummyCanEdit';
END

IF(@CanDelete IS NOT NULL)
BEGIN
    IF(@HasWhere=0) 
        BEGIN
            SET @QueryString = @QueryString + ' WHERE a.CanDelete = @DummyCanDelete';
            SET @HasWhere=1;
        END
    ELSE SET @QueryString = @QueryString + ' AND a.CanDelete = @DummyCanDelete';
END

IF(@CreatedDatetime IS NOT NULL)
BEGIN
    IF(@HasWhere=0) 
    BEGIN
        SET @QueryString = @QueryString + ' WHERE a.CreatedDatetime = @DummyCreatedDatetime';
        SET @HasWhere=1;
    END
    ELSE SET @QueryString = @QueryString + ' AND a.CreatedDatetime = @DummyCreatedDatetime';
END

IF(@LastAccessDatetime IS NOT NULL)
BEGIN
    IF(@HasWhere=0) 
        BEGIN
            SET @QueryString = @QueryString + ' WHERE a.LastAccessDatetime = @DummyLastAccessDatetime';
            SET @HasWhere=1;
        END
    ELSE SET @QueryString = @QueryString + ' AND a.LastAccessDatetime = @DummyLastAccessDatetime';
END

IF(@Deleted IS NOT NULL)
BEGIN
  IF(@HasWhere=0)   
    BEGIN
        SET @QueryString = @QueryString + ' WHERE a.Deleted = @DummyDeleted';
        SET @HasWhere=1;
    END
  ELSE SET @QueryString = @QueryString + ' AND a.Deleted = @DummyDeleted';
END

PRINT @QueryString

EXECUTE SP_EXECUTESQL @QueryString
                      ,N'@DummyAccessRightId int, @DummyRoleId int, @DummyModuleId int, @DummyCanAdd char(1), @DummyCanEdit char(1), @DummyCanDelete char(1), @DummyCreatedDatetime datetime, @DummyLastAccessDatetime datetime, @DummyDeleted char(1)'
                      ,@DummyAccessRightId=@AccessRightId
                      ,@DummyRoleId=@RoleId
                      ,@DummyModuleId=@ModuleId
                      ,@DummyCanAdd=@CanAdd
                      ,@DummyCanEdit=@CanEdit
                      ,@DummyCanDelete=@CanDelete
                      ,@DummyCreatedDatetime=@CreatedDatetime
                      ,@DummyLastAccessDatetime=@LastAccessDatetime
                      ,@DummyDeleted=@Deleted;

यहाँ मैं अनुवर्ती के रूप में अशक्त करने के लिए संग्रहीत कार्यविधि के इनपुट परम की शुरुआत कर रहा हूँ

    @AccessRightId int=null,
@RoleId int=null,
@ModuleId int=null,
@CanAdd char(1)=null,
@CanEdit char(1)=null,
@CanDelete char(1)=null,
@CreatedDatetime datetime=null,
@LastAccessDatetime datetime=null,
@Deleted char(1)=null

मेरे लिए यह चाल चली।

मुझे आशा है कि यह किसी ऐसे व्यक्ति के लिए उपयोगी होगा जो समान जाल में आते हैं।


3

यदि टेम्प्लेट सेट नहीं है (अर्थात = null), तो यह त्रुटि भी उठाई जाएगी।

अधिक टिप्पणियाँ:

यदि आप मापदंडों को जोड़ते समय पैरामीटर मान जानते हैं, तो आप AddWithValue का उपयोग भी कर सकते हैं

EXEC की आवश्यकता नहीं है। आप सीधे चयन में @template पैरामीटर को संदर्भित कर सकते हैं।


0

पहला - वह EXEC क्यों है? ऐसा नहीं होना चाहिए

AS
SELECT Column_Name, ...
FROM ...
WHERE TABLE_NAME = @template

वर्तमान सपा मतलब नहीं है? विशेष रूप से, जो @template से मेल खाने वाले कॉलम की तलाश करेगा, न कि @template के varchar मान का। अगर @template है 'Column_Name', तो यह खोज करेगा WHERE TABLE_NAME = Column_Name, जो बहुत ही दुर्लभ है (तालिका और स्तंभ नाम समान है)।

इसके अलावा, अगर आपको डायनेमिक एसक्यूएल का उपयोग करना है , तो आपको EXEC sp_ExecuteSQLइंजेक्शन के हमलों (इनपुट के संघटन के बजाय) को रोकने के लिए (मान को मापदंडों के रूप में रखते हुए) का उपयोग करना चाहिए । लेकिन इस मामले में यह आवश्यक नहीं है।

वास्तविक समस्या को फिर से देखें - यह एक नज़र से ठीक लगता है; क्या आप सुनिश्चित हैं कि आपके पास एसपी की एक अलग प्रति नहीं है? यह एक सामान्य त्रुटि है ...


यह अभी भी उस परिवर्तन के साथ काम नहीं करता है। मेरे पास निष्पादन था क्योंकि मैं पहले एक प्रोक के साथ काम कर रहा था, जहां एक परम से क्लॉज की आपूर्ति की गई थी, इसलिए मैं इस पर गलत तरीके से सोच रहा था। लेकिन मुझे अभी भी सिलेक्शन के साथ त्रुटि मिलती है
टोनी पीटरसन

बहुत जिज्ञासु; शायद टाइपो के लिए तिहरा-जांच?
मार्क Gravell

0

मैं आज इस त्रुटि के सामने आया जब शून्य मान मेरी संग्रहीत कार्यविधि के मापदंडों में पारित हो गए। मैं डिफ़ॉल्ट मान = अशक्त जोड़कर संग्रहीत कार्यविधि को बदलकर आसानी से ठीक करने में सक्षम था।


0

मेरे पास एक ही मुद्दा था, इसे हल करने के लिए बस अपने पैरामीटर संग्रह में ठीक उसी पैरामीटर का नाम जोड़ें जैसा कि आपकी संग्रहीत प्रक्रियाओं में है।

उदाहरण

मान लें कि आप एक संग्रहीत प्रक्रिया बनाते हैं:

create procedure up_select_employe_by_ID 
     (@ID int) 
as
    select * 
    from employe_t 
    where employeID = @ID

तो अपने पैरामीटर को ठीक उसी तरह नाम देना सुनिश्चित करें जैसे यह आपके संग्रहीत कार्यविधि में है

cmd.parameter.add("@ID", sqltype,size).value = @ID

अगर तुम जाते हो

cmd.parameter.add("@employeID", sqltype,size).value = @employeid 

तब त्रुटि होती है।


0

यह बताना आवश्यक है कि एक स्टोर्ड प्रोक कहा जा रहा है:

comm.CommandType = CommandType.StoredProcedure;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.