LAST INSERT ID () всегда возвращает 0 (RMySQL) - отдельная проблема подключения
оригинальный пример, как найдено в некоторых в должности
по этому в должности следующие операторы SQL должны дать мне вектор
1, 2, 2, 2, 2
в итоге:
require("RMySQL")
con <- dbConnect(
dbDriver("MySQL"),
db="your_db",
user="your_user",
password="your_pw",
host="localhost"
)
> con
<MySQLConnection:(6640,122)>
> dbSendQuery(con, "DROP TABLE IF EXISTS t;")
<MySQLResult:(6640,122,0)>
> dbSendQuery(con, "CREATE TABLE t (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY);")
<MySQLResult:(6640,122,1)>
> dbSendQuery(con, "INSERT INTO t VALUES(NULL);")
<MySQLResult:(6640,122,2)>
> dbGetQuery(con, "SELECT LAST_INSERT_ID() FROM t;")
LAST_INSERT_ID()
1 0
> dbSendQuery(con, "INSERT INTO t VALUES(NULL),(NULL),(NULL);")
<MySQLResult:(6640,122,3)>
> dbGetQuery(con, "SELECT LAST_INSERT_ID() FROM t;")
LAST_INSERT_ID()
1 0
2 0
3 0
4 0
по предложению Б. Н., Джефф Аллен и Quassnoi
адаптировал пример, чтобы он напоминал реальные случаи использования немного больше, чем оригинальный:
dbSendQuery(con, "DROP TABLE IF EXISTS t;")
dbSendQuery(con, paste("CREATE TABLE t",
"(i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, x INT);"))
> dbGetQuery(con, "SELECT CONNECTION_ID();")
CONNECTION_ID()
1 673490
dbSendQuery(con, "INSERT INTO t SET x=1;")
> dbGetQuery(con, "SELECT CONNECTION_ID();")
CONNECTION_ID()
1 673491
> dbGetQuery(con, "SELECT LAST_INSERT_ID();")
LAST_INSERT_ID()
1 0
> dbGetQuery(con, "SELECT CONNECTION_ID();")
CONNECTION_ID()
1 673493
> dbGetQuery(con, "SELECT LAST_INSERT_ID();")
LAST_INSERT_ID()
1 0
dbSendQuery(con, "INSERT INTO t SET x=2;")
> dbGetQuery(con, "SELECT LAST_INSERT_ID();")
LAST_INSERT_ID()
1 0
> dbGetQuery(con, "SELECT * FROM t;")
i x
1 1 1
2 2 2
Ну, это не, действительно ;-)
Я немного погуглил и AFAIU,LAST_INSERT_ID()
является "Connection-aware" в том смысле, что одно и то же соединение должно использоваться, если оно должно работать правильно. Тем не менее, я думал, что, назначив объект соединения con
я убедился, что действительно такая же связь и используется в каждом из приведенных выше утверждений.
ну, по-видимому, нет ; -) Может ли кто-нибудь помочь мне с некоторыми объяснениями и/или обходными путями?
Используя что-то вроде select max(<ID>) from <TABLE>
не однако я собираюсь сократить его, поскольку я запускаю несколько потоков, которые одновременно пишут в БД, тем самым испортив поиск идентификатора, если это сделано таким образом.
спасибо!
выводы по состоянию на 2012-04-20
- спасибо Quassnoi я смог отследить проблему немного больше. Кажется
RMySQL
функции на самом деле не заботятся о явномconn
аргумент, но открывать новые соединения в фоновом режиме каждый раз при подключении к БД. Возможно, для этого тоже есть веские причины. Но знает ли кто-нибудь, как этого избежать? - только что связался с Джеффри Хорнером (сопровождающий RMySQL). Похоже, это проблема Windows. Работал на него в Linux: -/
детали подключения
как было предложено Джефф
> dbGetInfo(con)
$host
[1] "localhost"
$user
[1] "your_user"
$dbname
[1] "your_db"
$conType
[1] "localhost via TCP/IP"
$serverVersion
[1] "5.5.20"
$protocolVersion
[1] 10
$threadId
[1] 673489
$rsId
$rsId[[1]]
<MySQLResult:(6640,171,3)>
> dbGetInfo(dbDriver("MySQL"))
$drvName
[1] "MySQL"
$connectionIds
$connectionIds[[1]]
<MySQLConnection:(6640,149)>
$connectionIds[[2]]
<MySQLConnection:(6640,112)>
$connectionIds[[3]]
<MySQLConnection:(6640,171)>
$fetch_default_rec
[1] 500
$managerId
<MySQLDriver:(6640)>
$length
[1] 16
$num_con
[1] 3
$counter
[1] 179
$clientVersion
[1] "5.5.20"
> dbListConnections(dbDriver("MySQL"))
[[1]]
<MySQLConnection:(6640,149)>
[[2]]
<MySQLConnection:(6640,112)>
[[3]]
<MySQLConnection:(6640,171)>
3 ответов
Я нашел рабочее решение здесь. Это также упоминается в ответе stephan mc, но как второй вариант. Первый не сработал для меня, поэтому я подумал, что это может стоить выделить больше.
в любом случае, фокус в том, чтобы запустить dbClearResult()
между INSERT
и SELECT LAST_INSERT_ID()
:
> library("RMySQL")
> con <- dbConnect(MySQL())
> dbSendQuery(con, "DROP TABLE IF EXISTS t;")
> dbSendQuery(con, "CREATE TABLE t (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY);")
> res <- dbSendQuery(con, "INSERT INTO t VALUES (NULL);")
# doesn't work:
> dbGetQuery(con, "SELECT LAST_INSERT_ID();")
LAST_INSERT_ID()
1 0
# works:
> dbClearResult(rs)
> dbGetQuery(con, "SELECT LAST_INSERT_ID();")
LAST_INSERT_ID()
1 1
вы вставляете NULL
значения в столбце первичного ключа. Поскольку вы не можете иметь две строки с одним и тем же ПК, вы, вероятно, не вставляете никаких реальных данных (что также, вероятно, является ошибкой, которую вы хотите поймать). Попробуйте:
dbSendQuery(con, "INSERT INTO t VALUES(5);")
выполнение, которое должно дать вам два разных значения для last_insert_id.
Edit: неправильно понято. См.здесь подробнее о LAST_INSERT_ID
. Пересмотренный ответ: если вы не укажете значение в элементе
мы нашли очень интересное решение:
res <- dbSendQuery(con, "INSERT INTO t VALUES (5);")
res <- dbSendQuery(con, "SELECT LAST_INSERT_ID();")
fetch(res)
если он не работает, используйте dbClearResult(res)
перед отправкой последнего запроса id. У нас все получилось.