我正在尝试修改现有的Access应用程序,以便通过ODBC将MySQL用作数据库,并且记录的次数最少。
当前代码通常会使用DAO插入新记录,然后使用LastModified获取ID。这不适用于MySQL。相反,我正在尝试使用
方法SELECT * FROM tbl_name WHERE auto_col IS NULL
建议MySQL documentation中的访问权限。但是,如果我设置一个仅包含id和text数据字段的示例表并执行此
CurrentDb.Execute ("INSERT INTO tbl_scratch (DATA) VALUES ('X')")
Set rst = CurrentDb.OpenRecordset("SELECT id FROM tbl_scratch WHERE id IS NULL")
myid = rst!id
ID返回null。但是,如果我执行
INSERT INTO tbl_scratch (DATA) VALUES ('X');
SELECT id FROM tbl_scratch WHERE id IS NULL;
使用直接MySQL编辑器然后正确返回id,所以我的数据库和方法很好,但我在Access中的实现必须是不正确的。令人沮丧的是,MySQL文档提供了SQL语句来检索id作为在Access中工作的示例(因为它声明LAST_INSERT_ID()没有)但没有提供进一步的细节。
我该如何解决这个问题?
答案 0 :(得分:1)
解决(和博客)如下
我一直在为一组Access数据库实现升级,以使用ODBC链接的MySQL替换Access文件数据库。除了将记录插入具有自动增量id列的表并检索刚创建的id的值的常见概念之外,一切似乎都非常顺利。当然,对于PHP等,只需使用
即可SELECT LAST_INSERT_ID()
检索ID的功能。但是,MySQL文档本身表示这不适用于某些ODBC应用程序,如Delphi或Access,并建议使用
SELECT * FROM tbl WHERE auto IS NULL;
不幸的是,当我从我正在使用的Access应用程序内部调用时,这对我来说根本不起作用,并且在Web上似乎有几条评论确实这是不可靠的,因为Access可能会丢弃数据连接并重新连接到场景 - 从而使通话无效。
作为替代方案,我决定使用MySQL函数向表中添加空白记录,返回Access然后用于更新记录的id(这与现有应用程序的代码样式非常吻合)。不幸的是,这显然简单的解决办法也不是很简单,因为MySQL中长期存在的错误使得找到有效的代码可以发送和返回变量。 Web上的几个示例将在仅使用IN或OUT变量的有限域内工作,但无法同时使用这两个变量。
我的最终解决方案,适用于我正在部署的MySQL 5.1和Access 2003组合,如下所示
MySQL程序
DELIMITER $$
CREATE
PROCEDURE `alicedata`.`sp_ins_identity`(IN tablename VARCHAR(50))
BEGIN
SET @result = 0;
SET @sqlproc = CONCAT("INSERT INTO ",tablename," () VALUES ();");
PREPARE s1 FROM @sqlproc;
EXECUTE s1;
DEALLOCATE PREPARE s1;
SELECT LAST_INSERT_ID();
END$$
此过程很有用,因为它将插入一行并返回任何表的id,其中一行包含所有空字段或定义了默认值的非空字段。要调用它,我使用以下函数:
Public Function InsertMySQLIdentityRow(DSN As String, Tablename As String) As Integer
On Error GoTo Err_InsertMySQLIdentity
Dim cnnSQL As New ADODB.Connection
Dim cmdSQL As ADODB.Command
Dim pid As Integer
Dim rs
Dim strSQL As String
' initialize
pid = 0
' set up ADO connection
Set cnnSQL = New ADODB.Connection
cnnSQL.Open DSN
' execute the procedure - note that assembling by parameter fails to handle IN or OUT correctly
Set cmdSQL = New ADODB.Command
cmdSQL.ActiveConnection = cnnSQL
strSQL = "call sp_ins_identity('" & Tablename & "');"
Set rs = CreateObject("ADODB.Recordset")
Set rs = cnnSQL.Execute(strSQL)
If Not rs.EOF Then
pid = rs(0)
End If
' clean up
Set rs = Nothing
Set cmdSQL = Nothing
cnnSQL.Close
Set cnnSQL = Nothing
Exit_InsertMySQLIdentity:
InsertMySQLIdentityRow = pid
Exit Function
Err_InsertMySQLIdentity:
MsgBox Err.Number & Err.Description
Resume Exit_InsertMySQLIdentity
End Function
这段代码有点不寻常,因为通常在MSSQL上你会使用参数化过程调用,但是由于MySQL ODBC中的错误(或者至少与Access不兼容),上面似乎是允许两者的唯一方法要传递和返回的数据。