虽然我发送参数我得到"不能插入NULL值..."

时间:2014-08-19 11:52:54

标签: sql tsql stored-procedures

我正在开发一个ADO.NET应用程序。在DAL中的某个时刻,我调用名为“CREATE_CUSTOMER”的存储过程。虽然我设置了SHORT_NAME字段,但仍然可以获得

"Msg 515, Level 16, State 2, Procedure CREATE_CUSTOMER, Line 29
Cannot insert the value NULL into column 'SHORT_NAME', table 'MYDB.app.CUSTOMER';
column does not allow nulls. INSERT fails." error.

当我使用SQL事件探查器检查查询时,我在服务器上运行以下SQL。当我将它复制并粘贴到新的查询窗口时,我仍然得到相同的错误。

我错过了什么吗?

declare @p16 int
set @p16=NULL

exec sp_executesql N'[app].[CREATE_CUSTOMER]',
N'@SHORT_NAME nvarchar(11),
@MAIL_NAME nvarchar(18),
@MT_SALESPERSON_ID int,
@CREDIT_LIMIT decimal(1,0),
@CREDIT_LIMIT_CURRENCY_ID int,
@PAYMENT_TYPE_ID int,
@SALES_TERM_ID int,
@FREE_STORAGE_DAY_ID int,
@RISK_GROUP_ID int,
@SECTOR_ID int,
@OCCUPATION_ID int,
@STORAGE_FEE_ID int,
@STATUS smallint,
@IDENTITY int output',

@SHORT_NAME=N'NEW Corp',
@MAIL_NAME=N'NEW Corporation',
@MT_SALESPERSON_ID=3,
@CREDIT_LIMIT=0,
@CREDIT_LIMIT_CURRENCY_ID=1,
@PAYMENT_TYPE_ID=4,
@SALES_TERM_ID=7,
@FREE_STORAGE_DAY_ID=6,
@RISK_GROUP_ID=3,
@SECTOR_ID=13,
@OCCUPATION_ID=16,
@STORAGE_FEE_ID=6,
@STATUS=0,
@IDENTITY=@p16 output

select @p16

我的存储过程如下:

CREATE PROCEDURE [app].[CREATE_CUSTOMER]
    @SHORT_NAME varchar(250) = NULL,
    @MAIL_NAME varchar(500) = NULL,
    @MT_SALESPERSON_ID int = NULL,
    @CREDIT_LIMIT decimal(18,2) = NULL,
    @CREDIT_LIMIT_CURRENCY_ID int = NULL,
    @PAYMENT_TYPE_ID int = NULL,
    @SALES_TERM_ID int = NULL,
    @FREE_STORAGE_DAY_ID int = NULL,
    @RISK_GROUP_ID int = NULL,
    @SECTOR_ID int = NULL,
    @OCCUPATION_ID int = NULL,
    @STORAGE_FEE_ID int = NULL,
    @STATUS tinyint = NULL,

    @IDENTITY INT = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;

INSERT INTO [app].[CUSTOMER]
       ([SHORT_NAME],
        [MAIL_NAME],
        [MT_SALESPERSON_ID],
        [CREDIT_LIMIT],
        [CREDIT_LIMIT_CURRENCY_ID],
        [PAYMENT_TYPE_ID],
        [SALES_TERM_ID],
        [FREE_STORAGE_DAY_ID],
        [RISK_GROUP_ID],
        [SECTOR_ID],
        [OCCUPATION_ID],
        [STORAGE_FEE_ID],
        [STATUS],
        [CREATE_DATE],
        [CREATE_USERID])
VALUES
       (@SHORT_NAME,
        @MAIL_NAME,
        @MT_SALESPERSON_ID,
        @CREDIT_LIMIT,
        @CREDIT_LIMIT_CURRENCY_ID,
        @PAYMENT_TYPE_ID,
        @SALES_TERM_ID,
        @FREE_STORAGE_DAY_ID,
        @RISK_GROUP_ID,
        @SECTOR_ID,
        @OCCUPATION_ID,
        @STORAGE_FEE_ID,
        @STATUS,
        GETDATE(),
        CONTEXT_INFO())

SELECT @IDENTITY = SCOPE_IDENTITY()
END

此SQL代码由ADO.NET生成。实际的C#代码是:

    private static ICustomer CreateCustomer(ICustomer customer, int contextUserId)
    {
        try
        {
            string sql = "[app].[CREATE_CUSTOMER]";
            SqlConnection conn = null;
            using (conn = GetConnection())
            {
                SetContextInfomationToConnection(conn, contextUserId);
                SqlCommand cmd = new SqlCommand(sql, conn);
                cmd.Parameters.AddWithValue("@SHORT_NAME", customer.ShortName);
                cmd.Parameters.AddWithValue("@MAIL_NAME", customer.MailName);
                cmd.Parameters.AddWithValue("@MT_SALESPERSON_ID", customer.SalesPersonId);
                cmd.Parameters.AddWithValue("@CREDIT_LIMIT", customer.CreditLimit);
                cmd.Parameters.AddWithValue("@CREDIT_LIMIT_CURRENCY_ID", customer.CreditLimitCurrencyId);
                cmd.Parameters.AddWithValue("@PAYMENT_TYPE_ID", customer.PaymentTypeId);
                cmd.Parameters.AddWithValue("@SALES_TERM_ID", customer.SalesTermId);
                cmd.Parameters.AddWithValue("@FREE_STORAGE_DAY_ID", customer.FreeStorageDayId);
                cmd.Parameters.AddWithValue("@RISK_GROUP_ID", customer.RiskGroupId);
                cmd.Parameters.AddWithValue("@SECTOR_ID", customer.SectorId);
                cmd.Parameters.AddWithValue("@OCCUPATION_ID", customer.OccupationId);
                cmd.Parameters.AddWithValue("@STORAGE_FEE_ID", customer.StorageFeeId);
                cmd.Parameters.AddWithValue("@STATUS", customer.Status);

                SqlParameter prmNewId = new SqlParameter("@IDENTITY", SqlDbType.Int, 4);
                prmNewId.Direction = ParameterDirection.Output;
                cmd.Parameters.Add(prmNewId);

                cmd.ExecuteNonQuery();
                int id = prmNewId.Value != DBNull.Value ? (int)prmNewId.Value : -1;
                if (id > 0)
                {
                    customer.Id = id;
                    return customer;
                }
                else
                {
                    throw new Exception("Can not insert customer record with Id generation");
                }
            }
        }
        catch (Exception ex)
        {
            throw;
        }
    }

2 个答案:

答案 0 :(得分:1)

您的代码相当于这样做:

DECLARE @SHORT_NAME nvarchar(11) = N'NEW Corp';
...
EXEC [app].[CREATE_CUSTOMER];

您只是声明参数,从未实际将它们传递给过程调用。你的代码应该是这样的:

exec sp_executesql N'[app].[CREATE_CUSTOMER] @SHORT_NAME, @MAIL_NAME, ...',
   N'@SHORT_NAME nvarchar(11),
     @MAIL_NAME nvarchar(18),
     ...',
    @SHORT_NAME=N'NEW Corp',
    @MAIL_NAME=N'NEW Corporation',
    ...

您不仅必须声明传递给批处理的参数,还必须在调用该程序时使用它们。

  

当我使用SQL事件探查器检查查询时,我在服务器上运行以下SQL。当我将它复制并粘贴到新的查询窗口时,我仍然得到相同的错误

这听起来很可疑,就像您使用的是SqlCommand,但忘了将CommandType设置为Procedure。默认值为Text,其行为与您观察到的完全相同。

答案 1 :(得分:0)

不要为ur变量赋值空值,只能尝试将其声明为

DECLARE @SHORT_NAME varchar(250),

而不是

@SHORT_NAME varchar(250)= NULL,