Suporte de API do driver ODBC¶
O driver ODBC do Snowflake oferece suporte à versão 3.52 da API ODBC. Este tópico lista as rotinas ODBC relevantes para o Snowflake e indica se elas são compatíveis. As rotinas são organizadas em categorias com base na função que desempenham.
Para obter a referência completa da API, consulte a Referência do programador ODBC da Microsoft.
Neste tópico:
Conexão a uma fonte de dados¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. |
|
✔ |
Como obter informações de drivers e fontes de dados¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Configuração e recuperação de atributos de drivers¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
A configuração SQL_ATTR_METADATA_ID afeta apenas as funções SQLTables e SQLColumns (e não as outras funções de catálogo suportadas). |
|
✔ |
Não há suporte para o modo somente leitura. SQL_MODE_READ_ONLY é passado para o driver, mas o Snowflake ainda grava no banco de dados. . . Além disso, alguns atributos foram introduzidos após a versão 3.52 da API: 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. |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. |
|
✔ |
|
|
✔ |
O atributo SQL_ATTR_CONNECTION_POOLING foi introduzido após a versão 3.52 da API ODBC e não é suportado. |
|
✔ |
SQL_ATTR_CURSOR_SCROLLABLE aceita apenas um valor SQL_NONSCROLLABLE. . SQL_ATTR_USE_BOOKMARKS aceita apenas um valor SQL_UB_OFF. . . Para compatibilidade com ferramentas de terceiros, SQL_ATTR_ENABLE_AUTO_IPD é definido como verdadeiro por padrão, mesmo que o padrão ODBC diga que ele deve ser falso. Para alterar o valor padrão para falso, defina o parâmetro EnableAutoIpdByDefault como |
|
✔ |
Além dos atributos padrão, a implementação do Snowflake oferece suporte ao atributo SQL_SF_STMT_ATTR_LAST_QUERY_ID, que permite ao usuário recuperar a ID da consulta mais recente associada ao identificador da instrução especificada. Veja um exemplo parcial na seção Exemplos abaixo. |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. Substituída por |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. Substituída por |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. Substituída por |
Cada uma das funções anteriores tem uma função correspondente que aceita caracteres amplos (unicode). Cada uma dessas funções unicode tem o nome mostrado acima, seguido por «W». Por exemplo, a função SQLGetStmtAttr
, que aceita uma matriz de caracteres como terceiro parâmetro, tem uma função correspondente chamada SQLGetStmtAttrW
, que aceita uma matriz de caracteres amplos como terceiro parâmetro.
Comportamento específico do Snowflake¶
SQLSetConnectAttr
Esse método é compatível com dois atributos específicos do Snowflake:
Nome do atributo
Descrição
SQL_SF_CONN_ATTR_APPLICATION
Substitui o valor especificado pela configuração APPLICATION no registro ou no arquivo .ini.
SQL_SF_CONN_ATTR_PRIV_KEY
Ponteiro EVP_PKEY* que aponta para uma cópia da chave privada na memória. Substitui as configurações PRIV_KEY_FILE e PRIV_KEY_PWD no registro ou no arquivo .ini. O Snowflake recomenda o uso desse atributo para definir a chave privada.
Configuração e recuperação dos campos descritores¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Preparação de solicitações SQL¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. |
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC. |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 2.x. Substituída por |
Nota
Há um limite máximo para o tamanho dos dados que você pode vincular. Para obter mais detalhes, consulte Limites no tamanho do texto de consulta.
Instruções SQL com suporte para preparação lista os tipos de instruções SQL que são suportadas na preparação.
Envio de solicitações¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Independentemente do tipo de dados vinculado ao parâmetro, o Snowflake realiza uma conversão no lado do servidor e retorna um VARCHAR com um comprimento máximo de 16777216. |
|
✔ |
|
|
✔ |
O suporte para essa função foi adicionado na versão 2.23.3 do driver ODBC. |
|
✔ |
O suporte para essa função foi adicionado na versão 2.23.3 do driver ODBC. |
Obtenção de resultados e informações sobre os resultados¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
No momento, o driver ODBC não oferece suporte a dados semiestruturados, incluindo os tipos de dados |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. Substituída por |
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Nas colunas GEOGRAPHY, |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 2.x. Substituída por |
|
✔ |
|
|
✔ |
O argumento |
|
Substituída por |
|
|
O Snowflake não oferece suporte à funcionalidade. |
|
|
O Snowflake não oferece suporte à funcionalidade. |
Obtenção de informações sobre as tabelas de sistema da fonte de dados (funções de catálogo)¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
Retorna um conjunto de resultados vazio. |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
No conjunto de resultados, a coluna |
|
Retorna um conjunto de resultados vazio. |
|
|
Retorna um conjunto de resultados vazio. |
|
|
Retorna um conjunto de resultados vazio. |
|
|
✔ |
Se o parâmetro passado para a função for “TABLE”, a função retorna todos os tipos de tabelas, incluindo tabelas transitórias e tabelas temporárias. . . Se o parâmetro passado para a função for “VIEW”, a função retorna todos os tipos de exibições, inclusive as exibições materializadas. . . Se o parâmetro passado para a função for “TABLE, VIEW” ou “%”, a função retorna informações sobre todos os tipos de tabelas e todos os tipos de exibições. |
Se o nome passado para a função de catálogo tiver um caractere inválido, ou se o nome não corresponder a nenhum objeto do banco de dados, a função retorna um conjunto de resultados vazio.
A configuração SQL_ATTR_METADATA_ID
afeta apenas as funções SQLTables
, SQLColumns
e SQLProcedures
.
Encerramento de uma instrução¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. Substituída por |
Encerramento de uma conexão¶
Nome da função |
Com suporte |
Notas |
---|---|---|
|
Introduzida na versão da API posterior à versão 3.52. |
|
|
✔ |
|
|
✔ |
|
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. |
|
✔ |
O driver do Snowflake oferece suporte, mas foi depreciada na API ODBC versão 3.x. |
Tipos de dados SQL personalizados¶
Alguns tipos de dados SQL aceitos pelo Snowflake não têm mapeamento direto no ODBC (por exemplo, TIMESTAMP_*tz, VARIANT). Para permitir que o driver ODBC trabalhe com os tipos de dados sem suporte, o arquivo de cabeçalho enviado com o driver inclui definições para os seguintes tipos de dados personalizados:
////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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
O código a seguir mostra um exemplo de uso dos tipos de dados personalizados:
// 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);
Exemplos¶
Esta seção oferece exemplos de utilização da API.
Recuperação da ID da última consulta¶
Recuperar a ID da última consulta é uma extensão do Snowflake para o padrão ODBC.
Para recuperar a ID da última consulta, chame a função SQLGetStmtAttr
(ou SQLGetStmtAttrW
), e passe o atributo SQL_SF_STMT_ATTR_LAST_QUERY_ID e uma matriz de caracteres grande o suficiente para armazenar a ID da consulta.
O exemplo abaixo mostra como recuperar a ID da consulta de uma consulta:
// 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);
Se você estiver usando Linux ou macOS, chame SQLGetStmtAttrW
e passe parâmetros do tipo de dados apropriado (por exemplo, «wchar» em vez de «char»).
Práticas recomendadas para melhorar o desempenho na recuperação de dados¶
Ao recuperar dados com SQLFetch
, você pode usar as funções SQLGetData
ou SQLBindCol
para acessar o conteúdo das células. Na maioria dos casos, o uso de SQLBindCol
proporciona melhor desempenho porque reduz o número de chamadas ODBC que você precisa fazer para recuperar os dados, e porque permite que você tire proveito da cópia de dados na memória.
Como usar SQLGetData
para recuperar dados da célula¶
O exemplo a seguir usa a função SQLGetData
para recuperar valores de células do buffer de dados retornados por SQLFetch
. Observe que você precisa chamar SQLGetData
uma vez para cada célula da linha.
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);
Como usar SQLBindCol
para vincular as colunas de uma linha de dados¶
O exemplo a seguir usa a função SQLBindCol
para recuperar valores de células do buffer de dados retornados por SQLFetch
. Ela cria um buffer na memória para o número de colunas em uma linha e depois faz uma única chamada SQLBindCol
para vincular os buffers do aplicativo ao conjunto de resultados. Finalmente, ela chama SQLFetch
uma vez por linha e carrega os valores das células no buffer. Essa abordagem pode aumentar significativamente a velocidade e a eficiência da recuperação de dados.
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);
Como usar SQLBindCol
para vincular colunas de várias linhas de dados¶
Você pode melhorar ainda mais o desempenho ao buscar várias linhas em uma única chamada SQLFetch
, o que reduz o número de chamadas ODBC SQLFetch
necessárias para processar todas as linhas de uma tabela de consulta.
O exemplo a seguir:
Determina o número de colunas no conjunto de resultados.
Cria uma matriz na memória para armazenar os dados de várias colunas.
Chama
SQLBindCol
para cada coluna para vincular os buffers do aplicativo ao conjunto de resultados.Chama
SQLFetch
para obter o número especificado de linhas (100) e processa os dados no buffer de memória sem fazer chamadas ODBC, até que o final da tabela de consulta seja alcançado.
Essa abordagem pode aumentar significativamente a velocidade e a eficiência da recuperação de dados. Para uma tabela de consulta com 20 colunas e 1.000 linhas, esse exemplo faria apenas 20 chamadas SQLBindCol
e 10 SQLFetch
em vez de 20.000 chamadas SQLGetData
para carregar todos os dados da tabela.
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);