Как получить значение поля auto_increment в Access, связанном с MySQL? - PullRequest
1 голос
/ 24 марта 2010

Я пытаюсь изменить существующее приложение Access, чтобы использовать MySQL в качестве базы данных через ODBC с минимальным объемом перекодирования.

Текущий код часто вставляет новую запись с использованием DAO, а затем получает идентификатор с помощью LastModified. Это не работает с MySQL. Вместо этого я пытаюсь использовать подход, используя

SELECT * FROM tbl_name WHERE auto_col IS NULL

Рекомендуется для доступа в документации MySQL . Однако, если я настрою образец таблицы, состоящей только из поля 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

Идентификатор возвращается как ноль. Однако, если я выполню

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

с использованием прямого редактора MySQL, тогда id возвращается правильно, поэтому моя база данных и подход в порядке, но моя реализация в Access должна быть неправильной. К сожалению, документация MySQL дает инструкцию SQL для получения идентификатора в качестве примера, который работает в Access (поскольку в нем говорится, что LAST_INSERT_ID () нет), но не дает никаких дополнительных подробностей.

Как я могу это исправить?

1 Ответ

1 голос
/ 13 мая 2010

Решено (и в блоге), как показано ниже

Я внедряю обновление для набора баз данных Access, чтобы заменить файловую базу данных Access на MySQL, связанную ODBC. Кажется, все идет замечательно гладко, за исключением общей концепции вставки записи в таблицу со столбцом идентификатора с автоприращением и извлечения значения только что созданного идентификатора. Конечно, на PHP или тому подобном можно было бы использовать

SELECT LAST_INSERT_ID ()

Функция для получения идентификатора. Однако сама документация MySQL говорит, что это не работает для некоторых приложений ODBC, таких как Delphi или Access, и предлагает использовать

ВЫБРАТЬ * ОТ ТАБЛИЦЫ, ГДЕ АВТОМАТ НУЛ;

К сожалению, это просто не сработало для меня, когда меня вызвали из приложения Access, с которым я работал, и, кажется, в Интернете есть несколько комментариев, которые действительно ненадежны, так как Access может разорвать соединение для передачи данных и восстановить соединение за сцены - таким образом, сделать вызов недействительным.

В качестве альтернативы я решил использовать функцию MySQL для добавления пустой записи в таблицу, возвращая идентификатор, который Access затем использовал бы для обновления записи (что хорошо согласуется со стилем кода существующего приложения). К сожалению, этот, по-видимому, простой обходной путь не может быть простым, так как давние ошибки в MySQL делают поиск допустимого кода, который может как отправлять, так и возвращать переменную, чем-то сложным. Несколько примеров в Интернете будут работать в ограниченной области использования переменных 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$$

Эта процедура полезна тем, что вставляет строку и возвращает идентификатор для любой таблицы, где строка содержит все нулевые или ненулевые поля с определенными значениями по умолчанию. Для вызова я использую следующую функцию:

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) вышеприведенное, кажется, единственный способ, который позволяет данные для передачи и возврата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...