Verwenden des JDBC-Treibers

Unter diesem Thema werden Informationen zur Verwendung des JDBC-Treibers bereitgestellt.

Unter diesem Thema:

Snowflake-JDBC-API-Erweiterungen

Der Snowflake-JDBC-Treiber unterstützt zusätzliche Methoden, die über JDBC-die Standardspezifikation hinausgehen. In diesem Abschnitt wird beschrieben, wie Sie beim Entpacken den Zugriff auf die Snowflake-spezifischen Methoden bereitstellen. Anschließend werden drei Situationen beschrieben, in denen ein Entpacken möglicherweise erforderlich ist:

Entpacken von Snowflake-spezifischen Klassen

Der Snowflake-JDBC-Treiber unterstützt Snowflake-spezifische Methoden. Folgende Methoden sind Snowflake-spezifische, in Java codierte Schnittstellen wie SnowflakeConnection, SnowflakeStatement und SnowflakeResultSet. Beispielsweise enthält die SnowflakeStatement-Schnittstelle eine getQueryID()-Methode, die in der JDBC-Statement-Schnittstelle nicht definiert ist.

Wenn der Snowflake-JDBC-Treiber aufgefordert wird, ein JDBC-Objekt zu erstellen (z. B. Erstellen eines JDBC-Statement-Objekts durch Aufrufen der createStatement()-Methode eines Connection-Objekts), erstellt der Snowflake-JDBC-Treiber tatsächlich Snowflake-spezifische Objekte, die nicht nur die Methoden des JDBC-Standards, sondern auch die zusätzlichen Methoden der Snowflake-Schnittstellen implementieren.

Um auf diese Snowflake-Methoden zuzugreifen, „entpacken“ Sie das Objekt (z. B. ein Statement-Objekt), sodass das Snowflake-Objekt und seine Methoden verfügbar sind. Sie können dann die zusätzlichen Methoden aufrufen.

Der folgende Code zeigt, wie Sie ein JDBC-Statement-Objekt entpacken, um die Methoden der SnowflakeStatement-Schnittstelle verfügbar zu machen, und dann eine dieser Methoden aufrufen, in diesem Fall setParameter:

Statement statement1;
...
// Unwrap the statement1 object to expose the SnowflakeStatement object, and call the
// SnowflakeStatement object's setParameter() method.
statement1.unwrap(SnowflakeStatement.class).setParameter(...);
Copy

Ausführen einer asynchronen Abfrage

Der Snowflake-JDBC-Treiber unterstützt asynchrone Abfragen (d. h. Abfragen, die dem Benutzer die Kontrolle zurückgeben, bevor die Abfrage abgeschlossen ist). Benutzer können eine Abfrage starten und dann durch Abrufen feststellen, wann die Abfrage abgeschlossen ist. Nach Abschluss der Abfrage kann der Benutzer das Resultset lesen.

Mit diesem Feature kann ein Clientprogramm mehrere Abfragen parallel ausführen, ohne dass das Clientprogramm selbst Multithreading verwendet.

Asynchrone Abfragen verwenden Methoden, die den Klassen SnowflakeConnection, SnowflakeStatement, SnowflakePreparedStatement und SnowflakeResultSet hinzugefügt wurden.

Bemerkung

Um asynchrone Abfragen auszuführen, müssen Sie sicherstellen, dass der Konfigurationsparameter ABORT_DETACHED_QUERY den Wert FALSE hat (Standardwert).

Snowflake schließt Verbindungen automatisch nach einer bestimmten Zeit (Standard: 5 Minuten), wodurch alle aktiven Abfragen verwaist sind. Wenn der Wert TRUE ist, bricht Snowflake diese verwaisten Abfragen ab, was sich auf asynchrone Abfragen auswirken kann.

Sie können in derselben Sitzung eine Mischung aus synchronen und asynchronen Abfragen ausführen.

Best Practices für asynchrone Abfragen

  • Stellen Sie vor der parallelen Ausführung von Abfragen sicher, dass Sie die Abhängigkeiten der Abfragen von anderen Abfragen genau kennen. Einige Abfragen sind voneinander und von der Ausführungsreihenfolge abhängig und sind daher nicht für die Parallelisierung geeignet. Beispielsweise kann eine INSERT-Anweisung offensichtlich erst beginnen, nachdem die entsprechende CREATE TABLE-Anweisung abgeschlossen wurde.

  • Stellen Sie sicher, dass die Anzahl der gestarteten Abfragen auf den verfügbaren Arbeitsspeicher abgestimmt ist. Das parallele Ausführen mehrerer Abfragen beansprucht normalerweise mehr Speicher, insbesondere wenn mehr als ein ResultSet gleichzeitig im Arbeitsspeicher gespeichert ist.

  • Behandeln Sie beim Abrufen die seltenen Fälle, in denen eine Abfrage nicht erfolgreich ist. Vermeiden Sie beispielsweise die folgende potenzielle Endlosschleife:

    QueryStatus queryStatus = QueryStatus.RUNNING;
    while (queryStatus != QueryStatus.SUCCESS)  {     //  NOT RECOMMENDED
        Thread.sleep(2000);   // 2000 milliseconds.
        queryStatus = resultSet.unwrap(SnowflakeResultSet.class).getStatus();
        }
    
    Copy

    Verwenden Sie stattdessen ungefähr folgenden Code:

    // Assume that the query is not done yet.
    QueryStatus queryStatus = QueryStatus.RUNNING;
    while (queryStatus == QueryStatus.RUNNING || queryStatus == QueryStatus.RESUMING_WAREHOUSE)  {
        Thread.sleep(2000);   // 2000 milliseconds.
        queryStatus = resultSet.unwrap(SnowflakeResultSet.class).getStatus();
        }
    
    if (queryStatus == QueryStatus.SUCCESS) {
        ...
        }
    
    Copy
  • Stellen Sie sicher, dass Anweisungen zur Transaktionssteuerung (BEGIN, COMMIT und ROLLBACK) nicht parallel zu anderen Anweisungen ausgeführt werden.

Beispiele für asynchrone Abfragen

In den meisten dieser Beispiele muss das Programm die folgenden Klassen importieren:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import net.snowflake.client.core.QueryStatus;
import net.snowflake.client.jdbc.SnowflakeConnection;
import net.snowflake.client.jdbc.SnowflakeResultSet;
import net.snowflake.client.jdbc.SnowflakeStatement;
Copy

Dies ist ein sehr einfaches Beispiel:

    String sql_command = "";
    ResultSet resultSet;

    System.out.println("Create JDBC statement.");
    Statement statement = connection.createStatement();
    sql_command = "SELECT PI()";
    System.out.println("Simple SELECT query: " + sql_command);
    resultSet = statement.unwrap(SnowflakeStatement.class).executeAsyncQuery(sql_command);

    // Assume that the query isn't done yet.
    QueryStatus queryStatus = QueryStatus.RUNNING;
    while (queryStatus == QueryStatus.RUNNING || queryStatus == QueryStatus.RESUMING_WAREHOUSE) {
      Thread.sleep(2000); // 2000 milliseconds.
      queryStatus = resultSet.unwrap(SnowflakeResultSet.class).getStatus();
    }

    if (queryStatus == QueryStatus.FAILED_WITH_ERROR) {
      // Print the error code to stdout
      System.out.format("Error code: %d%n", queryStatus.getErrorCode());
      System.out.format("Error message: %s%n", queryStatus.getErrorMessage());
    } else if (queryStatus != QueryStatus.SUCCESS) {
      System.out.println("ERROR: unexpected QueryStatus: " + queryStatus);
    } else {
      boolean result_exists = resultSet.next();
      if (!result_exists) {
        System.out.println("ERROR: No rows returned.");
      } else {
        float pi_result = resultSet.getFloat(1);
        System.out.println("pi = " + pi_result);
      }
    }
Copy

In diesem Beispiel wird die Abfrage-ID gespeichert, die Verbindung geschlossen, die Verbindung erneut geöffnet und die Daten werden mithilfe der Abfrage-ID abgerufen:

    String sql_command = "";
    ResultSet resultSet;
    String queryID = "";

    System.out.println("Create JDBC statement.");
    Statement statement = connection.createStatement();
    sql_command = "SELECT PI() * 2";
    System.out.println("Simple SELECT query: " + sql_command);
    resultSet = statement.unwrap(SnowflakeStatement.class).executeAsyncQuery(sql_command);
    queryID = resultSet.unwrap(SnowflakeResultSet.class).getQueryID();
    System.out.println("INFO: Closing statement.");
    statement.close();
    System.out.println("INFO: Closing connection.");
    connection.close();

    System.out.println("INFO: Re-opening connection.");
    connection = create_connection(args);
    use_warehouse_db_and_schema(connection);
    resultSet = connection.unwrap(SnowflakeConnection.class).createResultSet(queryID);

    // Assume that the query isn't done yet.
    QueryStatus queryStatus = QueryStatus.RUNNING;
    while (queryStatus == QueryStatus.RUNNING) {
      Thread.sleep(2000); // 2000 milliseconds.
      queryStatus = resultSet.unwrap(SnowflakeResultSet.class).getStatus();
    }

    if (queryStatus == QueryStatus.FAILED_WITH_ERROR) {
      System.out.format(
          "ERROR %d: %s%n", queryStatus.getErrorMessage(), queryStatus.getErrorCode());
    } else if (queryStatus != QueryStatus.SUCCESS) {
      System.out.println("ERROR: unexpected QueryStatus: " + queryStatus);
    } else {
      boolean result_exists = resultSet.next();
      if (!result_exists) {
        System.out.println("ERROR: No rows returned.");
      } else {
        float pi_result = resultSet.getFloat(1);
        System.out.println("pi = " + pi_result);
      }
    }
Copy

Datendateien direkt von einem Stream in einen internen Stagingbereich hochladen

Sie können Datendateien mit dem PUT-Befehl hochladen. Manchmal ist es jedoch sinnvoll, Daten direkt von einem Stream in einen internen (d. h. Snowflake) Stagingbereich als Datei zu übertragen. (Der Stagingbereich kann ein beliebiger interner Stagingbereich vom Typ Tabellen-, Benutzer- oder benannter Stagingbereich sein. Der JDBC-Treiber bietet keine Unterstützung für das Hochladen in einen externen Stagingbereich.) Folgende Methode wird in der Klasse SnowflakeConnection bereitgestellt:

/**
 * Method to compress data from a stream and upload it at a stage location.
 * The data will be uploaded as one file. No splitting is done in this method.
 *
 * Caller is responsible for releasing the inputStream after the method is
 * called.
 *
 * @param stageName    stage name: e.g. ~ or table name or stage name
 * @param destPrefix   path / prefix under which the data should be uploaded on the stage
 * @param inputStream  input stream from which the data will be uploaded
 * @param destFileName destination file name to use
 * @param compressData compress data or not before uploading stream
 * @throws java.sql.SQLException failed to compress and put data from a stream at stage
 */
public void uploadStream(String stageName,
                         String destPrefix,
                         InputStream inputStream,
                         String destFileName,
                         boolean compressData)
    throws SQLException
Copy

Anwendung des Beispiels:

Connection connection = DriverManager.getConnection(url, prop);
File file = new File("/tmp/test.csv");
FileInputStream fileInputStream = new FileInputStream(file);

// upload file stream to user stage
connection.unwrap(SnowflakeConnection.class).uploadStream("MYSTAGE", "testUploadStream",
   fileInputStream, "destFile.csv", true);
Copy

Code, der für JDBC-Treiberversionen vor 3.9.2 geschrieben wurde, wird möglicherweise in SnowflakeConnectionV1 umgewandelt und nicht in SnowflakeConnection.class entpackt. Beispiel:

...

// For versions prior to 3.9.2:
// upload file stream to user stage
((SnowflakeConnectionV1) connection.uploadStream("MYSTAGE", "testUploadStream",
   fileInputStream, "destFile.csv", true));
Copy

Bemerkung

Kunden, die neuere Versionen des Treibers verwenden, sollten ihren Code für die Verwendung von unwrap aktualisieren.

Datendateien direkt von einem internen Stagingbereich in einen Stream herunterladen

Sie können Datendateien mit dem GET-Befehl herunterladen. Manchmal ist es jedoch sinnvoll, Daten direkt aus einer Datei in einen internen (d. h. Snowflake) Stagingbereich für einen Stream zu übertragen. (Der Stagingbereich kann ein beliebiger interner Stagingbereich vom Typ Tabellen-, Benutzer- oder benannter Stagingbereich sein. Der JDBC-Treiber bietet keine Unterstützung für das Herunterladen in einen externen Stagingbereich.) Folgende Methode wird in der Klasse SnowflakeConnection bereitgestellt:

/**
 * Download file from the given stage and return an input stream
 *
 * @param stageName      stage name
 * @param sourceFileName file path in stage
 * @param decompress     true if file compressed
 * @return an input stream
 * @throws SnowflakeSQLException if any SQL error occurs.
 */
InputStream downloadStream(String stageName,
                           String sourceFileName,
                           boolean decompress) throws SQLException;
Copy

Anwendung des Beispiels:

Connection connection = DriverManager.getConnection(url, prop);
InputStream out = connection.unwrap(SnowflakeConnection.class).downloadStream(
    "~",
    DEST_PREFIX + "/" + TEST_DATA_FILE + ".gz",
    true);
Copy

Code, der für JDBC-Treiberversionen vor 3.9.2 geschrieben wurde, wird möglicherweise in SnowflakeConnectionV1 umgewandelt und nicht in SnowflakeConnection.class entpackt. Beispiel:

...

// For versions prior to 3.9.2:
// download file stream to user stage
((SnowflakeConnectionV1) connection.downloadStream(...));
Copy

Unterstützung für mehrere Anweisungen

In diesem Abschnitt wird beschrieben, wie Sie mit JDBC-Treiber mehrere Anweisungen in einer einzelnen Anforderung ausführen.

Bemerkung

Standardmäßig gibt Snowflake bei Abfragen mit mehreren Anweisungen einen Fehler zurück. Dieses Verhalten dient teilweise zum Schutz vor einer Einschleusung von SQL-Befehlen. Die Verwendung der Funktion für mehrere Anweisungen eröffnet die Möglichkeit der Einschleusung von SQL-Befehlen und sollte mit größter Sorgfalt verwendet werden. Das Risiko kann verringert werden, indem mit der setParameter()-Methode der SnowflakeStatement-Klasse die Anzahl der auszuführenden Anweisungen angegeben wird. Dies erschwert das Einfügen einer Anweisung durch Anhängen. Weitere Details dazu finden Sie unter Schnittstelle: SnowflakeStatement.

Senden mehrerer Anweisungen und Verarbeiten der Ergebnisse

Abfragen, die mehrere Anweisungen enthalten, können auf dieselbe Weise wie Abfragen mit einer einzelnen Anweisung ausgeführt werden, mit der Ausnahme, dass die Abfragezeichenfolge mehrere durch Semikolons getrennte Anweisungen enthält.

Es gibt zwei Möglichkeiten, mehrere Anweisungen zuzulassen:

  • Rufen Sie Statement.setParameter („MULTI_STATEMENT_COUNT“, n) auf, um anzugeben, wie viele Anweisungen gleichzeitig ausgeführt werden dürfen. Weitere Details dazu finden Sie unten.

  • Legen Sie den Parameter MULTI_STATEMENT_COUNT auf Sitzungsebene oder Kontoebene fest, indem Sie einen der folgenden Befehle ausführen:

    alter session set MULTI_STATEMENT_COUNT = 0;
    
    Copy

    Oder:

    alter account set MULTI_STATEMENT_COUNT = 0;
    
    Copy

    Wenn Sie den Parameter auf 0 setzen, wird eine unbegrenzte Anzahl von Anweisungen zugelassen. Wenn Sie den Parameter auf 1 setzen, wird jeweils nur eine Anweisung zugelassen.

Um Angriffe durch Einschleusung von SQL-Befehlen zu erschweren, können Benutzer mithilfe der setParameter-Methode die Anzahl der Anweisungen angeben, die durch einen einzelnen Aufruf ausgeführt werden sollen (siehe unten). In diesem Beispiel beträgt die Anzahl der Anweisungen, die durch einen einzelnen Aufruf ausgeführt werden sollen, 3:

// Specify the number of statements that we expect to execute.
statement.unwrap(SnowflakeStatement.class).setParameter(
        "MULTI_STATEMENT_COUNT", 3);
Copy

Die Standardanzahl der Anweisungen ist 1. Mit anderen Worten, der Mehrfachanweisungsmodus ist deaktiviert.

Übergeben Sie den Wert 0, um mehrere Anweisungen auszuführen, ohne die genaue Anzahl anzugeben.

Der Parameter MULTI_STATEMENT_COUNT ist nicht Teil des JDBC-Standards, sondern eine Snowflake-Erweiterung. Dieser Parameter betrifft mehr als einen Snowflake-Treiber oder -Konnektor.

Wenn in einer einzigen execute()-Anweisung mehrere Anweisungen ausgeführt werden, ist das Ergebnis der ersten Anweisung über die Standardmethoden getResultSet() und getUpdateCount() verfügbar. Verwenden Sie die Methode getMoreResults(), um auf die Ergebnisse der nachfolgenden Anweisungen zuzugreifen. Diese Methode gibt true zurück, wenn weitere Anweisungen für die Iteration verfügbar sind, und false falls nicht.

Im folgenden Beispiel wird der Parameter MULTI_STATEMENT_COUNT festgelegt, dann werden 3 Anweisungen ausgeführt und schließlich werden die Aktualisierungszähler und die Resultsets abgerufen:

// Create a string that contains multiple SQL statements.
String command_string = "create table test(n int); " +
                        "insert into test values (1), (2); " +
                        "select * from test order by n";
Statement stmt = connection.createStatement();
// Specify the number of statements (3) that we expect to execute.
stmt.unwrap(SnowflakeStatement.class).setParameter(
        "MULTI_STATEMENT_COUNT", 3);

// Execute all of the statements.
stmt.execute(command_string);                       // false

// --- Get results. ---
// First statement (create table)
stmt.getUpdateCount();                              // 0 (DDL)

// Second statement (insert)
stmt.getMoreResults();                              // true
stmt.getUpdateCount();                              // 2

// Third statement (select)
stmt.getMoreResults();                              // true
ResultSet rs = stmt.getResultSet();
rs.next();                                          // true
rs.getInt(1);                                       // 1
rs.next();                                          // true
rs.getInt(1);                                       // 2
rs.next();                                          // false

// Past the last statement executed.
stmt.getMoreResults();                              // false
stmt.getUpdateCount();                              // 0 (no more results)
Copy

Snowflake empfiehlt die Verwendung von execute() für Abfragen mit mehreren Anweisungen. Die Methoden executeQuery() und executeUpdate() unterstützen auch mehrere Anweisungen, lösen jedoch eine Ausnahme aus, wenn das erste Ergebnis nicht dem erwarteten Ergebnistyp entspricht (Resultset bzw. Aktualisierungsanzahl).

Fehlgeschlagene Anweisungen

Wenn eine der SQL-Anweisungen nicht kompiliert oder ausgeführt werden kann, wird die Ausführung abgebrochen. Alle vorherigen Anweisungen, die zuvor ausgeführt wurden, bleiben davon unberührt.

Im folgenden Beispiel werden Anweisungen als einzelne Abfrage mit mehreren Anweisungen ausgeführt. Dabei schlägt die Abfrage bei der dritten Anweisung fehl, und es wird eine Ausnahme ausgelöst.

CREATE OR REPLACE TABLE test(n int);
INSERT INTO TEST VALUES (1), (2);
INSERT INTO TEST VALUES ('not_an_int');  -- execution fails here
INSERT INTO TEST VALUES (3);
Copy

Wenn Sie dann den Inhalt der Tabelle test abfragen würden, wären die Werte 1 und 2 vorhanden.

Nicht unterstützte Features

PUT- und GET-Anweisungen werden für Abfragen mit mehreren Anweisungen nicht unterstützt.

Das Vorbereiten von Anweisungen und die Verwendung von Bindungsvariablen werden für Abfragen mit mehreren Anweisungen ebenfalls nicht unterstützt.

Binden von Variablen an Anweisungen

Durch Binden können SQL-Anweisungen Werte verwenden, die in einer Java-Variablen gespeichert sind.

Einfaches Binden

Ohne Binden gibt eine SQL-Anweisung Werte an, indem sie Literale innerhalb der Anweisung angibt. Die folgende Anweisung verwendet z. B. den Literalwert 42 in einer UPDATE-Anweisung:

stmt.execute("UPDATE table1 SET integer_column = 42 WHERE ID = 1000");
Copy

Durch Binden können Sie eine SQL-Anweisung ausführen, die einen Wert verwendet, der sich innerhalb einer Variablen befindet. Beispiel:

int my_integer_variable = 42;
PreparedStatement pstmt = connection.prepareStatement("UPDATE table1 SET integer_colum = ? WHERE ID = 1000");
pstmt.setInt(1, my_integer_variable);
pstmt.executeUpdate();
Copy

Das ? innerhalb der VALUES-Klausel gibt an, dass die SQL-Anweisung den Wert aus einer Variablen verwendet. Die Methode setInt() gibt an, dass das erste Fragezeichen in der SQL-Anweisung durch den Wert in der Variable mit dem Namen my_integer_variable ersetzt werden soll. Beachten Sie, dass setInt() 1-basierte und nicht 0-basierte Werte verwendet, d. h. das erste Fragezeichen von 1 und nicht von 0 referenziert wird.

Binden von Variablen an Zeitstempelspalten

Snowflake unterstützt drei verschiedene Varianten für Zeitstempel: TIMESTAMP_LTZ , TIMESTAMP_NTZ , TIMESTAMP_TZ. Wenn Sie PreparedStatement.setTimestamp aufrufen, um eine Variable an eine Zeitstempelspalte zu binden, wird der JDBC-Treiber den Zeitstempelwert in Bezug zur lokalen Zeitzone (TIMESTAMP_LTZ) interpretieren oder die Zeitzone des Calendar-Objekts wird als Argument übergeben:

// The following call interprets the timestamp in terms of the local time zone.
insertStmt.setTimestamp(1, myTimestamp);
// The following call interprets the timestamp in terms of the time zone of the Calendar object.
insertStmt.setTimestamp(1, myTimestamp, Calendar.getInstance(TimeZone.getTimeZone("America/New_York")));
Copy

Wenn Sie möchten, dass der Treiber den Zeitstempel anhand einer anderen Variante (z. B. TIMESTAMP_NTZ) interpretiert, verwenden Sie einen der folgenden Ansätze:

  • Setzen Sie den Sitzungsparameter CLIENT_TIMESTAMP_TYPE_MAPPING auf die Variante.

    Beachten Sie, dass der Parameter alle Bindungsoperationen für die aktuelle Sitzung beeinflusst. Wenn Sie die Variante ändern müssen (z. B. zurück zu TIMESTAMP_LTZ), müssen Sie diesen Sitzungsparameter erneut einstellen.

  • (In JDBC-Treiber 3.13.3 und späteren Versionen) Rufen Sie die Methode PreparedStatement.setObject auf, und geben Sie mit dem Parameter targetSqlType eine der folgenden Snowflake-Zeitstempelvarianten an:

    • SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_LTZ

    • SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_TZ

    • SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_NTZ

    Beispiel:

    import net.snowflake.client.jdbc.SnowflakeUtil;
    ...
    insertStmt.setObject(1, myTimestamp, SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_NTZ);
    
    Copy

Batcheinfügungen

In Ihrem Java-Anwendungscode können Sie mehrere Zeilen in einen einzelnen Batch einfügen, indem Sie Parameter in einer INSERT-Anweisung binden und dann addBatch() und executeBatch() aufrufen.

Der folgende Code fügt beispielsweise zwei Zeilen in eine Tabelle ein, die eine INTEGER-Spalte und eine VARCHAR-Spalte enthält. Im Beispiel werden Werte an die Parameter der INSERT-Anweisung gebunden und dann addBatch() und executeBatch() aufgerufen, um eine Batcheinfügung durchzuführen.

Connection connection = DriverManager.getConnection(url, prop);
connection.setAutoCommit(false);

PreparedStatement pstmt = connection.prepareStatement("INSERT INTO t(c1, c2) VALUES(?, ?)");
pstmt.setInt(1, 101);
pstmt.setString(2, "test1");
pstmt.addBatch();

pstmt.setInt(1, 102);
pstmt.setString(2, "test2");
pstmt.addBatch();

int[] count = pstmt.executeBatch(); // After execution, count[0]=1, count[1]=1
connection.commit();
Copy

Wenn Sie dieses Verfahren verwenden, um eine große Anzahl von Werten einzufügen, kann die Treiberleistung verbessert werden, indem die Daten (ohne Erstellen von Dateien auf dem lokalen Computer) an einen temporären Stagingbereich gestreamt werden. Der Treiber führt dies automatisch durch, wenn die Anzahl der Werte einen Schwellenwert überschreitet.

Außerdem müssen die aktuelle Datenbank und das aktuelle Schema für die Sitzung festgelegt sein. Wenn diese nicht festgelegt sind, kann der vom Treiber ausgeführte CREATE TEMPORARY STAGE-Befehl folgenden Fehler generieren:

CREATE TEMPORARY STAGE SYSTEM$BIND file_format=(type=csv field_optionally_enclosed_by='"')
Cannot perform CREATE STAGE. This session does not have a current schema. Call 'USE SCHEMA', or use a qualified name.
Copy

Bemerkung

Alternative Möglichkeiten zum Laden von Daten in die Snowflake-Datenbank (einschließlich Massenladen mit dem COPY-Befehl) finden Sie unter Daten in Snowflake laden.

Java-Beispielprogramm

Für ein in Java geschriebenes Beispiel klicken Sie mit der rechten Maustaste auf den Namen der Datei SnowflakeJDBCExample.java, und speichern Sie den Link bzw. die Datei in Ihrem lokalen Dateisystem.

Problembehandlung

E/A-Fehler: Verbindung zurückgesetzt

In einigen Fällen kann der JDBC-Treiber nach einer gewissen Zeit der Inaktivität möglicherweise mit der folgenden Fehlermeldung fehlschlagen:

I/O error: Connection reset
Copy

Sie können das Problem umgehen, indem Sie eine bestimmte Lebensdauer („time to live“) für die Verbindungen einstellen. Wenn eine Verbindung länger als die Lebensdauer inaktiv ist, entfernt der JDBC-Treiber die Verbindung aus dem Verbindungspool und erstellt eine neue Verbindung.

Um die Lebensdauer einzustellen, setzen Sie die Java-Systemeigenschaft net.snowflake.jdbc.ttl auf die Anzahl der Sekunden, die die Verbindung bestehen bleiben soll:

  • Um diese Eigenschaft programmseitig festzulegen, rufen Sie System.setProperty auf:

    // Set the "time to live" to 60 seconds.
    System.setProperty("net.snowflake.jdbc.ttl", "60")
    
    Copy
  • Um diese Eigenschaft beim Ausführen des Befehls java festzulegen, verwenden Sie das Flag -D:

    # Set the "time to live" to 60 seconds.
    java -cp .:snowflake-jdbc-<version>.jar -Dnet.snowflake.jdbc.ttl=60 <ClassName>
    
    Copy

Der Standardwert der Eigenschaft net.snowflake.jdbc.ttl ist -1, was bedeutet, dass inaktive Verbindungen nicht aus dem Verbindungspool entfernt werden.

Fehlerbehandlung

Bei der Behandlung von Fehlern und Ausnahmen für eine JDBC-Anwendung können Sie die Datei ErrorCode.java verwenden, die von Snowflake zur Verfügung gestellt wird, um die Ursache von Problemen zu ermitteln. Die für den JDBC-Treiber spezifischen Fehlercodes beginnen mit 2, in der Form: 2NNNNN.

Bemerkung

Der Link zu „ErrorCode.java“ im öffentlichen „snowflake-jdbc“-Git-Repository verweist auf die aktuelle Version der Datei, die sich von der Version des derzeit verwendeten JDBC-Treibers unterscheiden kann.