【问题标题】:How to create SQL Server table from dplyr pipeline如何从 dplyr 管道创建 SQL Server 表
【发布时间】:2017-09-17 15:27:50
【问题描述】:

由于a bug in dbplyrcopy_tocompute 目前不适用于 SQL Server 连接。

connStr <- "driver=ODBC Driver 13 for SQL Server;server=localhost;..."
db <- DBI::dbConnect(odbc::odbc(), .connection_string=connStr)

copy_to(db, mtcars)
#Error: <SQL> 'CREATE TEMPORARY TABLE "mtcars" (
#  "row_names" varchar(255),
#  "mpg" FLOAT,
#  ...
#  nanodbc/nanodbc.cpp:1587: 42000: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Unknown object type 'TEMPORARY' used in a CREATE, DROP, or ALTER statement. 

# use raw DBI functionality to create table
DBI::dbWriteTable(db, "mtcars", mtcars)

qry <- tbl(db, "mtcars") %>% group_by(am) %>% summarise(m=mean(mpg))

compute(qry)
#Error: <SQL> 'CREATE TEMPORARY TABLE "isrxofsskr" AS SELECT "am" AS "am", "m" #AS "m"
#FROM (SELECT "am", AVG("mpg") AS "m"
#FROM "mtcars"
#GROUP BY "am") "htrkkxabrn"'
#  nanodbc/nanodbc.cpp:1587: 42000: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Unknown object type 'TEMPORARY' used in a CREATE, DROP, or ALTER statement. 

dbplyr repo 上有一个有效的 PR 可以解决这个问题,但没有说明何时合并(或何时到达 CRAN)。同时,如何在不将数据读入 R 的情况下从查询中创建表?

【问题讨论】:

  • @Hack-R 正确。理想情况下,我希望能够选择是创建永久表还是临时表。
  • 嘿,这可能是一个愚蠢的问题,但由于该错误只是 SQL 语法稍微不正确,我们可以不只是稍微编辑一下包源来修复它吗?我认为您只需要删除“临时”一词(或使用拉取请求中的代码,也许通过在合并它的地方创建一个分支,然后使用 install_github 安装您的分支?)。

标签: sql-server r dplyr r-dbi dbplyr


【解决方案1】:

事实证明,dbplyr repo 上的 PR 无论如何都会出现故障,并且会在写回之前将整个表拉入内存。

解决此问题需要为 dbplyr 泛型创建几个特定于 MSSQL 的方法。下面列出了这些。我也将它们发布到 dbplyr 存储库,因此(假设它们有效)它们应该有望在不久之后被合并。

#' @export
`db_compute.Microsoft SQL Server` <- function(con, table, sql, temporary=TRUE,
     unique_indexes=list(), indexes=list(), ...)
{
    # check that name has prefixed '##' if temporary
    if(temporary && substr(table, 1, 1) != "#")
        table <- paste0("##", table)

    if(!is.list(indexes))
        indexes <- as.list(indexes)

    if(!is.list(unique_indexes))
        unique_indexes <- as.list(unique_indexes)

    db_save_query(con, sql, table, temporary=temporary)
    db_create_indexes(con, table, unique_indexes, unique=TRUE)
    db_create_indexes(con, table, indexes, unique=FALSE)
    table
}


#' @export
`db_save_query.Microsoft SQL Server` <- function(con, sql, name, temporary=TRUE, ...)
{
    # check that name has prefixed '##' if temporary
    if(temporary && substr(name, 1, 1) != "#")
        name <- paste0("##", name)

    tt_sql <- build_sql("SELECT * INTO ", ident_q(name),
                        " FROM (", sql, ") ", ident_q(name), con=con)

    dbExecute(con, tt_sql)
    name
}

注意:可能不耐鲍比桌。建议进行测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2013-09-07
    • 2017-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多