SELECT SCOPE_IDENTITY()返回最后插入的ID

时间:2019-12-26 02:16:14

标签: excel vba tsql adodb scope-identity

关于这个问题有一些答案,但是我的问题是关于我拥有的特定代码。

我正在尝试获取在VBA代码上执行的此查询的最后插入的ID。

Public Function Execute(cQry As excfw_dbQuery) As ADODB.Recordset    

    If pConn.State = 0 Then
        OpenConnection
    End If

    qry = "INSERT INTO [some really long query, which actually works]; SELECT SCOPE_IDENTITY()"

    On Error Resume Next
    Dim rs As ADODB.Recordset
    Set rs = New ADODB.Recordset
    rs.Open qry, pConn 'also tried with adOpenKeyset, adLockOptimistic

    'some error handling code which is not related to the issue 

    Set rs = rs.NextRecordset() 'also tried without moving onto the next recordset
    pInsertedId = rs.Fields(0).Value

    Set Execute = rs 'this is just to pass the query result for SELECT queries 

End Function

这应该将最后插入的ID保存在pInsertedId变量上,但是每次插入一行时我都会得到0。奇怪的是,当我将相同的代码复制并粘贴到SSMS中时,它可以工作。

我可能只是将一些唯一的数据插入到数据库的一些未使用的列中并进行查询。

-更新-

我刚刚注意到,在运行SELECT查询时,rs对象将保持打开状态,直到超出范围。这是观看部分的屏幕截图:

select statement

在插入语句上,它会在查询执行后立即关闭:

insert statement

2 个答案:

答案 0 :(得分:1)

您可以使用output子句显式保存insert语句的结果,并返回带有select的结果:

qry =
  "declare @Ids as ( Id Int );" +
  "insert into MyTable ( Name ) " + ' Assuming   Id   is an identity column.
     "output Inserted.Id into @Ids " + 
     "values ( @Name );" +
  "select Id from @Ids;"

摘自output的文档:

  

INSERTED是列前缀,用于指定由   插入或更新操作。前缀为INSERTED的列反映了   UPDATE,INSERT或MERGE语句完成后的值,但   在执行触发器之前。

您可以使用output子句从行(注意复数)中获取任何数据,例如新插入的行的标识列值。 Output可以与insertupdatedeletemerge一起使用,并提供对 before after的访问值为update。值得一提的工具。

答案 1 :(得分:0)

事实证明,我要插入的表具有多个触发器。因此,查询包含SELECT SCOPE_IDENTITY();实际上是第四个查询。为了获得正确的范围,我不得不向前移动4个查询。我如何以编程方式实现这一目标的方法如下。不是很干净(可能不是最好的方法),但是对我来说却很有效。

我基本上继续下一个记录集,直到没有记录集为止,通过检查错误号91(对象变量或未设置块变量)来检测到该记录集

Undefined variable: empname (0)

同样,不是最干净,也不是最正确的方法,但是却成功了。我愿意接受任何改进或建议。

相关问题