Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Aplica-se a:SQL Server
Base de Dados SQL do Azure
Instância Gerida do Azure SQL
Azure Synapse Analytics
Importante
SQL Server Native Client (SNAC) não é fornecido com:
- SQL Server 2022 (16.x) e versões posteriores
- SQL Server Management Studio 19 e versões posteriores
O SQL Server Native Client (SQLNCLI ou SQLNCLI11) e o Microsoft OLE DB Provider for SQL Server (SQLOLEDB) herdado não são recomendados para o desenvolvimento de novos aplicativos.
Para novos projetos, use um dos seguintes drivers:
Para o SQLNCLI fornecido como componente do Mecanismo de Base de Dados do SQL Server (versões de 2012 a 2019), consulte esta exceção ao Ciclo de Vida de Suporte .
O Driver ODBC de Cliente Nativo de SQL Server 2012 (11.x) (SQLNCLI11.dll) alterou a forma como executa as conversões SQL_WCHAR* (NCHAR/NVARCHAR/NVARCHAR(MAX)) e SQL_CHAR* (CHAR/VARCHAR/NARCHAR(MAX)). Funções ODBC, como SQLGetData, SQLBindCol, SQLBindParameter, return (-4) SQL_NO_TOTAL como parâmetro de comprimento/indicador ao utilizar o driver ODBC do SQL Server Native Client 2012. Versões anteriores do driver ODBC do SQL Server Native Client devolviam um valor de comprimento, que pode estar incorreto.
Comportamento do SQLGetData
Muitas funções do Windows permitem especificar um tamanho de buffer de 0 e o comprimento devolvido é o tamanho dos dados devolvidos. O seguinte padrão é comum entre programadores de Windows:
int iSize = 0;
BYTE * pBuffer = NULL;
GetMyFavoriteAPI(pBuffer, &iSize); // Returns needed size in iSize
pBuffer = new BYTE[iSize]; // Allocate buffer
GetMyFavoriteAPI(pBuffer, &iSize); // Retrieve actual data
No entanto, o SQLGetData não deve ser utilizado neste cenário. O seguinte padrão não deve ser utilizado:
// bad
int iSize = 0;
WCHAR * pBuffer = NULL;
SQLGetData(hstmt, SQL_W_CHAR, ...., (SQLPOINTER*)0x1, 0, &iSize); // Get storage size needed
pBuffer = new WCHAR[(iSize/sizeof(WCHAR)) + 1]; // Allocate buffer
SQLGetData(hstmt, SQL_W_CHAR, ...., (SQLPOINTER*)pBuffer, iSize, &iSize); // Retrieve data
O SQLGetData só pode ser chamado para recuperar pedaços de dados reais. Usar SQLGetData para obter o tamanho dos dados não é desnecessário.
O que se segue mostra o impacto da mudança do driver quando se usa o padrão incorreto. Esta aplicação consulta uma coluna varchar e a ligação como Unicode (SQL_UNICODE/SQL_WCHAR):
Consulta: select convert(varchar(36), '123')
SQLGetData(hstmt, SQL_WCHAR, ....., (SQLPOINTER*) 0x1, 0 , &iSize); // Attempting to determine storage size needed
| Versão do Driver ODBC do SQL Server Native Client | Duração ou Resultado Indicador | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Cliente Nativo ou anterior | 6 | O maquinista assumiu incorretamente que converter CHAR para WCHAR poderia ser feito com o comprimento * 2. |
| SQL Server 2012 (11.x) Cliente Nativo (versão 11.0.2100.60) ou posterior | -4 (SQL_NO_TOTAL) | O condutor já não assume que converter de CHAR para WCHAR ou de WCHAR para CHAR é uma ação (multiplicar) *2 ou (dividir)/2. Chamar SQLGetData já não retorna o comprimento da conversão esperada. O condutor deteta a conversão para ou a partir de CHAR e WCHAR e devolve (-4) SQL_NO_TOTAL em vez de *2 ou /2 comportamentos que podem estar incorretos. |
Usa SQLGetData para recuperar os pedaços dos dados. (Pseudocódigo mostrado:)
while( (SQL_SUCCESS or SQL_SUCCESS_WITH_INFO) == SQLFetch(...) ) {
SQLNumCols(...iTotalCols...)
for(int iCol = 1; iCol < iTotalCols; iCol++) {
WCHAR* pBufOrig, pBuffer = new WCHAR[100];
SQLGetData(.... iCol ... pBuffer, 100, &iSize); // Get original chunk
while(NOT ALL DATA RETRIEVED (SQL_NO_TOTAL, ...) ) {
pBuffer += 50; // Advance buffer for data retrieved
// May need to realloc the buffer when you reach current size
SQLGetData(.... iCol ... pBuffer, 100, &iSize); // Get next chunk
}
}
}
Comportamento do SQLBindCol
Consulta: select convert(varchar(36), '1234567890')
SQLBindCol(... SQL_W_CHAR, ...) // Only bound a buffer of WCHAR[4] - Expecting String Data Right Truncation behavior
| Versão do Driver ODBC do SQL Server Native Client | Duração ou Resultado Indicador | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Cliente Nativo ou anterior | 20 |
O SQLFetch reporta que existe um truncamento no lado direito dos dados. O comprimento é o comprimento dos dados devolvidos, não o que foi armazenado (assume *2 conversão de CHAR para WCHAR, o que pode estar incorreto para glifos). Os dados armazenados no buffer são 123/0. O buffer é garantido como terminado por NULL. |
| SQL Server 2012 (11.x) Cliente Nativo (versão 11.0.2100.60) ou posterior | -4 (SQL_NO_TOTAL) |
O SQLFetch reporta que existe um truncamento no lado direito dos dados. O comprimento indica -4 (SQL_NO_TOTAL) porque o resto dos dados não foi convertido. Os dados armazenados no buffer são 123\0. - O buffer é garantido como terminado por NULL. |
SQLBindParameter (Comportamento do Parâmetro OUTPUT)
Consulta: create procedure spTest @p1 varchar(max) OUTPUT
select @p1 = replicate('B', 1234)
SQLBindParameter(... SQL_W_CHAR, ...) // Only bind up to first 64 characters
| Versão do Driver ODBC do SQL Server Native Client | Duração ou Resultado Indicador | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Cliente Nativo ou anterior | 2468 |
O SQLFetch não retorna mais dados disponíveis. O SQLMoreResults não retorna mais dados disponíveis. O comprimento indica o tamanho dos dados devolvidos pelo servidor, não armazenados em buffer. O buffer original contém 63 bytes e um terminador NULL. O buffer é garantido como terminado por NULL. |
| SQL Server 2012 (11.x) Cliente Nativo (versão 11.0.2100.60) ou posterior | -4 (SQL_NO_TOTAL) |
O SQLFetch não retorna mais dados disponíveis. O SQLMoreResults não retorna mais dados disponíveis. O comprimento indica (-4) SQL_NO_TOTAL porque o resto dos dados não foi convertido. O buffer original contém 63 bytes e um terminador NULL. O buffer é garantido como terminado por NULL. |
Realização de conversões CHAR e WCHAR
O driver SQL Server 2012 (11.x) Native Client ODBC oferece várias formas de realizar conversões CHAR e WCHAR. A lógica é semelhante à manipulação de blobs (varchar(max), nvarchar(max), ...):
Os dados são guardados ou truncados no buffer especificado quando ligados com SQLBindCol ou SQLBindParameter.
Se não fizeres bind, podes recuperar os dados em blocos usando SQLGetData e SQLParamData.