首页 > 解决方案 > 如何将 POSIXct / POSIXt 时间戳从 R 写入 Postgres 表

问题描述

我有一个 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’

标签: rpostgresqldplyrodbcdbi

解决方案


使用 postgres 驱动程序RPostgres而不是odbc.

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

推荐阅读