代码之家  ›  专栏  ›  技术社区  ›  Hong Ooi

如何从dplyr管道创建SQL Server表

  •  1
  • Hong Ooi  · 技术社区  · 9 年前

    由于 a bug in dbplyr copy_to compute 当前不适用于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回购上有一个有效的PR解决了这个问题,但没有迹象表明何时合并(或何时到达CRAN)。同时,我如何从查询中创建一个表,而不将数据读入R?

    1 回复  |  直到 9 年前
        1
  •  1
  •   Hong Ooi    9 年前

    事实证明,dbplyr回购上的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
    }