6

在一些帖子中找到的原始示例

根据这篇文章,以下 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

遵循NBJeff AllenQuassnoi的建议

对示例进行了修改,使其比原始用例更类似于真实用例:

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

好吧,它没有,真的;-)

我用谷歌搜索了一下,AFAIULAST_INSERT_ID()是“连接感知”的,因为如果要正常工作,必须使用相同的连接。但是,我认为通过将连接对象分配给con我可以确保在上面的每个语句中确实使用了相同的连接。

好吧,显然不是 ;-) 任何人都可以帮助我提供一些解释和/或解决方法吗?但是,使用类似的东西select max(<ID>) from <TABLE>不会减少它,因为我正在运行同时写入数据库的多个线程,因此如果这样做会弄乱 ID 检索。

谢谢!

截至 2012 年 4 月 20 日的调查结果

  • 多亏了Quassnoi,我才能够更多地找到问题所在。似乎RMySQL函数并不真正关心显式conn参数,而是每次连接到数据库时都会在后台打开新连接。可能也有一些很好的理由。然而,有谁知道如何避免这种情况?
  • 刚刚联系了 Jeffrey Horner(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)> 
4

3 回答 3

2

我在这里找到了一个可行的解决方案。stephan mc 的回复中也提到了它,但作为第二种选择。第一个对我不起作用,所以我认为这可能值得更多强调。

无论如何,诀窍是在anddbClearResult()之间运行:INSERTSELECT 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
于 2014-11-05T18:03:44.593 回答
0

您正在将NULL值插入到主键列中。由于您不能有两行具有相同的 PK,因此您实际上可能没有插入任何真实数据(这也可能是您想要捕获的错误)。尝试:

dbSendQuery(con, "INSERT INTO t VALUES(5);")

执行该操作应该会为您提供两个不同的 last_insert_id 值。

编辑:误会了。有关的详细信息,请参见此处LAST_INSERT_ID。修改后的答案:如果您没有在AUTO_INCREMENT列中指定值,那么您应该得到一个LAST_INSERT_ID返回值。在这种情况下,请尝试:

INSERT INTO t DEFAULT VALUES
于 2012-04-20T13:09:04.343 回答
0

We found a very interesting solution:

res <- dbSendQuery(con, "INSERT INTO t VALUES (5);")
res <- dbSendQuery(con, "SELECT LAST_INSERT_ID();")
fetch(res)

If it does not work, use a dbClearResult(res) before sending the last id request. For us it worked out.

于 2014-05-28T06:01:42.080 回答