PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

LỖI:dữ liệu bổ sung sau cột dự kiến ​​cuối cùng khi sử dụng PostgreSQL COPY

Một bảng trống sẽ không làm. Bạn cần bảng phù hợp với cấu trúc của dữ liệu đầu vào. Một cái gì đó như:

CREATE TABLE raw_data (
  col1 int
, col2 int
  ...
);

Bạn không cần khai báo tab dưới dạng DELIMITER vì đó là mặc định:

COPY raw_data FROM '/home/Projects/TestData/raw_data.txt';

800 cột bạn nói? Nhiều cột đó thường chỉ ra vấn đề với thiết kế của bạn. Dù sao, có nhiều cách để tự động hóa một nửa TẠO BẢNG tập lệnh.

Tự động hóa

Giả sử dữ liệu thô được đơn giản hóa

1   2   3   4  -- first row contains "column names"
1   1   0   1  -- tab separated
1   0   0   1
1   0   1   1

Xác định một DELIMITER khác (một điều hoàn toàn không xảy ra trong dữ liệu nhập) và nhập vào bảng dàn tạm thời với một văn bản duy nhất cột:

CREATE TEMP TABLE tmp_data (raw text);

COPY tmp_data FROM '/home/Projects/TestData/raw_data.txt' WITH (DELIMITER '§');

Truy vấn này tạo TẠO BẢNG tập lệnh:

SELECT 'CREATE TABLE tbl (col' || replace (raw, E'\t', ' bool, col') || ' bool)'
FROM   (SELECT raw FROM tmp_data LIMIT 1) t;

Một truy vấn chung chung hơn và an toàn hơn:

SELECT 'CREATE TABLE tbl('
    ||  string_agg(quote_ident('col' || col), ' bool, ' ORDER  BY ord)
    || ' bool);'
FROM  (SELECT raw FROM tmp_data LIMIT 1) t
     , unnest(string_to_array(t.raw, E'\t')) WITH ORDINALITY c(col, ord);

Lợi nhuận:

CREATE TABLE tbl (col1 bool, col2 bool, col3 bool, col4 bool);

Thực thi sau khi xác minh tính hợp lệ - hoặc thực thi động nếu bạn tin tưởng kết quả:

DO
$$BEGIN
EXECUTE (
   SELECT 'CREATE TABLE tbl (col' || replace(raw, ' ', ' bool, col') || ' bool)'
   FROM  (SELECT raw FROM tmp_data LIMIT 1) t
   );
END$$;

Sau đó, INSERT dữ liệu với truy vấn này:

INSERT INTO tbl
SELECT (('(' || replace(replace(replace(
                  raw
                , '1',   't')
                , '0',   'f')
                , E'\t', ',')
             || ')')::tbl).*
FROM   (SELECT raw FROM tmp_data OFFSET 1) t;

Hoặc đơn giản hơn với translate () :

INSERT INTO tbl
SELECT (('(' || translate(raw, E'10\t', 'tf,') || ')')::tbl).*
FROM   (SELECT raw FROM tmp_data OFFSET 1) t;

Chuỗi được chuyển đổi thành một chữ hàng, được truyền sang loại hàng trong bảng mới được tạo và được phân tách bằng (row). * .

Tất cả đã xong.

Bạn có thể đặt tất cả những điều đó vào một hàm plpgsql, nhưng bạn cần phải bảo vệ khỏi việc đưa vào SQL. (Có một số giải pháp liên quan ở đây trên SO. Hãy thử tìm kiếm.

db <> fiddle tại đây
Fiddle SQL cũ



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để triển khai PostgresQL tsvector cho tìm kiếm toàn văn bằng cách sử dụng Sequelize?

  2. strapi database.js / nhiều cấu hình cơ sở dữ liệu

  3. Làm cách nào để cấp quyền cho người dùng trên tất cả các bảng mới trong Postgres?

  4. Các biến do người dùng xác định trong PostgreSQL

  5. chỉ mục postgresql trên cột chuỗi