2017-01-06 2 views
0

Мне очень нравится функция dbWriteTable из DBI (обычно я использую RSQLite или ROracle в качестве backend).DBI dbWriteTable

Я использую эту функцию для импорта большого количества таблиц Excel, проблема в том, что если эти электронные таблицы были созданы в течение длительного времени, то изменения столбца будут добавлены/удалены или изменены имя из одного документа в другой.

Итак, у меня вопрос, есть ли у кого-то относительно быстрый способ добавить данные в базу данных, не имея при этом полного соответствия поданному списку?

Вот пример скрипта, который я использую

require(RSQLite) 
require(readxl) 

# Create database file 
conn <- dbConnect(drv=SQLite(),dbname = "path to database") 

# Define import function 

excel2sqltable <- function(conn, file, table) { 
    source.df <- read_excel(path=file,col_names = TRUE) %>% 
    cbind("SourceFile" = file, .) 

    names(source.df) <- source.df %>% 
    data.frame(check.names = TRUE) %>% 
    {gsub("[.]",x=names(.),replacement="_")} 

    print(paste("Importing ", file)) 

    setOldClass(c("tbl_df", "data.frame")) 
    dbWriteTable(conn = conn, name = table, value = source.df, append=TRUE) 
} 

С этой функцией я могу сделать: sapply(list.files(),FUN = function(x){excel2sqltable(conn,x,"Imports")})

+0

Непонятно, что вы пытаетесь сделать здесь. Вы пытаетесь пропустить часть об именах столбцов 'source.df'? Или вы говорите о части 'dbWriteTable' скрипта? – Abdou

+0

Я предполагаю, что обновить этот скрипт, чтобы динамически создавать поля, такие, что 'dbWriteTable' не вызывает ошибку' Columns NewColumn not found'. – sgp667

+0

Запросить db для одной строки и задать имена столбцов в соответствии с этим? Мне нужно будет посмотреть в документах, чтобы увидеть, есть ли функция DBI для просто возвращающих имен столбцов таблицы ... – joran

ответ

1

Вы можете использовать это в качестве руководства:

library(RSQLite) 

sqlite_conn <- dbConnect(drv = SQLite(),dbname = 'data_dump.sqlite') 

excel2sqltable <- function(conn, file, table) { 
    source.df <- readxl::read_excel(path=file,col_names = TRUE) %>% 
    cbind("SourceFile" = file, .) 

    names(source.df) <- source.df %>% 
    data.frame(check.names = TRUE) %>% 
    {gsub("[.]",x=names(.),replacement="_")} 

    if(!dbExistsTable(conn, table)) { 
    dbWriteTable(conn = conn, name = table, value = source.df) 
    } else { 
    # Get both dataframe columns and table columns 
    df_cols <- colnames(source.df) 
    tbl_cols <- dbListFields(conn, table) 

    # Check if there are columns in the dataframe 
    # that are not in the destination table 
    # Loop through the missing columns and add 
    # them to the database table 
    if (length(setdiff(df_cols, tbl_cols)) > 0) { 
     missing_cols <- setdiff(df_cols, tbl_cols) 
     for (col_name in missing_cols) { 
     dbSendStatement(conn, sprintf('ALTER TABLE %s ADD %s VARCHAR', table, col_name)) 
     } 
    } 

    setOldClass(c("tbl_df", "data.frame")) 


    dbWriteTable(conn = conn, name = table, value = source.df, append=TRUE) 
    } 
} 

lapply(list.files(), function(x) { 
    excel2sqltable(sqlite_conn, x, "Imports") 
}) 
dbDisconnect(sqlite_conn) 

Я надеюсь, что она служит цель.

+0

работает как шарм, спасибо – sgp667

Смежные вопросы