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実際に同じ接続が使用されていることを確認していると思いました。

まあ、明らかにそうではありません;-)誰かがいくつかの説明や回避策で私を助けることができますか?ただし、DBに同時に書き込む複数のスレッドを実行しているため、のようなものを使用してselect max(<ID>) from <TABLE>も、それを削減することはできません。そのため、そのようにするとIDの取得が台無しになります。

ありがとう!

2012年4月20日現在の調査結果

  • Quassnoiのおかげで、問題をもう少し追跡することができました。RMySQL関数は明示的な引数をそれほど気にしないようconnですが、DBに接続するたびにバックグラウンドで新しい接続を開きます。おそらくこれにもいくつかの正当な理由があります。それでも、これを回避する方法を知っている人はいますか?
  • 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の返信にも記載されていますが、2番目のオプションです。最初のものは私にはうまくいかなかったので、これはもっと強調する価値があるかもしれないと思いました。

とにかく、トリックはとの間で実行することdbClearResult()です: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を持つ2つの行を持つことはできないため、実際には実際のデータを挿入していない可能性があります(これはおそらくキャッチしたいエラーでもあります)。試す:

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

これを実行すると、last_insert_idに2つの異なる値が与えられます。

編集:誤解されています。の詳細については、こちらをご覧くださいLAST_INSERT_IDAUTO_INCREMENT改訂された回答:列に値を指定しない場合は値が返されるはずですLAST_INSERT_ID。その場合は、次を試してください。

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

非常に興味深い解決策が見つかりました。

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

それが機能しない場合はdbClearResult(res)、最後のIDリクエストを送信する前にaを使用してください。私たちにとってはうまくいきました。

于 2014-05-28T06:01:42.080 に答える