Được rồi, tôi không chắc tại sao lại dbWriteTable()
sẽ thất bại; có thể có một số loại phiên bản / giao thức không khớp. Có lẽ bạn có thể thử cài đặt phiên bản mới nhất của R, gói RPostgreSQL và nâng cấp máy chủ PostgreSQL trên hệ thống của mình, nếu có thể.
Về insert into
cách giải quyết không thành công đối với dữ liệu lớn, điều thường được thực hiện trong thế giới CNTT khi phải di chuyển một lượng lớn dữ liệu và việc truyền một lần là không khả thi / không thực tế / không ổn định là những gì đôi khi được gọi là lô hoặc xử lý hàng loạt
. Về cơ bản, bạn chia dữ liệu thành nhiều phần nhỏ hơn và gửi từng phần một.
Như một ví dụ ngẫu nhiên, một vài năm trước, tôi đã viết một số mã Java để truy vấn thông tin nhân viên từ máy chủ HR LDAP bị hạn chế chỉ cung cấp 1000 bản ghi cùng một lúc. Vì vậy, về cơ bản tôi phải viết một vòng lặp để tiếp tục gửi cùng một yêu cầu (với trạng thái truy vấn được theo dõi bằng cách sử dụng một số loại cơ chế dựa trên cookie kỳ lạ ) và tích lũy các bản ghi vào cơ sở dữ liệu cục bộ cho đến khi máy chủ báo cáo truy vấn hoàn tất.
Dưới đây là một số mã tạo SQL theo cách thủ công để tạo một bảng trống dựa trên data.frame nhất định, sau đó chèn nội dung của data.frame vào bảng bằng cách sử dụng kích thước lô được tham số hóa. Nó chủ yếu được xây dựng xung quanh các cuộc gọi tới paste()
để xây dựng các chuỗi SQL và dbSendQuery()
để gửi các truy vấn thực tế. Tôi cũng sử dụng postgresqlDataType()
để tạo bảng.
## connect to the DB
library('RPostgreSQL'); ## loads DBI automatically
drv <- dbDriver('PostgreSQL');
con <- dbConnect(drv,host=...,port=...,dbname=...,user=...,password=...);
## define helper functions
createEmptyTable <- function(con,tn,df) {
sql <- paste0("create table \"",tn,"\" (",paste0(collapse=',','"',names(df),'" ',sapply(df[0,],postgresqlDataType)),");");
dbSendQuery(con,sql);
invisible();
};
insertBatch <- function(con,tn,df,size=100L) {
if (nrow(df)==0L) return(invisible());
cnt <- (nrow(df)-1L)%/%size+1L;
for (i in seq(0L,len=cnt)) {
sql <- paste0("insert into \"",tn,"\" values (",do.call(paste,c(sep=',',collapse='),(',lapply(df[seq(i*size+1L,min(nrow(df),(i+1L)*size)),],shQuote))),");");
dbSendQuery(con,sql);
};
invisible();
};
## generate test data
NC <- 1e2L; NR <- 1e3L; df <- as.data.frame(replicate(NC,runif(NR)));
## run it
tn <- 't1';
dbRemoveTable(con,tn);
createEmptyTable(con,tn,df);
insertBatch(con,tn,df);
res <- dbReadTable(con,tn);
all.equal(df,res);
## [1] TRUE
Lưu ý rằng tôi không bận tâm về việc viết trước row.names
vào bảng cơ sở dữ liệu, không giống như dbWriteTable()
, dường như luôn bao gồm một cột như vậy (và dường như không cung cấp bất kỳ biện pháp nào để ngăn chặn nó).