Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O Driver ODBC do SQL Server 2012 Native Client (SQLNCLI11.dll) alterou o funcionamento das conversões SQL_WCHAR* (NCHAR/NVARCHAR/NVARCHAR(MAX)) e SQL_CHAR* (CHAR/VARCHAR/NARCHAR(MAX)). Funções ODBC, como SQLGetData, SQLBindCol, SQLBindParameter, retornam (-4) SQL_NO_TOTAL como o parâmetro de comprimento/indicador ao usar o driver ODBC do SQL Server 2012 Native Client. As versões anteriores do driver ODBC do SQL Server Native Client retornaram um valor de comprimento, o que pode estar incorreto.
Comportamento do SQLGetData
Muitas funções do Windows permitem especificar um tamanho de buffer de 0 e o comprimento retornado é o tamanho dos dados retornados. O seguinte padrão é comum para programadores do 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, SQLGetData não deve ser usado neste cenário. O seguinte padrão não deve ser usado:
// 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
SQLGetData só pode ser chamado para recuperar partes de dados reais. O uso do SQLGetData para obter o tamanho dos dados não tem suporte.
O exemplo a seguir mostra o impacto da alteração do driver quando você usa o padrão incorreto. Este aplicativo consulta uma coluna e uma varchar associaçã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 | Comprimento ou resultado do indicador | Descrição |
|---|---|---|
| SQL Server 2008 R2 Native Client ou anterior | 6 | O driver assumiu incorretamente que a conversão de CHAR em WCHAR poderia ser realizada como comprimento * 2. |
| SQL Server 2012 Native Client (versão 11.0.2100.60) ou posterior | -4 (SQL_NO_TOTAL) | O driver não pressupõe mais que converter de CHAR em WCHAR ou WCHAR em CHAR é uma ação (multiplicar) *2 ou (dividir)/2. Chamar SQLGetData não retorna mais o comprimento da conversão esperada. O driver detecta a conversão de ou para CHAR e WCHAR e retorna (-4) SQL_NO_TOTAL em vez de *2 ou /2 comportamento que pode estar incorreto. |
Use SQLGetData para recuperar as partes 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 RETREIVED (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 de 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 | Comprimento ou resultado do indicador | Descrição |
|---|---|---|
| SQL Server 2008 R2 Native Client ou anterior | 20 |
- O SQLFetch informa que há um truncamento no lado direito dos dados. - O comprimento é o comprimento dos dados retornados, não o que foi armazenado (pressupõe *2 CHAR para conversão WCHAR que pode estar incorreto para glifos). - Os dados armazenados no buffer são 123\0. O buffer tem a garantia de ser encerrado em NULL. |
| SQL Server 2012 Native Client (versão 11.0.2100.60) ou posterior | -4 (SQL_NO_TOTAL) |
- O SQLFetch informa que há um truncamento no lado direito dos dados. - O comprimento indica -4 (SQL_NO_TOTAL) porque o restante dos dados não foi convertido. - Os dados armazenados no buffer são 123\0. - O buffer tem a garantia de ser encerrado 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 | Comprimento ou resultado do indicador | Descrição |
|---|---|---|
| SQL Server 2008 R2 Native Client ou anterior | 2468 |
-
O SQLFetch não retorna mais dados disponíveis. - O SQLMoreResults não retorna mais dados disponíveis. - O tamanho indica o tamanho dos dados retornados do servidor, não armazenados no buffer. - O buffer original contém 63 bytes e um terminador NULL. O buffer tem a garantia de ser encerrado em NULL. |
| SQL Server 2012 Native Client (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 restante dos dados não foi convertido. - O buffer original contém 63 bytes e um terminador NULL. O buffer tem a garantia de ser encerrado em NULL. |
Executando conversões CHAR e WCHAR
O driver ODBC do SQL Server 2012 Native Client oferece várias maneiras de executar conversões CHAR e WCHAR. A lógica é semelhante à manipulação de blobs (varchar(max), nvarchar(max), ...):
Os dados são salvos ou truncados no buffer especificado ao associar com SQLBindCol ou SQLBindParameter.
Se você não associar, poderá recuperar os dados em partes usando SQLGetData e SQLParamData.