1

我是 PostgreSQL 新手,我正在尝试使用 R 将表写入 PostgreSQL。请参阅下面的 R 代码;首先制作一些可重现的数据框:

> Time<-c('201512', '201511', '201510')
> Department<-c('ABC', 'BCA', 'NBA')
> Pro_Type<-c('standard', 'maintain', 'sustaining')
> Man_month<-c('111.4', '124.1', '232.1')
> ID<-c('1','2', '3')
> melt_short<-data.frame(Time, Department, Pro_Type, Man_month, ID)
> melt_short
   Time  Department   Pro_Type Man_month ID
1 201512        ABC   standard     111.4  1
2 201511        BCA   maintain     124.1  2
3 201510        NBA sustaining     232.1  3

然后创建连接:

 require("RPostgreSQL")

# loads the PostgreSQL driver
  drv <- dbDriver("PostgreSQL")
# creates a connection to the postgres database
  con <- dbConnect(drv, dbname = "XXX",
             host = "XXX.XX.XX.XXX", port = 5432,
             user = "postgres", password = XXXXXX)

然后我在 PostgreSQL DB 中创建一个表:

 CREATE TABLE dms_melt
(
  "Time" numeric,
  "Department" character(1),
  "Pro_type" character(1),
  "Man_month" numeric,
  "ID" numeric NOT NULL,
  CONSTRAINT dms_melt_pkey PRIMARY KEY ("ID")
)
WITH (
  OIDS=FALSE
);
 ALTER TABLE dms_melt
 OWNER TO postgres;

最后执行写表代码,报错:

dbWriteTable(con, "dms_melt", value = melt_short, append = T,row.names=F)

Error in postgresqlgetResult(new.con) : 
RS-DBI driver: (could not Retrieve the result : ERROR:  value too long for   
type character(1) CONTEXT:  COPY dms_melt, line 1, column Department: "ABC"

这应该不是那么难,但我一直在寻找解决方案但徒劳无功。实际上我已经使用“mtcars”数据集来写表并且没有问题。

data(mtcars)
df <- data.frame(carname = rownames(mtcars), 
                 mtcars, 
                 row.names = NULL)
df$carname <- as.character(df$carname)

dbWriteTable(con, "cartable", 
             value = df, append = TRUE, row.names = FALSE)
[1] TRUE

插入了我创建的 PostgreSQL:

CREATE TABLE cartable
(
  carname character varying,
  mpg numeric(3,1),
  cyl numeric(1,0),
  disp numeric(4,1),
  hp numeric(3,0),
  drat numeric(3,2),
  wt numeric(4,3),
  qsec numeric(4,2),
  vs numeric(1,0),
  am numeric(1,0),
  gear numeric(1,0),
  carb numeric(1,0)
 )
 WITH (
  OIDS=FALSE
 );
 ALTER TABLE cartable
 OWNER TO postgres;

提前感谢您的任何建议和想法。

4

1 回答 1

3

注意以下两个表列的数据类型:

...
"Department" character(1),
"Pro_type" character(1),
...

现在让我们看看您要插入的数据:

   Time  Department   Pro_Type Man_month ID
1 201512        ABC   standard     111.4  1
2 201511        BCA   maintain     124.1  2
3 201510        NBA sustaining     232.1  3

现在错误消息:

Error in postgresqlgetResult(new.con) :
RS-DBI driver: (could not Retrieve the result : ERROR:  value too long for
type character(1) CONTEXT:  COPY dms_melt, line 1, column Department: "ABC"

PostgreSQL 中的character(N)数据类型是定长字符串类型。该列中的每个值都必须是长度为 N 的字符串。对于character(1),这意味着每个值都必须包含一个字符。

该值是一个长度为 3 的字符串。对于数据类型'ABC'来说它太长了。character(1)

您可能会将 R 字符向量类型与 SQL 字符类型混淆。在 R 中,字符向量的每个元素都是一个可变长度的字符串。具有讽刺意味的是,您可以使用 R 中的语法构造一个字符向量,character(N)其中 N 是结果向量中可变长度字符串元素的数量。在 SQL 中,您可以将列视为向量,但数据类型始终指的是单个单元格值的标量类型。SQL 语法中的 Ncharacter(N)是指每个字符串中的字符数。

您的mtcars测试有效的原因是因为该表中唯一的字符串列具有没有长度规范的carname数据类型。character varyingPostgreSQL 文档

如果在没有长度说明符的情况下使用字符变化,则该类型接受任何大小的字符串。后者是 PostgreSQL 扩展。

因此,您可以通过对这两列使用character varying(或更简洁的名称)来解决问题。varchar您可以像在mtcars模式中一样省略长度规范,或者如果您知道这些列的值的合同长度限制,您可以指定varchar(N)其中 N 是长度限制。此外,如果Department值总是 3 个字符长,您可以选择使用char(3)固定长度类型。

概括:

SQL
==========

character(N)            fixed-length strings of length N
char(N)                 alias for character(N)
character               alias for character(1)
char                    alias for character(1)
character varying(N)    variable-length strings of maximum length N
varchar(N)              alias for character varying(N)
character varying       variable-length strings of unlimited length
varchar                 alias for character varying

R
==========

character(N)            vector of length N of variable-length strings
于 2016-04-16T05:09:18.820 回答