PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

BŁĄD:dodatkowe dane po ostatniej oczekiwanej kolumnie podczas korzystania z PostgreSQL COPY

Pusty stół nie wystarczy. Potrzebujesz tabeli, która pasuje do struktury danych wejściowych. Coś takiego:

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

Nie musisz deklarować tab jako DELIMITER ponieważ jest to ustawienie domyślne:

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

800 kolumn mówisz? Tyle kolumn zwykle wskazuje na problem z projektem. W każdym razie są sposoby na półautomatyczną automatyzację CREATE TABLE skrypt.

Automatyzacja

Zakładając uproszczone nieprzetworzone dane

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

Zdefiniuj inny DELIMITER (taka, która w ogóle nie występuje w importowanych danych) i import do tymczasowej tabeli pomostowej z pojedynczym tekstem kolumna:

CREATE TEMP TABLE tmp_data (raw text);

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

To zapytanie tworzy CREATE TABLE skrypt:

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

Bardziej ogólne i bezpieczniejsze zapytanie:

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);

Zwroty:

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

Wykonaj po zweryfikowaniu poprawności - lub wykonaj dynamicznie, jeśli ufasz wynikowi:

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

Następnie WSTAW dane z tym zapytaniem:

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

Lub prościej dzięki translate() :

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

Ciąg jest konwertowany na literał wiersza, rzutowany na nowo utworzony typ wiersza tabeli i rozkładany za pomocą (row).* .

Wszystko gotowe.

Możesz to wszystko umieścić w funkcji plpgsql, ale musisz zabezpieczyć się przed wstrzyknięciem SQL. (W SO jest wiele powiązanych rozwiązań. Spróbuj wyszukać.

db<>fiddle tutaj
Stare skrzypce SQL



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak sprawić, by postgresSQL działał na komputerze z systemem Windows 7 z django?

  2. Napraw uszkodzoną bazę danych postgresql

  3. Jaka jest żywotność przygotowanego oświadczenia po stronie serwera PostgreSQL

  4. Plan wyjaśniania SQL:co to jest Materialise?

  5. 2 sposoby na uzyskanie rozmiaru bazy danych w PostgreSQL