문 실행하기¶
문은 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()); } } });
참고
단일 요청의 최대 페이로드 크기는 16MB입니다.
문 매개 변수 바인딩하기¶
종종 문의 데이터와 자리 표시자를 바인딩 해야 하는 경우가 있습니다. 이러한 방식으로 문을 실행하는 것은 SQL 삽입 공격을 방지할 수 있으므로 유용합니다. 다음 문을 살펴보겠습니다.
connection.execute({ sqlText: 'SELECT c1 FROM (SELECT 1 AS c1 UNION ALL SELECT 2 AS c1) WHERE c1 = 1;' });
다음 바인딩을 사용하여 동일한 결과를 얻을 수 있습니다.
connection.execute({ sqlText: 'SELECT c1 FROM (SELECT :1 AS c1 UNION ALL SELECT :2 AS c1) WHERE c1 = :1;', binds: [1, 2] });
바인딩을 위한 ?
구문도 지원됩니다.
connection.execute({ p sqlText: 'SELECT c1 FROM (SELECT ? AS c1 UNION ALL SELECT ? AS c1) WHERE c1 = ?;', binds: [1, 2, 1] });
참고
바인딩할 수 있거나 일괄 결합할 수 있는 데이터 크기의 상한에는 제한이 있습니다. 자세한 내용은 쿼리 텍스트 크기 제한 섹션을 참조하십시오.
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>
세션 수준 값을 설정하면 배치 문을 실행할 때마다 실행할 때 값을 설정할 필요가 없습니다. 다음 예에서는 세션 수준에서 문 개수를 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 } } } }); }
MULTI_STATEMENT_COUNT
를 connection.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 } } } });
대량 삽입을 위한 배열 바인딩하기¶
일괄 INSERT 연산을 위한 데이터 배열 바인딩이 지원됩니다. 배열의 배열을 다음과 같이 전달합니다.
connection.execute({ sqlText: 'INSERT INTO t(c1, c2, c3) values(?, ?, ?)', binds: [[1, 'string1', 2.0], [2, 'string2', 4.0], [3, 'string3', 6.0]] });
참고
대규모 배열을 바인딩하면 성능에 영향을 주며 데이터의 크기가 너무 커서 서버에서 처리할 수 없는 경우에는 거부될 수 있습니다.
문 취소하기¶
문은 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'); } });
요청 다시 제출하기¶
어쩌면 네트워크 오류 또는 시간 초과로 인해 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'); }); } });
명령이 성공적으로 실행되었다는 확인을 받지 못한 경우 아래 그림과 같이 저장된 요청 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'); }); } });
requestId
와 sqlText
를 사용하여 요청을 다시 제출하기로 할 때 다음 상호 작용에 유의하십시오.
requestId
가 이미 존재하는 경우, 즉 다시 제출하는 요청이 이전 요청과 일치하는 경우, 이 명령은sqlText
쿼리를 무시하고 원래 명령에서 쿼리를 다시 제출합니다.requestId
가 존재하지 않는 경우, 즉 이전 요청과 일치하지 않는 경우, 이 명령은sqlText
쿼리를 실행합니다.