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

如何获取链接到MySQL的Access中的auto_increment字段的值?,mysql,ms-access,Mysql,Ms Access,我正试图修改现有的Access应用程序,通过ODBC将MySQL用作数据库,并且只需最少的重新编码 当前代码通常会使用DAO插入新记录,然后使用LASTMODIFED获取ID。这不适用于MySQL。相反,我尝试使用 SELECT * FROM tbl_name WHERE auto_col IS NULL 建议在中访问。但是,如果我设置一个只包含id和文本数据字段的示例表并执行 CurrentDb.Execute ("INSERT INTO tbl_scratch (DATA) VALUES

我正试图修改现有的Access应用程序,通过ODBC将MySQL用作数据库,并且只需最少的重新编码

当前代码通常会使用DAO插入新记录,然后使用LASTMODIFED获取ID。这不适用于MySQL。相反,我尝试使用

SELECT * FROM tbl_name WHERE auto_col IS NULL
建议在中访问。但是,如果我设置一个只包含id和文本数据字段的示例表并执行

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文档给出了检索id的SQL语句作为一个在Access中工作的示例(正如它声明的LAST_INSERT_id()不工作),但没有给出进一步的细节

我该如何解决这个问题?

解决(并写博客)如下

我一直在对一组Access数据库进行升级,用ODBC链接的MySQL替换Access文件数据库。除了将记录插入到具有自动递增id列的表中并检索刚刚创建的id值这一常见概念之外,一切似乎都进展得非常顺利。当然,在PHP或类似的应用程序上,只需使用

选择最后一个插入ID()

函数来检索ID。但是MySQL文档本身说这不适用于某些ODBC应用程序,如Delphi或Access,并建议使用

从tbl中选择*其中auto为空

不幸的是,当从我正在使用的Access应用程序内部调用时,这对我来说根本不起作用,而且web上似乎有一些评论认为这确实不可靠,因为Access可能会中断数据连接并在幕后重新连接,从而使调用无效

作为替代方案,我决定使用MySQL函数向表中添加一条空白记录,返回Access随后用于更新记录的id(这与现有应用程序的代码样式非常吻合)。不幸的是,这种看似简单的解决方法也不简单,因为MySQL中长期存在的bug使得寻找既能发送又能返回变量的有效代码成为一种挑战。web上的几个示例将在使用just-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不兼容),上面的代码似乎是允许传递和返回两个数据的唯一方法。

解决(并写日志)如下所示

我一直在对一组Access数据库进行升级,用ODBC链接的MySQL替换Access文件数据库。除了将记录插入到具有自动递增id列的表中并检索刚刚创建的id值这一常见概念之外,一切似乎都进展得非常顺利。当然,在PHP或类似的应用程序上,只需使用

选择最后一个插入ID()

函数来检索ID。但是MySQL文档本身说这不适用于某些ODBC应用程序,如Delphi或Access,并建议使用

从tbl中选择*其中auto为空

不幸的是,当从我正在使用的Access应用程序内部调用时,这对我来说根本不起作用,而且web上似乎有一些评论认为这确实不可靠,因为Access可能会中断数据连接并在幕后重新连接,从而使调用无效

作为替代方案,我决定使用MySQL函数向表中添加一条空白记录,返回Access随后用于更新记录的id(这与现有应用程序的代码样式非常吻合)。不幸的是,这种看似简单的解决方法也不简单,因为MySQL中长期存在的bug使得寻找既能发送又能返回变量的有效代码成为一种挑战。web上的几个示例将在使用just-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不兼容),上述方法似乎是允许传递和返回两个数据的唯一方法