ODBC 드라이버 API 지원¶
Snowflake ODBC 드라이버는 ODBC API 3.52 버전을 지원합니다. 이 항목에서는 Snowflake와 관련된 ODBC 루틴을 나열하고 지원 여부를 제공합니다. 이러한 루틴은 수행하는 함수를 기준으로 카테고리로 구분됩니다.
전체 API 참고 자료는 Microsoft ODBC 프로그래머 참고 자료 를 참조하십시오.
이 항목의 내용:
데이터 원본에 연결하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
드라이버 및 데이터 원본에 대한 정보 획득하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
드라이버 속성 설정 및 검색하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
SQL_ATTR_METADATA_ID를 설정하면 SQLTables 및 SQLColumns 함수에만 영향을 줍니다(다른 지원되는 카탈로그 함수 에는 영향을 주지 않음). |
|
✔ |
읽기 전용 모드는 지원되지 않습니다. SQL_MODE_READ_ONLY는 드라이버로 전달되지만, Snowflake는 계속해서 데이터베이스에 작성합니다. . . 또한, SQL_ATTR_ASYNC_DBC_EVENT, SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE, SQL_ATTR_ASYNC_DBC_PCALLBACK, SQL_ATTR_ASYNC_DBC_PCONTEXT, SQL_ATTR_DBC_INFO_TOKEN의 속성이 API 버전 3.52 이후에 도입되었습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
|
|
✔ |
SQL_ATTR_CONNECTION_POOLING 속성은 ODBC API 버전 3.52 이후에 도입되었으며 지원되지 않습니다. |
|
✔ |
SQL_ATTR_CURSOR_SCROLLABLE은 SQL_NONSCROLLABLE 값만 지원합니다. . SQL_ATTR_USE_BOOKMARKS는 SQL_UB_OFF 값만 지원합니다. . . 서드 파티 도구와의 호환성을 위해 SQL_ATTR_ENABLE_AUTO_IPD는 기본적으로 true로 설정되며, 이는 ODBC 표준에서 기본값을 false로 설정할 것을 권장하는 경우에도 마찬가지입니다. 기본값을 false로 변경하려면, EnableAutoIpdByDefault 매개 변수를 |
|
✔ |
Snowflake 구현에서는 표준 속성뿐만 아니라 SQL_SF_STMT_ATTR_LAST_QUERY_ID 속성도 지원하며, 이를 통해 사용자는 지정된 문 핸들과 연결된 가장 최든 쿼리 ID를 검색할 수 있습니다. 부분적인 예는 아래 예 섹션에서 확인할 수 있습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
각 이전 함수에는 와이드 문자(유니코드)를 허용하는 해당 함수가 있습니다. 그러한 각 유니코드 함수의 이름은 위와 같으며, 뒤에 “W”가 추가됩니다. 예를 들어, 1개의 char 배열을 3번째 매개 변수로 허용하는 SQLGetStmtAttr
함수의 해당 함수 이름은 SQLGetStmtAttrW
이며, 이 함수는 1개의 wchar 배열을 3번째 매개 변수로 허용합니다.
Snowflake 고유 동작¶
SQLSetConnectAttr
이 메서드에서 지원하는 Snowflake 고유 속성 2개는 다음과 같습니다.
속성 이름
설명
SQL_SF_CONN_ATTR_APPLICATION
레지스트리 또는 .ini 파일의 APPLICATION 설정에 의해 지정된 값을 재정의합니다.
SQL_SF_CONN_ATTR_PRIV_KEY
개인 키의 인메모리 복사본을 가리키는 EVP_PKEY* 포인터로, 레지스트리 또는 .ini 파일의 PRIV_KEY_FILE 및 PRIV_KEY_PWD 설정을 재정의합니다. Snowflake는 이 속성을 사용하여 개인 키를 설정하는 것을 권장합니다.
설명자 필드 설정 및 검색하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
SQL 요청 준비하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API에서는 더 이상 사용되지 않습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 2.x에서는 더 이상 사용되지 않습니다. |
참고
바인딩할 수 있는 데이터 크기의 상한에는 제한이 있습니다. 자세한 내용은 쿼리 텍스트 크기 제한 섹션을 참조하십시오.
준비를 위해 지원되는 SQL 문 은 준비에서 사용할 수 있도록 지원되는 SQL 문의 타입을 나열합니다.
요청 제출하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
매개 변수에 바인딩된 데이터 타입에 관계없이, Snowflake는 서버측 변환을 실행하고 VARCHAR(최대 길이 16777216자)를 반환합니다. |
|
✔ |
|
|
✔ |
이 함수에 대한 지원은 ODBC 드라이버 2.23.3 버전에 추가되었습니다. |
|
✔ |
이 함수에 대한 지원은 ODBC 드라이버 2.23.3 버전에 추가되었습니다. |
결과 및 결과에 대한 정보 검색하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
ODBC 드라이버는 현재 |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
GEOGRAPHY 열의 경우 |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 2.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
|
|
✔ |
|
|
API 버전 3.x 드라이버에서 |
|
|
Snowflake는 이 기능을 지원하지 않습니다. |
|
|
Snowflake는 이 기능을 지원하지 않습니다. |
데이터 원본의 시스템 테이블에 대한 정보 획득하기(카탈로그 함수)¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
설정된 빈 결과를 반환합니다. |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
결과 세트에서 |
|
설정된 빈 결과를 반환합니다. |
|
|
설정된 빈 결과를 반환합니다. |
|
|
설정된 빈 결과를 반환합니다. |
|
|
✔ |
함수에 전달된 매개 변수가 “TABLE”인 경우, 함수는 일시적 테이블 및 임시 테이블 등 모든 테이블 타입을 반환합니다. . . 함수로 전달된 매개 변수가 “VIEW”인 경우 함수는 구체화된 뷰 등 모든 타입의 뷰를 반환합니다. . . 함수로 전달된 매개 변수가 “TABLE, VIEW” 또는 “%”인 경우 함수는 모든 타입의 테이블 및 모든 타입의 뷰에 대한 정보를 반환합니다. |
카탈로그 함수로 전달된 이름에 유효하지 않은 문자가 포함되거나 이름이 데이터베이스 오브젝트와 일치하지 않는 경우 함수는 빈 결과 세트를 반환합니다.
SQL_ATTR_METADATA_ID
를 설정하면 SQLTables
, SQLColumns
및 SQLProcedures
함수에만 영향을 줍니다.
문 종료하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
연결 종료하기¶
함수 이름 |
지원됨 |
참고 |
---|---|---|
|
3.52 버전 이후의 API에 도입되었습니다. |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
|
✔ |
Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. |
사용자 지정 SQL 데이터 타입¶
Snowflake에서 지원되는 일부 SQL 데이터 타입은 ODBC와 직접 매핑되지 않습니다(예: TIMESTAMP_*tz, VARIANT). 지원되지 않는 데이터 타입 관련 작업을 ODBC 드라이버에서 수행하려면 드라이버와 함께 제공되는 헤더 파일에 다음 사용자 지정 데이터 타입에 대한 정의가 포함되어야 합니다.
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Custom SQL Data Type Definition
///
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#define SQL_SF_TIMESTAMP_LTZ 2000
#define SQL_SF_TIMESTAMP_TZ 2001
#define SQL_SF_TIMESTAMP_NTZ 2002
#define SQL_SF_ARRAY 2003
#define SQL_SF_OBJECT 2004
#define SQL_SF_VARIANT 2005
다음 코드는 사용자 지정 데이터 타입의 샘플 사용법을 보여줍니다.
// bind insert as timestamp_ntz
SQLRETURN rc;
rc = SQLPrepare(odbc.StmtHandle,
(SQLCHAR *) "insert into testtimestampntz values (?)",
SQL_NTS);
SQL_TIMESTAMP_STRUCT bindData;
SQLLEN datalen = sizeof(SQL_TIMESTAMP_STRUCT);
bindData.year = 2017;
bindData.month = 11;
bindData.day = 30;
bindData.hour = 18;
bindData.minute = 17;
bindData.second = 5;
bindData.fraction = 123456789;
rc = SQLBindParameter(
odbc.StmtHandle, 1, SQL_PARAM_INPUT,
SQL_C_TIMESTAMP, SQL_SF_TIMESTAMP_NTZ,
100, 0, &bindData, sizeof(bindData), &datalen);
rc = SQLExecute(odbc.StmtHandle);
// query table
rc = SQLExecDirect(odbc.StmtHandle, (SQLCHAR *)"select * from testtimestampntz", SQL_NTS);
rc = SQLFetch(odbc.StmtHandle);
// fetch data as timestamp
SQL_TIMESTAMP_STRUCT ret;
SQLLEN retLen = (SQLLEN) 0;
rc = SQLGetData(odbc.StmtHandle, 1, SQL_C_TIMESTAMP, &ret, (SQLLEN)sizeof(ret), &retLen);
예¶
이 섹션은 API 사용 예를 제공합니다.
마지막 쿼리 ID 검색하기¶
마지막 쿼리 ID 검색은 ODBC 표준에 대한 Snowflake 확장입니다.
마지막 쿼리 ID를 검색하려면, SQLGetStmtAttr
(또는 SQLGetStmtAttrW
) 함수를 호출하여 SQL_SF_STMT_ATTR_LAST_QUERY_ID 속성 및 쿼리 ID를 포함하기에 충분히 큰 문자 배열을 전달합니다.
아래 예는 쿼리의 쿼리 ID를 검색하는 방법을 보여 줍니다.
// Space to store the query ID.
// The SQLGetStmtAttr() function fills this in with the actual ID.
char queryId[37]; // Maximum 36 chars plus string terminator.
// The length (in characters) of the query ID. The SQLGetStmtAttr() function fills this in
// with the actual length of the query ID (usually 36).
SQLINTEGER idLen;
// Execute a query.
rc = SQLExecDirect(odbc.StmtHandle, (SQLCHAR *) "select 1", SQL_NTS);
// Retrieve the query ID (queryId) and the length of that query ID (idLen).
SQLGetStmtAttr(odbc.StmtHandle, SQL_SF_STMT_ATTR_LAST_QUERY_ID, queryId, sizeof(queryId), &idLen);
Linux 또는 macOS에서 실행하는 경우에는 SQLGetStmtAttrW
을 호출하고 적절한 데이터 타입(예: “char”이 아닌 “wchar”)의 매개 변수를 전달합니다.
데이터 검색 시의 성능 향상을 위한 모범 사례¶
SQLFetch
로 데이터를 검색할 때 SQLGetData
또는 SQLBindCol
함수를 사용하여 셀 내용에 액세스할 수 있습니다. 대부분의 경우 SQLBindCol
을 사용하면 데이터 검색을 위해 필요한 ODBC 호출 횟수가 감소하고 메모리 내 데이터 복사를 이용할 수 있으므로 성능이 향상됩니다.
SQLGetData
를 사용하여 셀 데이터 검색하기¶
다음 예제에서는 SQLGetData
함수를 사용하여 SQLFetch
에서 반환된 데이터 버퍼에서 셀 값을 검색합니다. 행의 각 셀에 대해 SQLGetData
를 한 번 호출해야 합니다.
SQLRETURN rc;
SQLSMALLINT numCols;
const size_t s_MaxDataLen = 300;
// fetch with SQLGetData()
// query table
rc = SQLExecDirect(stmt, (SQLCHAR *)"select * from table", SQL_NTS);
// Find out the number of result set columns.
rc = SQLNumResultCols(stmt, &numCols);
// buffer for one cell
vector<char> dataBuffer(s_MaxDataLen);
SQLLEN dataLen = (SQLLEN)0;
// call SQLFetch() per row and SQLGetData() per column per row
while (true)
{
rc = SQLFetch(stmt);
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
break;
}
for (SQLUSMALLINT i = 0; i < numCols; i++)
{
rc = SQLGetData(stmt, i + 1, SQL_C_CHAR, dataBuffer.data(), (SQLLEN)s_MaxDataLen, &dataLen);
std::string data;
if (SQL_NULL_DATA == dataLen)
continue;
if (SQL_NO_TOTAL == dataLen)
dataLen = s_MaxDataLen;
data = std::string(dataBuffer.data(), dataLen);
}
}
rc = SQLCloseCursor(stmt);
SQLBindCol
을 사용하여 한 행의 데이터에 대한 열 바인딩하기¶
다음 예제에서는 SQLBindCol
함수를 사용하여 SQLFetch
에서 반환된 데이터 버퍼에서 셀 값을 검색합니다. 행의 열 개수에 대한 메모리 내 버퍼를 만든 다음, 단일 SQLBindCol
호출을 수행하여 애플리케이션 버퍼를 결과 세트에 바인딩합니다. 마지막으로, SQLFetch
를 행당 한 번 호출하고 셀 값을 버퍼에 로딩합니다. 이 접근 방식으로 데이터 검색 속도와 효율성을 크게 높일 수 있습니다.
SQLRETURN rc;
SQLSMALLINT numCols;
const size_t s_MaxDataLen = 300;
// fetch with SQLBindCol()
// query table
rc = SQLExecDirect(stmt, (SQLCHAR *)"select * from table", SQL_NTS);
// Find out the number of result set columns.
rc = SQLNumResultCols(stmt, &numCols);
// buffer for one row
vector<char> rowBuffer(s_MaxDataLen * numCols);
vector<SQLLEN> columnLenBuffer(numCols);
// call SQLBindCol() per column
for (SQLSMALLINT i = 0; i < numCols; ++i)
{
SQLBindCol(stmt, i + 1, SQL_C_CHAR, &rowBuffer[s_MaxDataLen * i],
s_MaxDataLen, &columnLenBuffer[i]);
}
// call SQLFetch() per row
while (true)
{
rc = SQLFetch(stmt);
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
break;
}
// go through data for each cell in buffer without ODBC calls
for (SQLUSMALLINT i = 0; i < numCols; i++)
{
std::string data;
SQLLEN len = columnLenBuffer[i];
if (SQL_NULL_DATA == len)
continue;
if (SQL_NO_TOTAL == len)
len = s_MaxDataLen;
data = std::string(&rowBuffer[s_MaxDataLen * i], len);
}
}
rc = SQLCloseCursor(stmt);
SQLBindCol
을 사용하여 여러 행의 데이터에 대한 열 바인딩하기¶
단일 SQLFetch
호출에서 여러 행을 가져옴으로써 성능을 훨씬 더 향상하여 쿼리 테이블의 모든 행을 처리하는 데 필요한 ODBC SQLFetch
호출의 횟수를 줄일 수 있습니다.
다음 예제에서는
결과 세트의 열 개수를 결정합니다.
여러 열의 데이터를 저장할 메모리 내 배열을 만듭니다.
각 열에 대해
SQLBindCol
을 호출하여 애플리케이션 버퍼를 결과 세트에 바인딩합니다.SQLFetch
를 호출하여 지정된 행 수(100개)를 가져오고 쿼리 테이블의 끝에 도달할 때까지 ODBC 호출을 하지 않고 메모리 내 버퍼의 데이터를 처리합니다.
이 접근 방식으로 데이터 검색 속도와 효율성을 크게 높일 수 있습니다. 20개의 열과 1,000개의 행이 있는 쿼리 테이블의 경우, 이 예제에서는 20,000개의 SQLGetData
호출 대신 20개의 SQLBindCol
과 10개의 SQLFetch
호출만 수행하여 모든 테이블 데이터를 로딩합니다.
SQLRETURN rc;
SQLSMALLINT numCols;
const size_t s_MaxDataLen = 300;
// fetch with SQLBindCol() and SQL_ATTR_ROW_ARRAY_SIZE > 1
const size_t s_numRowsPerSQLFetch = 100;
SQLULEN numRowsFetched = 0;
rc = SQLSetStmtAttr(stmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)s_numRowsPerSQLFetch, 0);
rc = SQLSetStmtAttr(stmt, SQL_ATTR_ROWS_FETCHED_PTR, (SQLPOINTER)&numRowsFetched, sizeof(SQLULEN));
// query table
rc = SQLExecDirect(stmt, (SQLCHAR *)"select * from table", SQL_NTS);
// Find out the number of result set columns.
rc = SQLNumResultCols(stmt, &numCols);
// buffer for all columns; each column has buffer size of s_numRowsPerSQLFetch
// To retrieve multiple rows per SQLFetch() call, use the default behavior of SQL_BIND_BY_COLUMN
vector<vector<char> > colArray(numCols);
vector<vector<SQLLEN> > colLenArray(numCols);
// call SQLBindCol() per column
for (SQLSMALLINT i = 0; i < numCols; ++i)
{
// initialize buffer for each column
colArray[i].resize(s_MaxDataLen * s_numRowsPerSQLFetch);
colLenArray[i].resize(s_numRowsPerSQLFetch);
SQLBindCol(stmt, i + 1, SQL_C_CHAR, colArray[i].data(),
s_MaxDataLen, colLenArray[i].data());
}
// call SQLFetch() per s_numRowsPerSQLFetch rows
while (true)
{
rc = SQLFetch(stmt);
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
break;
}
// go through data for each cell in buffer without ODBC calls
for (SQLULEN rowIndex = 0; rowIndex < numRowsFetched; rowIndex++)
{
for (SQLUSMALLINT colIndex = 0; colIndex < colIndex; colIndex++)
{
std::string data;
SQLLEN len = colLenArray[colIndex][rowIndex];
if (SQL_NULL_DATA == len)
continue;
if (SQL_NO_TOTAL == len)
len = s_MaxDataLen;
data = std::string(&(colArray[colIndex][s_MaxDataLen * rowIndex]), len);
}
}
}
rc = SQLCloseCursor(stmt);