【问题标题】:How to write POSIXct / POSIXt timestamps with milliseconds into Postgres table from R如何将 POSIXct / POSIXt 时间戳从 R 写入 Postgres 表
【发布时间】:2020-02-09 03:39:18
【问题描述】:

我有一个 PostgreSQL 11 数据库,它保存以毫秒为单位的时间戳(类型时间戳)。检索数据工作正常 - 时间有毫秒。写入数据库会导致毫秒数减少到十分之一秒。

如何在写入 Postgresql 时节省毫秒?

是 DBI 吗?我不受 DBI 的约束。不过会很好,因为我通常使用游泳池。欢迎使用任何 R-Postgres 接口。

示例数据

    data <- structure(list(event_time = structure(c(1562053856.679, 1561977632.48, 
1561129860.825), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
name = c("E9980.RT_POS", "E9984.FT_POS", "E9984.RT_POS"), 
float_val = c(78.7, 90.54, 78.82)), class = c("tbl_df", "tbl","data.frame"), row.names = c(NA, -3L))



# Look like this
# A tibble: 3 x 3
event_time               name         float_val
<dttm>                   <chr>            <dbl>
1 2019-07-02 07:50:56.6789 E9980.RT_POS      78.7
2 2019-07-01 10:40:32.4800 E9984.FT_POS      90.5
3 2019-06-21 15:11:00.8250 E9984.RT_POS      78.8

连接数据库

library(odbc)
library(DBI)
library(dplyr)
library(dbplyr)
op <- options(digits.secs=4) # let me see milliseconds
con <- DBI::dbConnect(odbc::odbc(),
                  Driver = "PostgreSQL Driver", 
                  Server = "localhost", 
                  Database  = "postgres",
                  UID = "postgres",
                  PWD = rstudioapi::askForPassword("Database password"),
                  Port = 5432)

写入数据库

dbWriteTable(con, "test", data)

从数据库读取

con %>% tbl(in_schema("public","test")) %>% collect()

# A tibble: 3 x 3
event_time               name         float_val
<dttm>                   <chr>            <dbl>
1 2019-07-02 07:50:56.0000 E9980.RT_POS      78.7
2 2019-07-01 10:40:32.0000 E9984.FT_POS      90.5
3 2019-06-21 15:11:00.0000 E9984.RT_POS      78.8

dbReadTable(con,"test")
event_time         name float_val
1 2019-07-02 07:50:56 E9980.RT_POS     78.70
2 2019-07-01 10:40:32 E9984.FT_POS     90.54
3 2019-06-21 15:11:00 E9984.RT_POS     78.82

pgadmin 查询还确认毫秒写入不正确。

会话和额外信息

sessionInfo()
R version 3.6.0 (2019-04-26)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.6

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] de_DE.UTF-8/de_DE.UTF-8/de_DE.UTF-8/C/de_DE.UTF-8/de_DE.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] dbplyr_1.4.2 dplyr_0.8.3  DBI_1.0.0    odbc_1.1.6  

loaded via a namespace (and not attached):
[1] Rcpp_1.0.1       rstudioapi_0.10  knitr_1.23       magrittr_1.5     hms_0.5.0        tidyselect_0.2.5
[7] bit_1.1-14       R6_2.4.0         rlang_0.4.0      fansi_0.4.0      blob_1.2.0       tools_3.6.0     
[13] xfun_0.8         utf8_1.1.4       cli_1.1.0        bit64_0.9-7      assertthat_0.2.1 tibble_2.1.3    
[19] crayon_1.3.4     purrr_0.3.2      vctrs_0.2.0      zeallot_0.1.0    glue_1.3.1       compiler_3.6.0  
[25] pillar_1.4.2     backports_1.1.4  pkgconfig_2.0.2 





 rstudioapi::versionInfo()$version
 [1] ‘1.2.1335’

【问题讨论】:

    标签: r postgresql dplyr odbc dbi


    【解决方案1】:

    使用来自RPostgres 而不是odbc 的postgres 驱动程序似乎可以按预期插入具有亚秒级分辨率的时间戳。

    library(DBI)
    library(RPostgres) #for Postgres driver
    library(dplyr)
    library(dbplyr)
    
    #set output/print resolution
    options(digits.secs=4) 
    
    con <- DBI::dbConnect(RPostgres::Postgres(),
                dbname  = "postgres",
                user = "postgres",
                password = rstudioapi::askForPassword("Database password"),
                host = "localhost",
                port = 5432)
    
    
    dbWriteTable(con, "test", data)
    
    Sys.setenv(TZ = "UTC") #so next line prints in UTC
    
    con %>% tbl(in_schema("public","test")) %>% collect()
    
    
    # A tibble: 3 x 3
    #  event_time               name         float_val
    #  <dttm>                   <chr>            <dbl>
    #1 2019-07-02 07:50:56.6779 E9980.RT_POS      78.7
    #2 2019-07-01 10:40:32.4800 E9984.FT_POS      90.5
    #3 2019-06-21 15:11:00.8250 E9984.RT_POS      78.8
    

    【讨论】:

    • 谢谢,这对我来说很好用。我必须在dbwriteTable(...) 语句之前发出options(digits.secs=4),以便写入亚秒。此外,我必须将host = 'localhost', 添加到DBI::bdConnect()statement 才能使其正常工作。我知道我可能是具有异国情调的默认值的人,因此您可能需要编辑您的答案以使其简洁明了。
    • 同意;无论默认值如何,将 digits.secs 设置为所需的分辨率可能是明智的;我已将两个建议的更改都添加到答案中
    • 我注意到 PostgreSQL 0.6-2 库在编写时会弄乱时区。我的 UTC 时间戳的时区更改为我的本地时区,即使 Sys.setenv(TZ = "UTC") !因此,我强烈推荐使用 Postgres 库。
    • 好点。我在 RPostgres 的答案中更改了包。它的价值:根据我的经验,当 postgresql.conf 中的 timezone = 'UTC' 时,RPostgreSQL 正确地将 POSIXct 对象传递给 postgres。
    • 退房,@Chris,太好了。当 postgresql.conf 中的 timezone = 'UTC' 时,RPostgreSQL 正确地将 POSIXct 对象传递给 postgres。
    猜你喜欢
    • 2020-03-31
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-23
    • 2015-03-28
    • 1970-01-01
    相关资源
    最近更新 更多