简体   繁体   English

如何获取链接到MySQL的Access中的auto_increment字段的值?

[英]How to obtain value of auto_increment field in Access linked to MySQL?

I'm trying to modify and existing Access application to use MySQL as a database via ODBC with the minimal amount of recoding. 我正在尝试修改现有的Access应用程序,以通过最少的重新编码就可以通过ODBC将MySQL用作数据库。

The current code will often insert a new record using DAO then obtain the ID by using LastModified. 当前代码通常会使用DAO插入新记录,然后使用LastModified获得ID。 This doesn't work with MySQL. 这不适用于MySQL。 Instead I'm trying to use the approach using 相反,我正在尝试使用以下方法

SELECT * FROM tbl_name WHERE auto_col IS NULL

Suggested for Access in the MySQL documentation . 建议在MySQL文档中进行访问。 However if I set up a sample table consisting of just an id and text data field and execute this 但是,如果我设置了一个仅由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 is returned as null. ID返回为null。 However if I execute 但是如果我执行

INSERT INTO tbl_scratch (DATA) VALUES ('X');
SELECT id FROM tbl_scratch WHERE id IS NULL;

using a direct MySQL editor then id is returned correctly, so my database and approach is fine but my implementation inside Access must be incorrect. 使用直接的MySQL编辑器,然后正确返回id,因此我的数据库和方法都很好,但是Access中的实现必须不正确。 Frustratingly the MySQL documentation gives the SQL statement to retrieve the id as an example that works in Access (as it states LAST_INSERT_ID() doesn't) but gives no further details. 令人沮丧的是,MySQL文档提供了SQL语句来检索ID,作为在Access中可用的示例(因为它声明LAST_INSERT_ID()无效),但没有提供更多详细信息。

How might I fix this? 我该如何解决?

Solved (and blogged) as below 解决(和博客)如下

I've been implementing an upgrade for a set of Access databases to replace the Access file database with MySQL linked by ODBC. 我一直在对一组Access数据库进行升级,以用ODBC链接的MySQL替换Access文件数据库。 Everything seems to be going remarkably smoothly except for the common concept of inserting a record into a table with an auto-increment id column and retrieving the value of the id just created. 除了将记录插入具有自动递增id列的表中并检索刚刚创建的id的值的通用概念外,一切似乎都进行得非常顺利。 Of course on PHP or the like one would just use the 当然,在PHP或类似系统上,只需使用

SELECT LAST_INSERT_ID() 选择LAST_INSERT_ID()

Function to retrieve the ID. 检索ID的功能。 However the MySQL documentation itself says that this doesn't work for certain ODBC applications such as Delphi or Access and suggests using 但是MySQL文档本身说这不适用于某些ODBC应用程序,例如Delphi或Access,并建议使用

SELECT * FROM tbl WHERE auto IS NULL; SELECT * FROM tbl WHERE auto IS NULL;

Unfortunately this simply didn't work for me when called from inside the Access application I was working with, and there seems to be several comments around the web that indeed this is unreliable as Access may drop the data connection and reconnect behind the scenes - thus invalidating the call. 不幸的是,当我从正在使用的Access应用程序内部进行调用时,这对我根本不起作用,并且在网络上似乎有一些评论确实确实不可靠,因为Access可能会断开数据连接并在后台重新连接-因此使呼叫无效。

As an alternative I decided to use a MySQL function to add a blank record to the table, returning the id which Access would then use to update the record (which fits well with the code-style of the existing application). 作为替代方案,我决定使用MySQL函数将空白记录添加到表中,并返回ID,然后Access将使用该ID更新记录(与现有应用程序的代码样式非常吻合)。 Unfortunately this apparently straightforward work-around fails to be simple either as long-standing bugs in MySQL make finding valid code that can both send and return a variable something of a challenge. 不幸的是,由于MySQL中长期存在的bug使得寻找可以发送和返回变量的有效代码变得困难重重,因此这种看似直接的变通方法并不简单。 Several examples on the web will work within the limited domain of using either just IN or OUT variables but fail to work with both. 网络上的几个示例仅在使用IN或OUT变量的有限范围内适用,但无法同时使用两者。

My final solution, which works on the MySQL 5.1 and Access 2003 combination I am deploying, is as follows 我的最终解决方案适用于我正在部署的MySQL 5.1和Access 2003组合,如下所示

MySQL procedure 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$$

This procedure is useful in that it will insert a row and return the id for any table where a row contains all null fields or non-null fields with defaults defined. 此过程很有用,因为它将插入一行并返回任何表的ID,该表的行包含已定义默认值的所有空字段或非空字段。 To call this I use the following function: 为此,我使用以下函数:

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

This code is somewhat unusual in that normally, on MSSQL, you would use a parametrized procedure call, but due to bugs in the MySQL ODBC (or at least incompatibilities with Access) the above seems to be the only way that allows both data to be passed and returned. 这段代码有点不寻常,因为通常在MSSQL上,您将使用参数化的过程调用,但是由于MySQL ODBC中的错误(或至少与Access不兼容),上述似乎是唯一允许两个数据都被存储的方法。通过并返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM