提问人:mechanicalMuse 提问时间:8/5/2023 最后编辑:mechanicalMuse 更新时间:8/8/2023 访问量:89
从MS Access VBA中的直通查询中检索输出参数?PT 查询执行程序。插入新记录的存储过程,我需要获取其 ID
Retrieving output parameter from passthrough query in MS Access VBA? PT query execs. a stored procedure inserting a new record, I need to get its id
问:
有没有办法使用具有输入和输出参数的直通查询来运行存储过程?如果是这样,如何使用VBA检索MS Access中的输出参数值?
有问题的存储过程插入了一条新记录,我需要获取新创建的记录 ID。
这是我的存储过程:
ALTER PROCEDURE [dbo].[sp_two_Insert]
@woTitle nvarchar(255),
@woWriter int,
@woDate date,
@woid int = 0 OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.two (woTitle, writtenby, wodate)
VALUES (@woTitle, @woWriter, @woDate);
SELECT @woid = SCOPE_IDENTITY();
END
先谢谢大家!
我尝试了这些代码片段:
尝试#1:
来自Gord Thompson的 https://stackoverflow.com/a/46086366/9604983
VBA每次在行上都会崩溃:,它会无限期地卡住创建新记录,所以我必须通过任务管理器退出程序。 Set rs = ptq.OpenRecordset
但是,同样尝试 #1,MS Access 在 时崩溃,并产生相同的后果。Set rs = rs.NextRecordset
我不认为galla_在“Replies(1)”部分下给出的解决方案对我有用,因为我需要插入查询创建的记录的 ID,并且在插入之后立即运行第二个存储过程,肯定会获得创建的最后一条记录的 ID,但不一定是首先运行的插入存储过程创建的记录的 ID。
这是崩溃的VBA代码:
Option Compare Database
Option Explicit
Sub ptqTest()
Dim cdb As DAO.Database
Dim rs As DAO.Recordset
Set cdb = CurrentDb
Set rs=cdb.OpenRecordset("qPtMyPassThroughQ") ‘this is where Ms
Access crashes
rs.Close
Set rs = Nothing
Set cdb = Nothing
End Sub
答:
好的,你这里有一些错误。
如果要使用或设置输出参数,则代码应按如下方式编写:
CREATE PROCEDURE [dbo].[AddHotel]
@FirstName nvarchar(50),
@LastName nvarchar(50),
@HotelName nvarchar(50),
@newPK int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO tblHotelsA (FirstName, LastName, HotelName)
VALUES (@FirstName, @LastName, @HotelName)
SET @newPK = SCOPE_IDENTITY()
END
请注意,输出值不是由 select 创建的。因此,上面的存储过程执行插入,然后设置 OUTPUT 参数。
但是,实际上,我认为没有必要或使用输出值的优势,因为使用 SELECT 返回值要容易得多。
那么,我能想到的唯一用例是将 OUTPUT 参数(并返回)到 MS-access?
这将是一个“用例”,其中存储过程由其他人编写,因此是一组现有 T-SQL 代码例程(以及那些其他例程需要并使用 OUTPUT 参数)的一部分。换句话说,当存储过程由您选择时,我不会以这种方式编写存储过程。
但是,我们仍然展示如何获取/使用/享受该返回值,因为您在软件旅行中很可能会遇到上述用例。
所以,说上面的存储过程。
因此,MS-Access VBA代码可以这样编写:
解决方法包括将存储过程调用“包装”在 2 行额外的代码中。(一个 T-SQL 变量声明和一个 SELECT 语句,用于将该输出值转换为 DAO 记录集返回)。
因此,这将适用于上述情况:
Dim newPK As Long
Dim strSQL As String
Dim sFirstName As String
Dim sLastName As String
Dim sHotelName As String
sFirstName = "Albert"
sLastName = "Kallal"
sHotelName = "My Cool Hotel"
strSQL = "declare @MyPK int;" & _
"exec dbo.AddHotel " & _
"@FirstName = '" & sFirstName & "'," & _
"@LastName = '" & sLastName & "'," & _
"@HotelName = '" & sHotelName & "'," & _
"@newPK = @MyPK OUTPUT;" & _
"SELECT @MyPK AS MyNewPKTest;"
With CurrentDb.QueryDefs("qryPassR")
.ReturnsRecords = True
.SQL = strSQL
newPK = .OpenRecordset()(0)
End With
现在,请注意上面的 BEYOND CLOSE:
请注意,返回值的 T-SQL 语法是“向后”的。这不是 MS-Access 人脸植物,而是 T-SQL 所需的令人困惑的语法。返回的参数值保留在上述表达式的左侧!
正如我所指出的,以上是解决方法,只有在您遇到无法更改的现有存储过程时才需要。
但是,可以这样编写上述存储过程:
CREATE PROCEDURE [dbo].[AddHotel]
@FirstName nvarchar(50),
@LastName nvarchar(50),
@HotelName nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO tblHotelsA (FirstName, LastName, HotelName)
VALUES (@FirstName, @LastName, @HotelName)
select SCOPE_IDENTITY()
END
因此,在上面,我们不使用输出参数(也不需要输出参数)。并代替 SET 命令来设置返回(输出)值?
我们使用一个简单的 SELECT 语句,这导致返回单个标准 DAO 数据行。
因此,我们的 VBA 代码现在如下所示:
strSQL = "exec dbo.AddHotel " & _
"@FirstName = '" & sFirstName & "'," & _
"@LastName = '" & sLastName & "'," & _
"@HotelName = '" & sHotelName & "'"
With CurrentDb.QueryDefs("qryPassR")
.ReturnsRecords = True
.SQL = strSQL
newPK = .OpenRecordset()(0)
End With
或者,它甚至可以以这种格式编写,但由于参数顺序很重要,因此需要谨慎。
所以,这个语法:
strSQL = "exec dbo.AddHotel '" & _
sFirstName & "','" & sLastName & "','" & sHotelName & "'"
With CurrentDb.QueryDefs("qryPassR")
.ReturnsRecords = True
.SQL = strSQL
newPK = .OpenRecordset()(0)
End With
请注意我用于返回记录集的简写。
这行代码:
newPK = .OpenRecordset()(0)
可以写成这样的长格式:
dim rstReturn as DAO.RecordSet
... same above code here, and then
set rstReturn = .OpenRecordSet
End With
然后,要获取该值,请使用:
rstReturn(0) ' first column.
或者,可以使用 T-SQL 语句中返回的列名。
rstReturn!newPK, or rstReturn("newPK")
同样,如果要将列名称用于返回值,请确保在 T-SQL 中设置该列
例如:
select SCOPE_IDENTITY() as newPK
因此,VBA DAO 不直接支持 T-SQL 返回(输出)参数。
但是,它们很少得到保证,并且只有在无法更改 T-SQL 例程时才需要上述第一个解决方法。
另请注意我如何使用现有的创建的直通查询,因此假定已为该 Access 直通查询创建和设置了连接设置。
评论
sp_
sp_
qPtMyPassThroughQ