当我尝试通过存储过程插入空值时出现 SqlException

Posted

技术标签:

【中文标题】当我尝试通过存储过程插入空值时出现 SqlException【英文标题】:Getting a SqlException when I try to insert null values through a stored procedure 【发布时间】:2013-08-28 21:57:49 【问题描述】:

我有一个表,它接受一堆参数,并使用 INSERT INTO 语句通过存储过程将其保存为新联系人。出于某种原因,当我的某些参数为空时,我得到了一个 SqlException。在 SQL Server 表中,所有留空的参数确实可以为空,所以我不明白这个问题。我的想法是,我的 INSERT 语句正在接受所有参数,即使它们为 null 并尝试将它们插入到我的表中,我认为这是语法上的“no-no”

不管怎样,这里是 C# 代码:

try
    
        using (SqlConnection sqlConn = new SqlConnection(connectionString))
        
            using (SqlCommand cmd = new SqlCommand("Insert_NewContact", sqlConn))
            
                sqlConn.Open();

                cmd.CommandType = CommandType.StoredProcedure;

                cmd.Parameters.AddWithValue("@CompanyID", CompanyID);
                cmd.Parameters.AddWithValue("@email", email);
                cmd.Parameters.AddWithValue("@phone", phone);
                cmd.Parameters.AddWithValue("@fax", fax);
                cmd.Parameters.AddWithValue("@fName", fName);
                cmd.Parameters.AddWithValue("@lName", lName);
                cmd.Parameters.AddWithValue("@sendVia", sendVia);                   
                cmd.Parameters.AddWithValue("@default", defaultContact);
                cmd.Parameters.AddWithValue("@repo", repo);
                cmd.Parameters.AddWithValue("@fail", fail);
                cmd.Parameters.AddWithValue("@borrow", borrow);
                cmd.Parameters.AddWithValue("@loan", loan);

                cmd.ExecuteNonQuery();

                sqlConn.Close();
            
        
    
    catch (Exception e)
    
        throw e;
    

这是SQL中的存储过程:

ALTER PROCEDURE [dbo].[Insert_NewContact]

@CompanyID  INT,
@email      VARCHAR(50),
@phone      VARCHAR(50),
@fax        VARCHAR(50),
@fName      VARCHAR(50),
@lName      VARCHAR(50),
@sendVia    VARCHAR(50),
@default    BIT,
@repo       TINYINT,
@fail       TINYINT,
@borrow     TINYINT,
@loan       TINYINT

AS
 BEGIN
    SET NOCOUNT ON;

BEGIN TRY

    INSERT INTO Master_Contacts(
                                    companyID, 
                                    fName, 
                                    lName, 
                                    phone, 
                                    email, 
                                    fax, 
                                    send_via, 
                                    defaultcontact, 
                                    repoRole, 
                                    borrowRole, 
                                    failRole, 
                                    loanRole
                                )
    VALUES                      (
                                    @CompanyID,
                                    @fName,
                                    @lName,
                                    @phone,
                                    @email,
                                    @fax,
                                    @sendVia,
                                    @default,
                                    @repo,
                                    @borrow,
                                    @fail,
                                    @loan
                                )                   
END TRY

不知道为什么 AS BEGIN 和 NOCOUNT 如此奇怪,但它们在存储过程中是正确的。

无论如何,如果我在我的应用程序中将电子邮件、电话、传真等留空,我会收到此错误:

SqlException 未被用户代码处理 过程或函数“Insert_NewContact”需要参数“@email”,但未提供。

如何编辑我的存储过程以使其使用空值?

【问题讨论】:

【参考方案1】:

设置参数的默认值为null,试试这个:

@CompanyID  INT,
@email      VARCHAR(50) = null,
@phone      VARCHAR(50)  = null,
@fax        VARCHAR(50)  = null,
@fName      VARCHAR(50) = null,
@lName      VARCHAR(50),
@sendVia    VARCHAR(50),
@default    BIT,
@repo       TINYINT,
@fail       TINYINT,
@borrow     TINYINT,
@loan       TINYINT

【讨论】:

那行得通。考虑到这很容易,我觉得很愚蠢。非常感谢!【参考方案2】:

当您有一个空值时,您应该传递 DBNull.Value。例如。

 cmd.Parameters.AddWithValue("@email", email == null ? DBNull.Value : (object)email);

【讨论】:

这比上面的方法更安全吗? ***.com/questions/4958379/… 非常感谢您的跟进。很有教育意义的读物,肯定会影响未来的编程决策。【参考方案3】:
ALTER PROCEDURE [dbo].[Insert_NewContact]

@CompanyID  INT,
@email      VARCHAR(50) = null,
@phone      VARCHAR(50) = null,
@fax        VARCHAR(50) = null,
@fName      VARCHAR(50) = null,
@lName      VARCHAR(50) = null,
@sendVia    VARCHAR(50) = null,
@default    BIT = 0,
@repo       TINYINT = 0,
@fail       TINYINT = 0,
@borrow     TINYINT = 0,
@loan       TINYINT = 0

AS
BEGIN
SET NOCOUNT ON;

BEGIN TRY

INSERT INTO Master_Contacts(
                                companyID, 
                                fName, 
                                lName, 
                                phone, 
                                email, 
                                fax, 
                                send_via, 
                                defaultcontact, 
                                repoRole, 
                                borrowRole, 
                                failRole, 
                                loanRole
                            )
VALUES                      (
                                @CompanyID,
                                @fName,
                                @lName,
                                @phone,
                                @email,
                                @fax,
                                @sendVia,
                                @default,
                                @repo,
                                @borrow,
                                @fail,
                                @loan
                            )                   
END TRY

【讨论】:

以上是关于当我尝试通过存储过程插入空值时出现 SqlException的主要内容,如果未能解决你的问题,请参考以下文章

当我尝试通过 C# 将日期插入 Access 数据库时出现“INSERT INTO 语句中的语法错误”错误

Asp.Net 在运行存储过程时出现超时错误

CASE表达式总和-加入其他表时出现的问题

示例数据 - “执行包含更新和插入语句的存储过程时出现问题”

尝试使用 .NET Core 执行存储过程时出现“ORA-03115:不支持的网络数据类型或表示”

oracle 存储过程循环插入数据不定时出现卡死,求高手指点,循环过程如下: