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

Kopiuj CSV do Postgresa z tablicą niestandardowego typu za pomocą JDBC

Zobacz https://git.mikael.io/mikaelhg/pg -object-csv-copy-poc/ dla projektu z testem JUnit, który robi to, co chcesz.

Zasadniczo chcesz mieć możliwość używania przecinków do dwóch rzeczy:do oddzielania elementów tablicy i oddzielania pól typu, ale NIE chcesz, aby analiza CSV interpretowała przecinki jako separatory pól.

Więc

  1. chcesz powiedzieć parserowi CSV, aby traktował cały wiersz jako jeden ciąg, jedno pole, co możesz zrobić, umieszczając go w pojedynczych cudzysłowach i informując o tym parser CSV, oraz
  2. chcesz, aby parser pól PG brał pod uwagę każdą instancję typu elementu tablicy jako ujętą w podwójny cudzysłów.

Kod:

copyManager.copyIn("COPY my_table (addresses) FROM STDIN WITH CSV QUOTE ''''", reader);

Przykład DML 1:

COPY my_table (addresses) FROM STDIN WITH CSV QUOTE ''''

Przykład CSV 1:

'{"(10.0.0.1,1)","(10.0.0.2,2)"}'
'{"(10.10.10.1,80)","(10.10.10.2,443)"}'
'{"(10.10.10.3,8080)","(10.10.10.4,4040)"}'

Przykład 2 DML, unikanie podwójnych cudzysłowów:

COPY my_table (addresses) FROM STDIN WITH CSV

CSV przykład 2, unikanie podwójnych cudzysłowów:

"{""(10.0.0.1,1)"",""(10.0.0.2,2)""}"
"{""(10.10.10.1,80)"",""(10.10.10.2,443)""}"
"{""(10.10.10.3,8080)"",""(10.10.10.4,4040)""}"

Pełna klasa testowa JUnit:

package io.mikael.poc;

import com.google.common.io.CharStreams;
import org.junit.*;
import org.postgresql.PGConnection;
import org.postgresql.copy.CopyManager;
import org.testcontainers.containers.PostgreSQLContainer;

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;

import static java.nio.charset.StandardCharsets.UTF_8;

public class CopyTest {

    private Reader reader;

    private Connection connection;

    private CopyManager copyManager;

    private static final String CREATE_TYPE = "CREATE TYPE address AS (ip inet, port int)";

    private static final String CREATE_TABLE = "CREATE TABLE my_table (addresses  address[] NULL)";

    private String loadCsvFromFile(final String fileName) throws IOException {
        try (InputStream is = getClass().getResourceAsStream(fileName)) {
            return CharStreams.toString(new InputStreamReader(is, UTF_8));
        }
    }

    @ClassRule
    public static PostgreSQLContainer db = new PostgreSQLContainer("postgres:10-alpine");

    @BeforeClass
    public static void beforeClass() throws Exception {
        Class.forName("org.postgresql.Driver");
    }

    @Before
    public void before() throws Exception {
        String input = loadCsvFromFile("/data_01.csv");
        reader = new StringReader(input);

        connection = DriverManager.getConnection(db.getJdbcUrl(), db.getUsername(), db.getPassword());
        copyManager = connection.unwrap(PGConnection.class).getCopyAPI();

        connection.setAutoCommit(false);
        connection.beginRequest();

        connection.prepareCall(CREATE_TYPE).execute();
        connection.prepareCall(CREATE_TABLE).execute();
    }

    @After
    public void after() throws Exception {
        connection.rollback();
    }

    @Test
    public void copyTest01() throws Exception {
        copyManager.copyIn("COPY my_table (addresses) FROM STDIN WITH CSV QUOTE ''''", reader);

        final StringWriter writer = new StringWriter();
        copyManager.copyOut("COPY my_table TO STDOUT WITH CSV", writer);
        System.out.printf("roundtrip:%n%s%n", writer.toString());

        final ResultSet rs = connection.prepareStatement(
                "SELECT array_to_json(array_agg(t)) FROM (SELECT addresses FROM my_table) t")
                .executeQuery();
        rs.next();
        System.out.printf("json:%n%s%n", rs.getString(1));
    }

}

Wyjście testowe:

roundtrip:
"{""(10.0.0.1,1)"",""(10.0.0.2,2)""}"
"{""(10.10.10.1,80)"",""(10.10.10.2,443)""}"
"{""(10.10.10.3,8080)"",""(10.10.10.4,4040)""}"

json:
[{"addresses":[{"ip":"10.0.0.1","port":1},{"ip":"10.0.0.2","port":2}]},{"addresses":[{"ip":"10.10.10.1","port":80},{"ip":"10.10.10.2","port":443}]},{"addresses":[{"ip":"10.10.10.3","port":8080},{"ip":"10.10.10.4","port":4040}]}]


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wykonywanie zmian topologii replikacji dla PostgreSQL

  2. Dlaczego warunki CROSS JOIN nie działają w klauzuli „ON”, tylko klauzula WHERE?

  3. nieprawidłowa sekwencja bajtów do kodowania UTF8

  4. Znajdowanie pozycji wartości w tablicach PostgreSQL

  5. Jak wykonać podzapytanie Postgresql w klauzuli select z klauzulą ​​Join in from, taką jak SQL Server?