0

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

我正在尝试获取在 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 对象保持打开状态,直到超出范围。以下是观看部分的截图:

选择语句

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

插入语句

4

2 回答 2

1

insert您可以使用子句显式保存语句的结果,output并使用以下命令返回结果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可以与insert、和一起使用update,并且在 的情况下提供对之前之后值的访问。一个非常值得放在口袋里的工具。deletemergeupdate

于 2019-12-26T15:03:31.053 回答
0

事实证明,我试图插入的表附有多个触发器。因此,包含 SELECT SCOPE_IDENTITY(); 的查询 实际上是第四个查询。为了获得正确的范围,我不得不向前移动 4 个查询。我如何以编程方式实现这一点如下。不是很干净(也可能不是最好的方法),但为我完成了这项工作。

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

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 cQry.Query, pConn, adOpenKeyset, adLockOptimistic

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

    On Error Resume Next
    'begin loop
    Do
        'go to next recordset
        Set rs = rs.NextRecordset()

        'if we're getting error n. 91, it means 
        'recordsets are exhausted, hence we're getting
        'out of the loop 
        If Err.Number = 91 Then
            Err.Clear
            Exit Do
        End If

        'if we are not out of recordsets, check the 
        'result of the query. If it is bigger then zero, 
        'it means we hit the jackpot. 
        If rs.Fields(0).Value > 0 Then
            pInsertedId = rs.Fields(0).Value
        End If
    Loop
    On Error GoTo 0

End Function

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

于 2019-12-26T12:24:24.393 回答