문 실행하기

문은 connection.execute() 메서드를 호출하여 실행할 수 있습니다. execute() 메서드에서는 SQL 텍스트 및 complete 콜백을 지정하기 위해 사용할 수 있는 options 오브젝트를 허용합니다. complete 콜백은 문의 실행이 종료되고 결과를 사용할 수 있을 때 호출됩니다.

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

참고

단일 요청의 최대 페이로드 크기는 16MB입니다.

문 매개 변수 바인딩하기

종종 문의 데이터와 자리 표시자를 바인딩 해야 하는 경우가 있습니다. 이러한 방식으로 문을 실행하는 것은 SQL 삽입 공격을 방지할 수 있으므로 유용합니다. 다음 문을 살펴보겠습니다.

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

다음 바인딩을 사용하여 동일한 결과를 얻을 수 있습니다.

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

바인딩을 위한 ? 구문도 지원됩니다.

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

참고

바인딩할 수 있거나 일괄 결합할 수 있는 데이터 크기의 상한에는 제한이 있습니다. 자세한 내용은 쿼리 텍스트 크기 제한 섹션을 참조하십시오.

SQL 문 일괄 실행하기(다중 문 지원)

Node.js의 버전 1.6.18 이상에서는 세미콜론으로 구분된 SQL 문 배치를 전송하여 단일 요청에서 실행되도록 할 수 있습니다.

참고

기본적으로 Snowflake는 다중 문으로 실행된 쿼리에 대한 오류를 반환하여 SQL 삽입 공격으로부터 보호합니다. 다중 문 기능을 사용하면 시스템이 SQL 삽입에 더 취약해지므로 신중하게 사용해야 합니다. MULTI_STATEMENT_COUNT 매개 변수를 사용해 실행할 문의 개수를 지정하여 위험을 줄일 수 있으며, 문을 매개 변수에 추가하여 삽입하는 것이 더욱 어려워집니다.

쿼리 문자열에 세미콜론으로 구분된 여러 문이 포함되어 있다는 점을 제외하면 단일 문으로 쿼리를 실행하는 것과 동일한 방식으로 여러 문을 일괄 처리로 실행할 수 있습니다. 여러 문은 병렬이 아니라 순차적으로 실행됩니다. MULTI_STATEMENT_COUNT 매개 변수는 배치에 포함된 문의 정확한 개수를 지정합니다.

예를 들어 MULTI_STATEMENT_COUNT=3 을 설정하면 배치 문에 정확히 세 개의 문이 포함되어야 합니다. 다른 개수의 문과 함께 배치 문을 제출하면 Node.js 드라이버가 요청을 거부합니다. MULTI_STATEMENT_COUNT=0 을 설정하여 배치 쿼리에 개수에 관계없이 문을 포함할 수 있습니다. 하지만 이 값을 사용하면 SQL 삽입 공격에 대한 보호가 감소한다는 점에 유의하십시오.

다음 명령을 사용하여 세션 수준에서 이 매개 변수를 설정하거나 쿼리를 제출할 때마다 별도로 값을 설정할 수 있습니다.

ALTER SESSION SET multi_statement_count = <n>
Copy

세션 수준 값을 설정하면 배치 문을 실행할 때마다 실행할 때 값을 설정할 필요가 없습니다. 다음 예에서는 세션 수준에서 문 개수를 3개로 설정한 다음 SQL 문 세 개를 실행합니다.

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

MULTI_STATEMENT_COUNTconnection.execute 함수의 매개 변수로 설정하여 다중 문 쿼리를 실행할 때마다 배치의 문 개수를 설정할 수도 있습니다. 다음 예에서는 배치에 대해 문 개수를 3개로 설정하고 배치 쿼리에 3개의 SQL 문을 포함합니다.

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

대량 삽입을 위한 배열 바인딩하기

일괄 INSERT 연산을 위한 데이터 배열 바인딩이 지원됩니다. 배열의 배열을 다음과 같이 전달합니다.

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

참고

대규모 배열을 바인딩하면 성능에 영향을 주며 데이터의 크기가 너무 커서 서버에서 처리할 수 없는 경우에는 거부될 수 있습니다.

문 취소하기

문은 statement.cancel() 메서드를 호출하여 취소할 수 있습니다.

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

요청 다시 제출하기

어쩌면 네트워크 오류 또는 시간 초과로 인해 Snowflake가 SQL 문을 성공적으로 실행했는지 확실하지 않은 경우 요청 ID를 사용하여 같은 문을 다시 제출할 수 있습니다. 예를 들어, 데이터를 추가하려고 INSERT 명령을 제출했지만 적시에 확인을 받지 못했는데, 명령에 어떤 문제가 있는지는 모른다고 가정해 보십시오. 이런 상황에서는 똑같은 명령을 새 명령으로 실행하면 명령을 두 번 실행하여 데이터 중복을 일으킬 수 있으므로 그렇게 하고 싶지는 않을 것입니다.

SQL 문에 요청 ID를 포함하면 데이터 중복 가능성을 피할 수 있습니다. 초기 요청에서 요청 ID로 요청을 다시 제출하면 초기 요청이 실패하는 경우에만 다시 제출된 명령이 실행됩니다. 자세한 내용은 SQL 문 실행 요청 다시 제출하기 섹션을 참조하십시오.

참고

요청 ID를 사용하여 쿼리를 다시 제출하려면 요청 ID를 생성한 것과 동일한 연결을 사용해야 합니다. 다른 연결에서 쿼리 결과를 검색하려면 RESULT_SCAN 섹션을 참조하십시오.

다음 코드 샘플에서는 요청 ID를 저장하고 사용하여 문을 다시 제출하는 방법을 보여줍니다. 문을 실행할 때 getRequestId() 함수를 사용하여 제출된 요청의 ID를 검색할 수 있습니다. 그런 다음 해당 ID를 사용하여 나중에 같은 문을 실행할 수 있습니다. 다음 예제에서는 INSERT 문을 실행하고 requestId 변수에 요청 ID를 저장합니다.

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

명령이 성공적으로 실행되었다는 확인을 받지 못한 경우 아래 그림과 같이 저장된 요청 ID를 사용하여 요청을 다시 제출할 수 있습니다.

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

requestIdsqlText 를 사용하여 요청을 다시 제출하기로 할 때 다음 상호 작용에 유의하십시오.

  • requestId 가 이미 존재하는 경우, 즉 다시 제출하는 요청이 이전 요청과 일치하는 경우, 이 명령은 sqlText 쿼리를 무시하고 원래 명령에서 쿼리를 다시 제출합니다.

  • requestId 가 존재하지 않는 경우, 즉 이전 요청과 일치하지 않는 경우, 이 명령은 sqlText 쿼리를 실행합니다.