【问题标题】:Unable to insert values to sqlite table无法将值插入到 sqlite 表
【发布时间】:2013-06-04 10:12:34
【问题描述】:

我需要创建一个表名包含一些特殊字符的表。我正在使用RSQLite 包。我需要创建的表名是port.3.1。无法使用此名称创建表。所以我在What are valid table names in SQLite?的基础上把表名改成了[port.3.1]

现在我可以创建表了,但我无法向该表插入数据框。 我使用的代码如下:

createTable <- function(tableName){
    c <- c(portDate='varchar(20) not null' ,
         ticker='varchar(20)',
         quantities='double(20,10)')
  lite <- dbDriver("SQLite", max.con = 25)
  db <- dbConnect(lite, dbname="sql.db")

  if( length(which(strsplit(toString(tableName),'')[[1]]=='.') ) != 0){ tableName = paste("[",tableName,"]",sep="") } #check whether the portfolio contains special characters or not
  sql <- dbBuildTableDefinition(db, tableName, NULL, field.types = c, row.names = FALSE)
  print(sql)
  dbGetQuery(db, sql)
}
datedPf <- data.frame(date=c("2001-01-01","2001-01-01"), ticker=c("a","b"),quantity=c(12,13))
for(port in c("port1","port2","port.3.1")){
  createTable(port)
  lite <- dbDriver("SQLite", max.con = 25)
  db <- dbConnect(lite, dbname="sql.db")
  if( length(which(strsplit(toString(port),'')[[1]]=='.') ) != 0){ port = paste("[",port,"]",sep="") } #check whether the portfolio contains special characters or not
  dbWriteTable(db,port,datedPf ,append=TRUE,row.names=FALSE)
}

在这个例子中,我可以将数据框插入表port1port2,但它没有插入表[port.3.1]。这背后的原因是什么?我该如何解决这个问题?

【问题讨论】:

    标签: r dataframe sqlite


    【解决方案1】:

    查看sqliteWriteTable 实现,只需输入该名称并按回车即可。你会注意到两件事:

    […]
    foundTable <- dbExistsTable(con, name)
    new.table <- !foundTable
    createTable <- (new.table || foundTable && overwrite)
    […]
    if (createTable) {
        […]
    

    查看showMethods("dbExistsTable", includeDefs=T) 输出,您会看到它使用dbListTables(conn),它将返回未引用 版本的表名。所以如果你将引用的表名传递给sqliteWriteTable,那么它会错误地认为你的表不存在,尝试创建它然后遇到错误。如果传入不带引号的表名,创建语句会出错。

    我认为这是 RSQLite 中的一个错误。在我看来,用户传递的 SQL 语句必须正确引用,但是在任何你将表名作为单独参数传递给函数的任何地方,默认情况下都应该不引用该表名,并且应该在从它生成的 SQL 语句中引用该表名。如果名称允许以带引号或不带引号的形式出现会更好,但这主要是为了最大限度地提高可移植性。如果您愿意,可以尝试联系开发者报告此问题。

    你可以解决这个问题:

    setMethod(dbExistsTable, signature(conn="SQLiteConnection", name="character"),
      function(conn, name, ...) {
        lst <- dbListTables(conn)
        lst <- c(lst, paste("[", lst, "]", sep=""))
        match(tolower(name), tolower(lst), nomatch = 0) > 0
      }
    )
    

    这将覆盖 SQLite 连接的 dbExistsTable 的默认实现,其版本会检查带引号和不带引号的表名。在此更改之后,将 "[port.3.1]" 作为表名传递将导致 foundTable 为真,因此 RSQLite 不会尝试为您创建该表。

    【讨论】:

    • 太棒了..感谢您的时间和精力..对我来说非常有价值的信息..再次感谢..:)
    猜你喜欢
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    相关资源
    最近更新 更多