如何管理R& S中的模式MonetDB?

时间:2015-10-08 23:19:56

标签: r dplyr monetdb r-dbi

我最近问过一个类似的问题,更多是针对dplyr。

请参阅dplyr & monetdb - appropriate syntax for querying schema.table?

作为dplyr& MonetDB(根据@HannesMühleisen上面的回复)没有正确的方法来管理模式,我决定使用MonetDB.R / DBI本机函数。

同样在这种情况下,结果有些问题:现在似乎MonetDB.R能够正确管理每个数据库一个模式。

让我们看一些代码。我创建了两个模式,并在每个模式中创建相同的表名(标准sql实践)。然后我尝试将数据写入每个。

> conn <– dbConnect(MonetDB.R(), "db.url", user= "monetdb", password="monetdb")
> df <- data.frame(i=10,j=20)
> q <- dbGetQuery(conn, "CREATE SCHEMA foo;")
> q <- dbGetQuery(conn, "SET SCHEMA foo;")
> q <- dbGetQuery(conn, "CREATE TABLE mytable (i int, j int);")
> q <- dbWriteTable(conn,  "mytable",df,overwrite=TRUE)
> q <- dbGetQuery(conn, "CREATE SCHEMA bar;")
> q <- dbGetQuery(conn, "SET SCHEMA bar;")
> q <- dbGetQuery(conn, "CREATE TABLE mytable (i int, j int);")

在这个阶段,我应该有两个名称相同的表,但是有两个不同的模式。 dbListTables证实了这一点(看到模式会很好,但我可以没有它):

> dbListTables(conn)
[1] "mytable" "mytable"

但是一旦我尝试使用与之前使用的相同的查询写入mytable,灾难!

> q <- dbWriteTable(conn,  "mytable",df,overwrite=TRUE)
Error in .local(conn, statement, ...) : 
  Unable to execute statement 'INSERT INTO mytable VALUES (10, 20)'.
Server says 'INSERT INTO: no such table 'mytable'' [#42S02].

此时数据库处于凌乱状态,并要求回滚事务。

让我们尝试使用overwrite = FALSE,只是为了看看是否有任何不同:

> df <- data.frame(i=10,j=20)
> q <- dbGetQuery(conn, "CREATE SCHEMA foo;")
> q <- dbGetQuery(conn, "SET SCHEMA foo;")
> q <- dbGetQuery(conn, "CREATE TABLE mytable (i int, j int);")
> q <- dbWriteTable(conn,  "mytable",df,overwrite=TRUE)
> q <- dbGetQuery(conn, "CREATE SCHEMA bar;")
> q <- dbGetQuery(conn, "SET SCHEMA bar;")
> q <- dbGetQuery(conn, "CREATE TABLE mytable (i int, j int);")
> dbListTables(conn)
[1] "mytable" "mytable"
> q <- dbWriteTable(conn,  "mytable",df,overwrite=FALSE)
Error in .local(conn, name, value, ...) : 
  Table mytable already exists. Set overwrite=TRUE if you want 
      to remove the existing table. Set append=TRUE if you would like to add the new data to the 
      existing table.

我用append=true

击中了母亲
> df <- data.frame(i=10,j=20)
> q <- dbGetQuery(conn, "CREATE SCHEMA foo;")
> q <- dbGetQuery(conn, "SET SCHEMA foo;")
> q <- dbGetQuery(conn, "CREATE TABLE mytable (i int, j int);")
> q <- dbWriteTable(conn,  "mytable",df,overwrite=TRUE)
> q <- dbGetQuery(conn, "CREATE SCHEMA bar;")
> q <- dbGetQuery(conn, "SET SCHEMA bar;")
> q <- dbGetQuery(conn, "CREATE TABLE mytable (i int, j int);")
> dbListTables(conn)
[1] "mytable" "mytable"
> q <- dbWriteTable(conn,  "mytable",df,append=TRUE)

后一个序列似乎可以正常工作并将数据加载到bar模式中而不会出现问题。 但是你使用(正如我通常那样)csvdump=TRUE你会得到另一个错误:

Error in .local(conn, statement, ...) : 
Unable to execute statement 'COPY 15 RECORDS INTO mytable FROM '/var/folders/m4/yfyjwcpj6rv5nq730bl9vr1h000...'.
Server says 'COPY INTO: no such table 'mytable'' [#42S02].

我总是可以避免使用csvdump,但我需要写大表......

我也试过copy_to&amp; dplyr,但我也遇到了错误。

毫不奇怪,看到csvdump的问题我也使用monetdb.read.csv得到了类似的错误:如果在另一个模式中存在同名表时尝试加载csv,则会出错。

我做错了吗?有更好的办法吗?这是一个错误吗?

欢迎任何帮助。

1 个答案:

答案 0 :(得分:0)

当我需要找到解决方案时,我最终重新编写/重构了MonetDB.R中的所有主要标准函数。

作为一个简单示例,这是替换/** * @Entity * @Table(name="database_name.table_name") */ class YourEntity 的代码:

dbListTables

公平地说,真正的问题是fdblisttables <- function(conn, schema){ q <- dbGetQuery(conn, paste0("SELECT s.name AS name FROM sys.tables AS s JOIN sys.schemas AS t ON s.schema_id=t.id WHERE t.name='", schema,"';" )) if(is.null(q$name)) q <- character() else q <- q$name } 没有针对模式的语法(但如果它有......那就好了),所以{{1}的编程手库开发人员有点束缚。

我意识到模式可以至少以两种方式实现:

  • 隐式地,但它需要一种方法来从数据库中获取DBIMonetDB.R目前不可用(并且可能两者都没有)
  • 显式地,将关键字模式添加到函数调用中。最后这是我所做的,因为这是最简单的方法。另一方面,它可能会产生与现有代码等兼容的问题。

像往常一样,欢迎任何建议和帮助。如果有兴趣,我会在github上的gist上发布我创建的函数。