Ausführen von Anweisungen

Anweisungen können durch Aufruf der Methode connection.execute() ausgeführt werden. Die execute()-Methode akzeptiert ein options-Objekt, mit dem der SQL-Text und ein complete-Callback angegeben werden können. Der complete-Callback wird aufgerufen, wenn eine Anweisung die Ausführung beendet hat und das Ergebnis zur Weiterverarbeitung bereit steht:

var statement = connection.execute({
  sqlText: 'CREATE DATABASE testdb',
  complete: function(err, stmt, rows) {
    if (err) {
      console.error('Failed to execute statement due to the following error: ' + err.message);
    } else {
      console.log('Successfully executed statement: ' + stmt.getSqlText());
    }
  }
});
Copy

Bemerkung

Die maximale Größe der Nutzlast einer einzelnen Anfrage beträgt 16 MB.

Binden von Anweisungsparametern

Gelegentlich kann es sinnvoll sein, Daten in einer Anweisung mit einem Platzhalter zu binden. Das Ausführen von Anweisungen auf diese Weise ist nützlich, um Angriffe durch Einschleusung von SQL-Befehlen zu verhindern. Verwenden Sie ggf. die folgende Anweisung:

connection.execute({
  sqlText: 'SELECT c1 FROM (SELECT 1 AS c1 UNION ALL SELECT 2 AS c1) WHERE c1 = 1;'
});
Copy

Das gleiche Ergebnis erzielen Sie mit den folgenden Bindungen:

connection.execute({
  sqlText: 'SELECT c1 FROM (SELECT :1 AS c1 UNION ALL SELECT :2 AS c1) WHERE c1 = :1;',
  binds: [1, 2]
});
Copy

Die ?-Syntax für Bindungen wird ebenfalls unterstützt:

connection.execute({
p
  sqlText: 'SELECT c1 FROM (SELECT ? AS c1 UNION ALL SELECT ? AS c1) WHERE c1 = ?;',
  binds: [1, 2, 1]
});
Copy

Bemerkung

Es gibt eine Obergrenze für die Datengröße, die Sie binden oder in einem Batch kombinieren können. Weitere Details dazu finden Sie unter Begrenzung der Abfragetextgröße.

Ausführen eines Batches mit SQL-Anweisungen (Unterstützung von mehreren Anweisungen)

Ab Version 1.6.18 des Node.js-Konnektors können Sie einen Batch mit SQL-Anweisungen (durch Semikolons getrennt) senden, der mit einer einzigen Anforderung ausgeführt wird.

Bemerkung

Standardmäßig gibt Snowflake bei Abfragen mit mehreren Anweisungen einen Fehler zurück, um Angriffe durch Einschleusen von SQL-Befehlen zu verhindern. Das Feature für mehrere Anweisungen macht Ihr System anfälliger für das Einschleusen von SQL-Befehlen und sollte mit größter Vorsicht verwendet werden. Sie können das Risiko verringern, indem Sie mit dem Parameter MULTI_STATEMENT_COUNT die Anzahl der auszuführenden Anweisungen angeben. Dies erschwert das Einschleusen einer Anweisung durch Anhängen.

Sie können mehrere Anweisungen als Batch auf die gleiche Weise ausführen wie Abfragen mit einzelnen Anweisungen, mit dem Unterschied, dass die Abfragezeichenfolge mehrere durch Semikolon getrennte Anweisungen enthält. Beachten Sie, dass mehrere Anweisungen sequenziell und nicht parallel ausgeführt werden. Der Parameter MULTI_STATEMENT_COUNT gibt die genaue Anzahl der Anweisungen an, die der Batch enthält.

Wenn Sie zum Beispiel MULTI_STATEMENT_COUNT=3 einstellen, muss eine Batch-Anweisung genau drei Anweisungen umfassen. Wenn Sie eine Batch-Anweisung mit einer anderen Anzahl von Anweisungen übermitteln, lehnt der Node.js-Treiber die Anfrage ab. Sie können MULTI_STATEMENT_COUNT=0 einstellen, damit Batch-Abfragen eine beliebige Anzahl von Anweisungen enthalten können. Beachten Sie jedoch, dass die Verwendung dieses Wertes den Schutz vor Angriffen durch Einschleusung von SQL-Befehlen verringert.

Sie können diesen Parameter auf Sitzungsebene mit dem folgenden Befehl einstellen oder den Wert bei jeder Abfrage separat festlegen.

ALTER SESSION SET multi_statement_count = <n>
Copy

Wenn Sie den Wert auf Sitzungsebene einstellen, müssen Sie ihn nicht bei jeder Ausführung einer Batch-Anweisung neu einstellen. Im folgenden Beispiel wird die Anzahl auf Sitzungsebene auf drei Anweisungen festgelegt, und danach werden drei SQL-Anweisungen ausgeführt:

var statement = connection.execute({
    sqlText: "ALTER SESSION SET multi_statement_count=0",
    complete: function (err, stmt, rows) {
      if (err) {
        console.error('1 Failed to execute statement due to the following error: ' + err.message);
      } else {
        testMulti();
      }
    }
  });
function testMulti() {
  console.log('select bind execute.');
  var selectStatement = connection.execute({
    sqlText: "create or replace table test(n int); insert into test values(1), (2); select * from test order by n",
    complete: function (err, stmt, rows) {
      if (err) {
        console.error('1 Failed to execute statement due to the following error: ' + err.message);
      }
      else {
        console.log('==== complete');
        console.log('==== sqlText=' + stmt.getSqlText());
        if(stmt.hasNext())
        {
          stmt.NextResult();
        }
        else {
          // do something else, e.g. close the connection
        }
      }
    }
  });
}
Copy

Sie können auch jedes Mal, wenn Sie eine Abfrage mit mehreren Anweisungen ausführen, die Anzahl der Anweisungen im Batch festlegen, indem Sie MULTI_STATEMENT_COUNT als Parameter für die Funktion connection.execute festlegen. Im folgenden Beispiel wird die Anzahl der Anweisungen im Batch auf drei festgelegt, und es werden drei SQL-Anweisungen in die Batch-Abfrage aufgenommen:

var selectStatement = connection.execute({
    sqlText: "CREATE OR REPLACE TABLE test(n int); INSERT INTO test values(1), (2); SELECT * FROM test ORDER BY n",
    parameters: { MULTI_STATEMENT_COUNT: 3 },
    complete: function (err, stmt, rows) {
      if (err) {
        console.error('1 Failed to execute statement due to the following error: ' + err.message);
      }
      else {
        console.log('==== complete');
        console.log('==== sqlText=' + stmt.getSqlText());
        if(stmt.hasNext())
        {
          stmt.NextResult();
        }
        else {
          // do something else, e.g. close the connection
        }
      }
    }
  });
Copy

Binden eines Arrays für Masseneinfügen

Das Binden eines Arrays von Daten wird für INSERT-Massenoperationen unterstützt. Übergeben Sie ein Array von Arrays wie folgt:

connection.execute({
  sqlText: 'INSERT INTO t(c1, c2, c3) values(?, ?, ?)',
  binds: [[1, 'string1', 2.0], [2, 'string2', 4.0], [3, 'string3', 6.0]]
});
Copy

Bemerkung

Das Binden eines großen Arrays wirkt sich auf die Leistung aus und kann abgelehnt werden, wenn die Datenmenge zu groß ist, um vom Server verarbeitet zu werden.

Abbrechen von Anweisungen

Eine Anweisung kann durch Aufruf der Methode statement.cancel() abgebrochen werden:

statement.cancel(function(err, stmt) {
  if (err) {
    console.error('Unable to abort statement due to the following error: ' + err.message);
  } else {
    console.log('Successfully aborted statement');
  }
});
Copy

Erneutes Übermitteln von Anforderungen

Wenn Sie sich nicht sicher sind, ob Snowflake eine SQL-Anweisung erfolgreich ausgeführt hat, z. B. aufgrund eines Netzwerkfehlers oder eines Timeouts, können Sie dieselbe Anweisung unter Verwendung der Anforderungs-ID erneut übermitteln. Angenommen, Sie senden einen INSERT-Befehl zum Hinzufügen von Daten, erhalten aber nicht rechtzeitig eine Bestätigung, sodass Sie nicht wissen, was mit dem Befehl passiert ist. In diesem Szenario möchten Sie nicht einfach denselben Befehl als neuen Befehl ausführen, da dies dazu führen könnte, dass der Befehl zweimal ausgeführt wird, was zu einer Verdoppelung der Daten führt.

Indem Sie die Anforderungs-ID in die SQL-Anweisung einbeziehen, können Sie eine mögliche Duplizierung der Daten vermeiden. Das erneute Übermitteln der Anforderung unter Verwendung der Anforderung-ID der ursprünglichen Anforderung stellt sicher, dass der erneut übermittelte Befehl nur ausgeführt wird, wenn die ursprüngliche Anforderung fehlgeschlagen ist. Weitere Informationen dazu finden Sie unter Erneutes Übermitteln von Anforderungen zum Ausführen von SQL-Anweisungen.

Bemerkung

Um eine Abfrage unter Verwendung einer Anfrage-ID erneut zu übermitteln, müssen Sie dieselbe Verbindung verwenden, die die Anfrage-ID generiert hat. Wenn Sie das Ergebnis einer Abfrage von einer anderen Verbindung abrufen möchten, finden Sie entsprechende Informationen unter RESULT_SCAN.

Die folgenden Codebeispiele zeigen, wie Sie eine Anforderungs-ID speichern und verwenden können, um eine Anweisung erneut zu übermitteln. Wenn Sie eine Anweisung ausführen, können Sie mit der Funktion getRequestId() die ID der übermittelten Anforderung abrufen. Sie können diese ID dann verwenden, um die gleiche Anweisung zu einem späteren Zeitpunkt auszuführen. Im folgenden Beispiel wird eine INSERT-Anweisung ausgeführt und deren Anforderungs-ID in der Variablen requestId gespeichert.

var requestId;
connection.execute({
  sqlText: 'INSERT INTO testTable VALUES (1);',
    complete: function (err, stmt, rows)
    {
      var stream = stmt.streamRows();
      requestId = stmt.getRequestId();   // Retrieves the request ID
      stream.on('data', function (row)
      {
        console.log(row);
      });
      stream.on('end', function (row)
      {
        console.log('done');
      });
    }
});
Copy

Wenn Sie keine Bestätigung erhalten, dass der Befehl erfolgreich ausgeführt wurde, können Sie die Anforderung unter Verwendung der gespeicherten Anfrage-ID wie unten gezeigt erneut übermitteln.

connection.execute({
  sqlText: 'INSERT INTO testTable VALUES (1);',  // optional
    requestId: requestId,  // Uses the request ID from before
    complete: function (err, stmt, rows)
    {
      var stream = stmt.streamRows();
      stream.on('data', function (row)
      {
        console.log(row);
      });
      stream.on('end', function (row)
      {
        console.log('done');
      });
  }
});
Copy

Wenn Sie sich entscheiden, eine Anforderung erneut mit requestId und sqlText zu übermitteln, müssen Sie folgende Wechselwirkungen beachten:

  • Wenn die Anforderungs-ID requestId bereits vorhanden ist, d. h. mit einer früheren Anforderung übereinstimmt, ignoriert der Befehl die sqlText-Abfrage und übermittelt erneut die Abfrage aus dem ursprünglichen Befehl.

  • Wenn die Anforderungs-ID requestId nicht vorhanden ist, d. h. mit keiner früheren Anforderung übereinstimmt, führt der Befehl die sqlText-Abfrage aus.