如何更新 SQLite 数据库中的表?

问题描述 投票:0回答:1

我想使用 R 对本地存储在 SQLite 数据库中的表执行多个后续联接。我使用这种方法来保持内存不受数据(存储为 tibble)的影响,因为某些表大于大小限制R 允许单个向量。 虽然我设法执行连接并根据每个连接创建一个新表,但我宁愿更新现有表。

library(DBI)
library(dbplyr)
library(tidyverse)


con <- DBI::dbConnect(RSQLite::SQLite(), 
                      dbname = "test")

dbplyr::copy_nycflights13(con)

dbListTables(con)

加入本地 tibbles 是可行的,但对于我的用例来说,没有足够的内存来在环境中执行此步骤。

# data stored locally
left_join(nycflights13::flights,
          nycflights13::planes,
          by = c("tailnum", "year")) |> 
  left_join(nycflights13::airlines, by = "carrier")

数据存储在 RSQLite 数据库中。第一个连接工作并返回 df1,它作为新表写入数据库。例如:

# in dplyr /dbplyr
left_join(x = tbl(con, "flights"),
          y = tbl(con, "planes"),
          by = c("tailnum", "year")) |> 
  show_query() |> 
  compute(name = "df1", temporary = F)

无法保存第二个查询,表 df1 已存在。例如:

left_join(x = tbl(con, "df1"),
          y = tbl(con, "airlines"),
          by = "carrier") |> 
  show_query() |> 
  compute(name = "df1", temporary = F)

有没有办法强制

compute()
覆盖现有表?或者有人可以建议如何在 SQL 查询中编写它?我尝试了以下方法:

query <- "
  UPDATE df1
  SET
    name = result.name
  FROM (
    SELECT
      carrier,
      name
    FROM
      df1
    LEFT JOIN
      airlines
    USING
      (carrier)
  ) AS result
  WHERE
    df1.carrier = result.carrier
"

# Execute the update query
dbExecute(con, query)

但是我收到错误:

Error: no such table: df1
dbListTables(con)
表示 df1 在数据库中。

出了什么问题?

sql r sqlite
1个回答
0
投票

您遇到的一个问题是数据库中的

name
中没有定义
df1
;一旦完成,您可以使用“加入更新”。

# setup
library(DBI); library(dplyr)
con <- DBI::dbConnect(RSQLite::SQLite(), dbname = "test")
dbplyr::copy_nycflights13(con)

# for the demo, we'll wipe out `df1` and regenerate it with an empty `name` column
dbExecute(con, "drop table df1")
left_join(x = tbl(con, "flights"),
          y = tbl(con, "planes"),
          by = c("tailnum", "year")) |> 
  mutate(name = NA_character_) |>
  show_query() |> 
  compute(name = "df1", temporary = FALSE)

从这里开始,如果我们尝试使用您现有的

query
进行更新,则会收到错误:

Error: ambiguous column name: name

此外,一旦我们解决了这个问题,我们就会得到一个“非常慢”的更新(我从来没有足够的耐心让它持续超过几分钟)。从https://stackoverflow.com/a/21074659/3358272获取提示 query <- " UPDATE df1 SET name = (SELECT name FROM airlines WHERE airlines.carrier = df1.carrier) where EXISTS (SELECT name FROM airlines WHERE airlines.carrier = df1.carrier)" dbExecute(con, query) # [1] 336776 dbGetQuery(con, "select * from df1 limit 10") |> str() # 'data.frame': 10 obs. of 27 variables: # $ year : int 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 # $ month : int 1 1 1 1 1 1 1 1 1 1 # $ day : int 1 1 1 1 1 1 1 1 1 1 # $ dep_time : int 517 533 542 544 554 554 555 557 557 558 # $ sched_dep_time: int 515 529 540 545 600 558 600 600 600 600 # $ dep_delay : num 2 4 2 -1 -6 -4 -5 -3 -3 -2 # $ arr_time : int 830 850 923 1004 812 740 913 709 838 753 # $ sched_arr_time: int 819 830 850 1022 837 728 854 723 846 745 # $ arr_delay : num 11 20 33 -18 -25 12 19 -14 -8 8 # $ carrier : chr "UA" "UA" "AA" "B6" ... # $ flight : int 1545 1714 1141 725 461 1696 507 5708 79 301 # $ tailnum : chr "N14228" "N24211" "N619AA" "N804JB" ... # $ origin : chr "EWR" "LGA" "JFK" "JFK" ... # $ dest : chr "IAH" "IAH" "MIA" "BQN" ... # $ air_time : num 227 227 160 183 116 150 158 53 140 138 # $ distance : num 1400 1416 1089 1576 762 ... # $ hour : num 5 5 5 5 6 5 6 6 6 6 # $ minute : num 15 29 40 45 0 58 0 0 0 0 # $ time_hour : num 1.36e+09 1.36e+09 1.36e+09 1.36e+09 1.36e+09 ... # $ type : chr NA NA NA NA ... # $ manufacturer : chr NA NA NA NA ... # $ model : chr NA NA NA NA ... # $ engines : int NA NA NA NA NA NA NA NA NA NA # $ seats : int NA NA NA NA NA NA NA NA NA NA # $ speed : int NA NA NA NA NA NA NA NA NA NA # $ engine : chr NA NA NA NA ... # $ name : chr "United Air Lines Inc." "United Air Lines Inc." "American Airlines Inc." "JetBlue Airways" ...

(旁注:这是

df1数据库的非规范化;如果这是您明确的意图,那么它就是按照您的意思做的,尽管在许多数据库讨论中可能建议/首选保持其规范化,其中(对于例如)字符串

"United Air Lines Inc."
存储在一个由运营商和名称组成的 16 行表中,当您进行查询时,您可以将其连接到数据中。这主要是一个理论讨论,尽管以这种方式存储
df1.name
确实需要花费数据库中还有更多空间。)

    

© www.soinside.com 2019 - 2024. All rights reserved.