5

我正在使用DBI,与数据库RMySql交互的包。MySql

以下是有关配置的更多详细信息:

  • R版本:3.3.2
  • DBI 版本:0.7
  • RMySql 版本:0.10.13

下面是表站点的架构:

+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| short_name | varchar(10) | NO   | UNI | NULL    |                |
| full_name  | varchar(50) | NO   | UNI | NULL    |                |
+------------+-------------+------+-----+---------+----------------+

如您所见,字段short_name&full_name具有UNIQUE&NOT NULL约束。

在尝试插入具有重复项short_namefull_name表中已存在的行时,dbWriteTable不会让这种行插入发生,但它会返回TRUE状态,即使它违反了UNIQUE约束。NOT NULL约束也会发生同样的事情。

这是DBI&的预期行为dbWriteTable吗?为什么它不返回FALSE状态?

编辑:我还观察到,即使在违反约束的情况下dbSendStatement()dbSendQuery()不会给出任何错误。有什么方法可以了解这个吗?

4

1 回答 1

1

我觉得必须有更好的方法来做到这一点,但我知道的解决方案是使用 tryCatch 来捕获错误消息。除了捕获消息之外,这里还有其他选项……例如,您可以采取行动。

文档中解释了 dbWriteTable 不返回 FALSE 的原因。如果 DBI 函数有问题,它只返回 FALSE。您的问题出在数据库中。我知道这是语义,但在这里有所不同。

我编了一个例子,因为我没有这个问题。

library(DBI)
library(RSQLite)

con <- dbConnect(RSQLite::SQLite(), ":memory:")

dbSendQuery(con,
            "CREATE TABLE mtcars
            (
              mpg REAL,
              cyl INTEGER,
              disp REAL,
              hp REAL, 
              drat REAL NOT NULL
            );")

dbWriteTable(con, "mtcars", mtcars[1:5,1:5], append = TRUE)

test_db <- dbGetQuery(con,"SELECT * FROM mtcars")
test_db
# mpg cyl disp  hp drat
# 1 21.0   6  160 110 3.90
# 2 21.0   6  160 110 3.90
# 3 22.8   4  108  93 3.85
# 4 21.4   6  258 110 3.08
# 5 18.7   8  360 175 3.15

# Can't capture output
result <- dbWriteTable(con, "mtcars", 
             data.frame(mpg = 1, cyl = 2, disp = 3, hp = 4, drat = NA),
             append = TRUE)
result
# Error: object 'result' not found

# Let's try checking exceptions
# This doesn't work because it is checking for exceptions in the DBI commands...not in the database.
result <- dbGetException(con)
result
# $errorNum
# [1] 0
# 
# $errorMsg
# [1] "OK"

# Because of the error there wasn't a change in the database.
test_db <- dbGetQuery(con,"SELECT * FROM mtcars")
test_db
# mpg cyl disp  hp drat
# 1 21.0   6  160 110 3.90
# 2 21.0   6  160 110 3.90
# 3 22.8   4  108  93 3.85
# 4 21.4   6  258 110 3.08
# 5 18.7   8  360 175 3.15

# We can use a tryCatch to capture error or warning messages
tryCatch({
  dbWriteTable(con, "mtcars", 
               data.frame(mpg = 1, cyl = 2, disp = 3, hp = 4, drat = NA),
               append = TRUE)
  result <- dbGetException(con)
},
  error = function(e) result <<- conditionMessage(e),
  warning = function(w) result <<- conditionMessage(w)
)
于 2022-02-10T15:12:12.510 回答