使用 R 从 SQL 服务器导入数据截断前导零

Importing data using R from SQL Server truncate leading zeros

我正在尝试从 SQL 服务器中的 table 导入数据,然后将其写入 .txt 文件。我正在按以下方式进行。但是,当我这样做时,所有前导 0 的数字似乎都被修剪了。

例如,如果我在数据库中有 000124,它在 .txt 中显示为 124 以及如果我检查 x_1 它在那里是 124嗯。

我怎样才能避免这种情况?我想在 x_1 中保留前导 0 并且在输出 .txt 文件中也需要它们。

library(RODBC)
library(lubridate)
library(data.table)

cn_1 <- odbcConnect('channel_name')
qry <- "
select
    *
from table_name
"
x_1 <- sqlQuery(channel=cn_1, query=qry, stringsAsFactors=FALSE)
rm(qry)
setDT(x_1)
fwrite(x=x_1, file=paste0(export_location, "file_name", date_today, ".txt"), sep="|", quote=TRUE, row.names=FALSE, na="")

x_1 成为您 SQL 查询的结果 data.table。然后,您可以使用 sprintf 将数字列(例如 value)转换为格式化字符串以获得前导零:

library(data.table)

x_1 <- data.table(value = c(1,12,123,1234))
x_1
#>    value
#> 1:     1
#> 2:    12
#> 3:   123
#> 4:  1234

x_1$value <- x_1$value |> sprintf(fmt = "%04d")
x_1
#>    value
#> 1:  0001
#> 2:  0012
#> 3:  0123
#> 4:  1234

reprex package (v2.0.1)

于 2021-10-08 创建

假设 DBMS 中的基础数据确实是类似“字符串”的...

RODBC::sqlQueryas.is= 参数可以防止它尝试转换值。默认值为 FALSE,当 false 且不是像 "date""timestamp" 这样的明确类型时,RODBC 调用 type.convert 将看到类似数字的字段并将其转换为整数或数字。

尝试:

x_1 <- sqlQuery(channel=cn_1, query=qry, stringsAsFactors=FALSE, as.is = TRUE)

这将停止所有列的自动转换。

老实说,这有点核,并且会停止 dates/times 的转换,也许 应该 转换的其他列。我们可以缩小范围; ?sqlQueryread.table 关于 as.is 的文档是相关的,它说:

   as.is: controls conversion of character variables (insofar as they
          are not converted to logical, numeric or complex) to factors,
          if not otherwise specified by 'colClasses'.  Its value is
          either a vector of logicals (values are recycled if
          necessary), or a vector of numeric or character indices which
          specify which columns should not be converted to factors.

所以如果您知道哪个列(按名称或列索引)被不必要地转换,那么您可以直接包含它。也许

## by column name
x_1 <- sqlQuery(channel=cn_1, query=qry, stringsAsFactors=FALSE, as.is = "somename")

## or by column index
x_1 <- sqlQuery(channel=cn_1, query=qry, stringsAsFactors=FALSE, as.is = 7)

(旁注:虽然我有时也会使用 select * ...,但按编号知道列的假设是基于知道 table/query 中包含的所有列。如果有任何变化,也许它实际上是一个 SQL 视图并且有人更新了它......或者如果有人更改了列的顺序,那么你对列索引的假设有点脆弱。我内部包中的所有“生产”查询都有所有列都拼写出来了,没有使用 select *。我 使用它时被咬过一次,这就是为什么我对此有点防御。)

如果您不知道,一种仓促动态的方式(不幸的是双击查询)可能类似于

qry10 <- "
select
    *
from table_name
limit 10"
x_1 <- sqlQuery(channel=cn_1, query=qry10, stringsAsFactors=FALSE, as.is = TRUE)
leadzero <- sapply(x_1, function(z) all(grepl("^0+[1-9]", z)))
x_1 <- sqlQuery(channel=cn_1, query=qry, stringsAsFactors=FALSE, as.is = which(leadzero))

警告:我不使用 RODBC 也没有设置具有适当时尚值的临时数据库,因此未经测试。