ODBC 드라이버 API 지원

Snowflake ODBC 드라이버는 ODBC API 3.52 버전을 지원합니다. 이 항목에서는 Snowflake와 관련된 ODBC 루틴을 나열하고 지원 여부를 제공합니다. 이러한 루틴은 수행하는 함수를 기준으로 카테고리로 구분됩니다.

전체 API 참고 자료는 Microsoft ODBC 프로그래머 참고 자료 를 참조하십시오.

이 항목의 내용:

데이터 원본에 연결하기

함수 이름

지원됨

참고

SQLAllocHandle

SQLConnect

SQLDriverConnect

SQLAllocEnv

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다.

SQLAllocConnect

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다.

SQLBrowseConnect

드라이버 및 데이터 원본에 대한 정보 획득하기

함수 이름

지원됨

참고

SQLDataSources

SQLDrivers

SQLGetInfo

SQLGetFunctions

SQLGetTypeInfo

드라이버 속성 설정 및 검색하기

함수 이름

지원됨

참고

SQLSetConnectAttr

SQL_ATTR_METADATA_ID를 설정하면 SQLTables 및 SQLColumns 함수에만 영향을 줍니다(다른 지원되는 카탈로그 함수 에는 영향을 주지 않음).

SQLGetConnectAttr

읽기 전용 모드는 지원되지 않습니다. 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 이후에 도입되었습니다.

SQLSetConnectOption

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다.

SQLGetConnectOption

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다.

SQLSetEnvAttr

SQLGetEnvAttr

SQL_ATTR_CONNECTION_POOLING 속성은 ODBC API 버전 3.52 이후에 도입되었으며 지원되지 않습니다.

SQLSetStmtAttr

SQL_ATTR_CURSOR_SCROLLABLE은 SQL_NONSCROLLABLE 값만 지원합니다. . SQL_ATTR_USE_BOOKMARKS는 SQL_UB_OFF 값만 지원합니다. . . 서드 파티 도구와의 호환성을 위해 SQL_ATTR_ENABLE_AUTO_IPD는 기본적으로 true로 설정되며, 이는 ODBC 표준에서 기본값을 false로 설정할 것을 권장하는 경우에도 마찬가지입니다. 기본값을 false로 변경하려면, EnableAutoIpdByDefault 매개 변수를 false 로 설정합니다. . . SQL_ATTR_METADATA_ID를 설정하면 SQLTables 및 SQLColumns 함수에만 영향을 줍니다(다른 지원되는 카탈로그 함수 에는 영향을 주지 않음). . . 지원되지 않는 속성: SQL_ATTR_SIMULATE_CURSOR, SQL_ATTR_FETCH_BOOKMARK_PTR, SQL_ATTR_KEYSET_SIZE.

SQLGetStmtAttr

Snowflake 구현에서는 표준 속성뿐만 아니라 SQL_SF_STMT_ATTR_LAST_QUERY_ID 속성도 지원하며, 이를 통해 사용자는 지정된 문 핸들과 연결된 가장 최든 쿼리 ID를 검색할 수 있습니다. 부분적인 예는 아래 섹션에서 확인할 수 있습니다.

SQLSetStmtOption

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. SQLSetStmtAttr 에 의해 대체되었습니다.

SQLGetStmtOption

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. SQLGetStmtAttr 에 의해 대체되었습니다.

SQLParamOptions

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. SQLSetStmtAttr 에 의해 대체되었습니다.

각 이전 함수에는 와이드 문자(유니코드)를 허용하는 해당 함수가 있습니다. 그러한 각 유니코드 함수의 이름은 위와 같으며, 뒤에 “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는 이 속성을 사용하여 개인 키를 설정하는 것을 권장합니다.

설명자 필드 설정 및 검색하기

함수 이름

지원됨

참고

SQLGetDescField

SQLGetDescRec

SQLSetDescField

SQLSetDescRec

SQL 요청 준비하기

함수 이름

지원됨

참고

SQLAllocStmt

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다.

SQLBindParameter

SQLPrepare

SQLGetCursorName

SQLSetCursorName

SQLSetScrollOptions

Snowflake 드라이버에서 지원되지만, ODBC API에서는 더 이상 사용되지 않습니다.

SQLSetParam

Snowflake 드라이버에서 지원되지만, ODBC API 버전 2.x에서는 더 이상 사용되지 않습니다. SQLBindParameter 에 의해 대체되었습니다.

참고

요청 제출하기

함수 이름

지원됨

참고

SQLExecute

SQLExecDirect

SQLNativeSql

SQLDescribeParam

매개 변수에 바인딩된 데이터 타입에 관계없이, Snowflake는 서버측 변환을 실행하고 VARCHAR(최대 길이 16777216자)를 반환합니다.

SQLNumParams

SQLParamData

이 함수에 대한 지원은 ODBC 드라이버 2.23.3 버전에 추가되었습니다.

SQLPutData

이 함수에 대한 지원은 ODBC 드라이버 2.23.3 버전에 추가되었습니다.

결과 및 결과에 대한 정보 검색하기

함수 이름

지원됨

참고

SQLBindCol

ODBC 드라이버는 현재 VARIANT, OBJECTARRAY 데이터 타입을 포함한 반정형 데이터를 지원하지 않습니다.

SQLError

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. SQLGetDiagRec 에 의해 대체되었습니다.

SQLGetData

SQLGetDiagField

SQLGetDiagRec

SQLRowCount

SQLNumResultCols

SQLDescribeCol

SQLColAttribute

GEOGRAPHY 열의 경우 SQL_DESC_TYPE_NAMEGEOGRAPHY 를 반환합니다. 기타 설명자(예: SQL_DESC_CONCISE_TYPE)는 열 타입이 GEOGRAPHY 임을 나타내지 않음에 유의하십시오.

SQLColAttributes

Snowflake 드라이버에서 지원되지만, ODBC API 버전 2.x에서는 더 이상 사용되지 않습니다. SQLColAttribute 에 의해 대체되었습니다.

SQLFetch

SQLFetchScroll

FetchOrientation 인자는 SQL_FETCH_NEXT 값만 지원합니다. 기타 모든 페치 타입은 실패합니다.

SQLExtendedFetch

API 버전 3.x 드라이버에서 SQLFetchScroll 에 의해 대체되었습니다.

SQLSetPos

Snowflake는 이 기능을 지원하지 않습니다.

SQLBulkOperations

Snowflake는 이 기능을 지원하지 않습니다.

데이터 원본의 시스템 테이블에 대한 정보 획득하기(카탈로그 함수)

함수 이름

지원됨

참고

SQLColumnPrivileges

설정된 빈 결과를 반환합니다.

SQLColumns

SQLForeignKeys

SQLPrimaryKeys

SQLProcedureColumns

SQLProcedures

결과 세트에서 NUM_INPUT_PARAMS 열에는 프로시저에 대한 인자의 개수가 포함됩니다(SHOW PROCEDURES 명령의 출력에서 max_num_arguments 열의 값). . . Snowflake의 저장 프로시저는 출력 매개 변수를 지원하지 않으므로 NUM_OUTPUT_PARAMS 열에는 NULL 값이 포함됩니다. . . Snowflake의 저장 프로시저는 결과 세트를 반환하지 않으므로 NUM_RESULT_SETS 열에도 NULL 값이 포함됩니다. . . Snowflake의 저장 프로시저는 항상 값을 반환하므로 PROCEDURE_TYPE 열에는 항상 SQL_PT_FUNCTION 이 포함됩니다.

SQLSpecialColumns

설정된 빈 결과를 반환합니다.

SQLStatistics

설정된 빈 결과를 반환합니다.

SQLTablePrivileges

설정된 빈 결과를 반환합니다.

SQLTables

함수에 전달된 매개 변수가 “TABLE”인 경우, 함수는 일시적 테이블 및 임시 테이블 등 모든 테이블 타입을 반환합니다. . . 함수로 전달된 매개 변수가 “VIEW”인 경우 함수는 구체화된 뷰 등 모든 타입의 뷰를 반환합니다. . . 함수로 전달된 매개 변수가 “TABLE, VIEW” 또는 “%”인 경우 함수는 모든 타입의 테이블 및 모든 타입의 뷰에 대한 정보를 반환합니다.

카탈로그 함수로 전달된 이름에 유효하지 않은 문자가 포함되거나 이름이 데이터베이스 오브젝트와 일치하지 않는 경우 함수는 빈 결과 세트를 반환합니다.

SQL_ATTR_METADATA_ID 를 설정하면 SQLTables, SQLColumnsSQLProcedures 함수에만 영향을 줍니다.

문 종료하기

함수 이름

지원됨

참고

SQLFreeStmt

SQLCloseCursor

SQLCancel

SQLEndTran

SQLTransact

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다. SQLEndTran 에 의해 대체되었습니다.

연결 종료하기

함수 이름

지원됨

참고

SQLCancelHandle

3.52 버전 이후의 API에 도입되었습니다.

SQLDisconnect

SQLFreeHandle

SQLFreeConnect

Snowflake 드라이버에서 지원되지만, ODBC API 버전 3.x에서는 더 이상 사용되지 않습니다.

SQLFreeEnv

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
Copy

다음 코드는 사용자 지정 데이터 타입의 샘플 사용법을 보여줍니다.

// 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);
Copy

이 섹션은 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);
Copy

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);
Copy

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);
Copy

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);
Copy