【问题标题】:SQL Server stored procedure with SCOPE_IDENTITY and ADO.NET parameterized query具有 SCOPE_IDENTITY 和 ADO.NET 参数化查询的 SQL Server 存储过程
【发布时间】:2012-10-12 18:59:34
【问题描述】:

我的存储过程应该返回我新创建的行的标识,但事实并非如此。

存储过程语法(简而言之):

Alter Procedure dbo.udsp_insert_record
    @record_title VARCHAR(100)
AS
BEGIN
    INSERT INTO tbl_records (RecordTitle) VALUES (@record_title)
    SELECT SCOPE_IDENTITY()
END

当我在 SQL Server Management Studio 中执行该过程时,这将按预期工作——插入一个新行并返回其标识。但是,当我从我的网络应用程序执行时,使用下面的代码,我得到一个错误。

dim obj_command as New SqlCommand("udsp_insert_record",obj_connection)
obj_command.CommandType = CommandType.StoredProcedure
obj_command.Parameters.Add("@record_title",SqlDbType.VarChar).Value = "just testing"
dim n_new_record_id as Integer = obj_command.ExecuteScalar()
obj_command.Dispose()  'etc., etc.

运行时出现错误

输入的字符串格式不正确

使用ExecuteScalar 命令。

我的解释是 SQL Server 没有返回一个整数值——它必须返回一个对象,或者一个DBNull,或者其他东西。

但这是为什么呢? INSERTSELECT SCOPE_IDENTITY() 发生在同一范围内,因此 SQL Server 交回的标识值必须是有效的(我通过 SQL Server Management Studio 进行的测试证明了这一点)。

我想我在某处读到,当您在 ADO.NET 中使用与 SQL Server 存储过程对话的参数化查询时,范围不是您所期望的,因为它实际上使用另一个存储过程来执行您询问的那个为了。这有什么好处吗?

有什么想法吗?

编辑:使用SELECT CAST(SCOPE_IDENTITY() AS INT) 也不起作用。另外:即使我没有将 ExecuteScalar 的结果分配给 Integer 值,我也会收到此错误 - 即使我只是执行response.write obj_command.ExecuteScalar()

,我也会收到相同的错误

【问题讨论】:

    标签: asp.net sql-server stored-procedures


    【解决方案1】:

    我会尝试稍微改变存储过程:

    Alter Procedure dbo.udsp_insert_record
      @record_title VARCHAR(100)
    AS
    BEGIN
      INSERT INTO tbl_records (RecordTitle) VALUES (@record_title)
      SELECT CAST(SCOPE_IDENTITY() AS INT)
    END
    

    据我所知,SCOPE_IDENTITY() 是十进制类型,因此您不能轻易将其转换为 int。您可以在服务器上(如我建议的那样)或在客户端上执行此操作,方法是将 ExecuteScalar 转换为 Decimal

    【讨论】:

    • 我已经尝试过 CAST 方法(和 CONVERT)——同样的错误。而且这种语法(没有 CAST)在同一台服务器上的许多其他存储过程中都可以完美地工作。另外,我编辑了我的原始帖子以反映即使我没有将标量的结果分配给整数值,我也会收到此错误 - 即使我只是执行response.write obj_command.ExecuteScalar()
    • 唯一可能的解释是您的表的主键不是整数类型。检查您的表定义。
    • 好主意,@Wiktor Zychla。但它绝对是一个 INT 列。还有主键,身份增量=1,等等等等。
    【解决方案2】:

    ExecuteScaler 总是返回一个对象数据类型。所以要从中检索整数值,你必须像这样转换它。

    例如。

    object id=cmd.ExecuteScaler(...........
    if(id != null)
    {   
     int newId=Convert.ToInt32(id);
    }
    

    【讨论】:

    • 更改您的代码以检查nulls 或使用Int32.TryParse,您的答案与OP(原始海报)所做的没有什么不同
    猜你喜欢
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多