【问题标题】:Difference between adding parameters to stored procedure in SQL Server?在 SQL Server 中向存储过程添加参数的区别?
【发布时间】:2011-03-26 22:14:38
【问题描述】:

我想知道这两种符号之间的区别。

首先我有一个存储过程

CREATE PROCEDURE AddSomething( @zonename varchar(50), @desc varchar(255), @TheNewId int OUTPUT ) AS 
BEGIN 
   INSERT INTO a_zone(zonename, descr) VALUES(@zonename, @desc) 
   SELECT @TheNewId = SCOPE_IDENTITY()         
END

如果我以这种方式添加参数有什么区别

SqlCommand Cmd = new SqlCommand("AddSomething", oConn); 
Cmd.CommandType = CommandType.StoredProcedure; 
SqlParameter oParam1 = Cmd.Parameters.AddWithValue("@zonename", sName);
SqlParameter oParam2 = Cmd.Parameters.AddWithValue("@desc", description);

SqlCommand Cmd2 = new SqlCommand("AddSomething", oConn); 
Cmd2.CommandType = CommandType.StoredProcedure;
cmd2.Parameters.Add("@zonename", SqlDbType.VarChar).Value = zonename.Text.Trim();
cmd2.Parameters.Add("@desc", SqlDbType.VarChar).Value = desc.Text.Trim();

【问题讨论】:

    标签: sql-server stored-procedures parameters ado.net


    【解决方案1】:

    这里有一些解释:

    difference between command Add and AddWithValue

    Dim cmd as new SqlCommand("SELECT * FROM MyTable WHERE MyDate>@TheDate",conn)
    cmd.Parameters.Add("@TheDate",SqlDbType.DateTime).Value="2/1/2007"
    

    cmd.Parameters.AddWithValue("@TheDate","2/1/2007")
    

    “当它进入参数时,Add 会强制从字符串转换为日期。AddWithValue 会简单地将字符串传递给 SQL Server。

    当使用Parameters.Add - SqlDbType 在编译时是已知的

    当使用Parameters.AddWithValue 时,该方法必须对值进行装箱和拆箱以找出其类型。

    前者的额外好处是Add 的代码更安全 并将协助抵御 SQL 注入攻击,代码安全 如果您尝试传递与 SqlDb 类型不匹配的值 已定义 - 错误将在 .Net 代码中捕获,您将不会拥有 等待往返。

    编辑

    获取输出参数的示例:

    C#

    cmd.Parameters.Add(new SqlParameter("@TheNewId", SqlDbType.Int, int.MaxValue));
    cmd.Parameters("@TheNewId").Direction = ParameterDirection.Output;
    cmd.ExecuteNonQuery();
    int theNewID = (int)cmd.Parameters("@TheNewId").Value;
    

    VB.Net

    cmd.Parameters.Add(New SqlParameter("@TheNewId", SqlDbType.Int, Int32.MaxValue))
    cmd.Parameters("@TheNewId").Direction = ParameterDirection.Output
    cmd.ExecuteNonQuery()
    Dim theNewID As Int32 = DirectCast(cmd.Parameters("@TheNewId").Value, Int32)
    

    【讨论】:

    • @Tim 所以你的意思是这两种方法都用于将参数传递给存储过程。
    • @user653622:是的,但不仅适用于存储过程,还适用于各种 sql 命令。它们都有优点和缺点(见链接)。
    • @Tim 如何使用第二种方法来传递输出类型参数,尤其是当我没有要传递的任何值但我期望来自存储过程的值时。特别是在这种情况下 cmd2.Parameters.Add("@TheNewId", SqlDbType.Int).Value = ???;如果我使用第二种方法,它会期望一个值,但我必须明确告诉它不要期望一个值作为输出参数,我应该怎么告诉这个?请帮帮我
    • @Tim 你的例子在 asp.net/c# 中不起作用,因为 SqlParameter 没有那个重载方法。相反,此过程有效 SqlParameter outputParameter1 = new SqlParameter("@NewIntId", SqlDbType.Int); outputParameter1.Direction = ParameterDirection.Output; cmd2.Parameters.Add(outputParameter1); cmd2.ExecuteNonQuery(); int valueFromOutputParameter = (int)cmd2.Parameter["@NewIntId"].Value
    【解决方案2】:

    当您使用 AddWithValue 时,将根据传递给方法的变量类型(尽可能)计算出数据类型 - 假设 sName 和 description 是字符串变量,参数将作为 NVARCHAR 传递。

    我个人更喜欢第二种方法,对数据类型进行明确说明(而且我实际上也指定了大小),以便保证它们与存储过程定义匹配并避免任何意外行为。

    【讨论】:

    • +1 完全正确 - 而不是让太多的“魔法”决定你的类型。另外:如果您需要通过,例如DBNull.Value - ADO.NET 运行时如何能够确定您的“NULL”将是什么类型!?!?!明确 - 输入更多一点,但更安全和清晰(想想:维护!)
    猜你喜欢
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 2016-02-25
    • 2013-05-06
    • 2015-11-20
    • 1970-01-01
    相关资源
    最近更新 更多