ID do artigo: 259691 - Última revisão: quarta-feira, 12 de outubro de 2005 - Revisão: 4.4

CORRECÇÃO: Mensagem de erro "Formato de hora inválido" ao inserir data/hora com valores de máximo

Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.

Nesta página

Expandir tudo | Recolher tudo

Sintomas

Quando você usa o driver ODBC do Microsoft SQL Server e você usar SQLSetPos para inserir ou valores de data ou hora de atualização que contêm os valores máximo permitidos para a hora, minuto, segundo e partes de milissegundos (como 23:59:59:999 1999-10-03), a instrução de inserção tiver êxito, mas valores incorretos são salvas no banco de dados.

Se você tentar selecionar novamente os valores de data/hora, a instrução gera um erro ou retorna valores incorretos, dependendo de como o campo de data/hora é ligado. Se o campo está vinculado como um SQL_C_TIMESTAMP, ocorrerá a mensagem de erro que se segue:
SQLState = 22007
[Microsoft][ODBC SQL Server ODBC driver]Formato de hora inválido
Quando o campo é vinculado como um SQL_C_CHAR, não ocorre nenhum erro; no entanto, valores incorretos são retornados, como 24:00:00.000 1999-10-03. Isso pode gerar erros no aplicativo de recebimento porque 24:00:00.000 não é um valor de data/hora válido.

Este erro ocorre com a compilação do Windows 2000/MDAC 2.5 do driver ODBC para SQL Server (versão 3.70.820) e versões anteriores.

Causa

Erro no algoritmo que converte a data/hora não é sem interrupção parte do tempo em horas à parte da data de dias.

Resolução

Um hotfix suportado agora está disponível da Microsoft, mas destina-se somente a corrigir o problema descrito neste artigo. Aplique-o somente nos sistemas que apresentarem esse problema específico. Esta correcção poderá submetida a testes adicionais. Portanto, se você não tiver sido gravemente afetado por esse problema, recomendamos que você aguarde o próximo Microsoft Data Access Components service pack que contém esse hotfix.

Para resolver esse problema imediatamente, contate o Atendimento Microsoft para obter a correção. Para obter uma lista completa dos números de telefone do Atendimento Microsoft do e informações sobre os custos de suporte, visite o seguinte site:
http://support.microsoft.com/contactus/?ws=support (http://support.microsoft.com/contactus/?ws=support)
Observação : em alguns casos, as taxas cobradas pelas ligações para chamadas de suporte podem ser canceladas se um profissional de suporte da Microsoft determinar que uma atualização específica resolverá o problema. Os custos de suporte normais serão aplicados a questões e problemas que não se qualificam à atualização específica em questão de suporte adicionais.



A versão em inglês dessa correção deve ter os seguintes atributos de arquivo ou posteriores:

   Date       Version      Size             File name    
   -----------------------------------------------------

   04/04/00   3.70.0784     24,848 bytes    Odbcbcp.dll
   04/04/00   3.70.0784    516,368 bytes    Sqlsrv32.dll

				




Solução alternativa

Aqui estão duas soluções possíveis para esse problema:
  • Se possível, executar as inserções e atualizações através de instruções SQL diretas, o que permite a SQL Server, em seguida, manipular a conversão dos valores de data/hora.

    - ou -

  • Se o armazenamento de milissegundos não for necessário, defina o campo como um tipo de dados smalldatetime em vez de data e hora. O tipo de dados smalldatetime somente usa 4 bytes para armazenamento e não inclui precisão milissegundos.

Situação

A Microsoft confirmou que esse é um problema nos produtos da Microsoft listados no começo deste artigo.

Mais Informações

Instalação manual do arquivo do Hotfix

  1. Feche quaisquer aplicativos ou serviços que usam o driver ODBC para SQL Server, Sqlsrv32.dll. Isso pode incluir Internet Information Server (IIS), Microsoft Transaction Server (MTS) e os aplicativos ODBC, Microsoft ActiveX Data Objects (ADO) ou OLE DB.
  2. Baixe o hotfix em um diretório temporário.
  3. Localize e renomeie as atuais versões dos arquivos Sqlsrv32.dll e Odbcbcp.dll, que devem estar na pasta \Winnt\System32 para computadores que executam o Microsoft Windows NT e na pasta \Windows\System para computadores executando o Microsoft Windows 95 e Microsoft Windows 98.
  4. Copie os arquivos de hotfix para o mesmo local e reinicie os serviços e aplicativos.

Etapas para reproduzir o problema

  1. Copie o código na etapa 2 em um aplicativo de console do Microsoft Visual C++ e, em seguida, compile o código. Por favor, observe que talvez seja necessário alterar o nome de fonte de dados, identificação de usuário e a senha.
  2. Executar o código e observe que um erro ocorre quando o valor de data/hora como SQL_C_TIMESTAMP de ligação e que um valor de hora inválido é retornado ao ligar o valor de data/hora como SQL_C_CHAR.
    #include <windows.h>
    #include <stdio.h>
    #include <sql.h>
    #include <sqlext.h>
    #include <time.h>
    
    void CreateTable(HSTMT);
    
    main()
    {
    
    //	ODBC handles
    	RETCODE rc;
    	HENV henv;
    	HDBC hdbc;
    	HSTMT hstmt;
    
    //	Variables for SQLConnect
    
    	char * dsn = "Pubs";
    	char * uid = "sa";
    	char * pwd = "";
    
    //	Variables for SQLDiagRec
    	char mstate[6] = "\0";
    	long native = 0;
    	char mtext[300] = "\0";
    	short mlength = 0;
    	short i = 0;
    	
    //	Variables for SQLBindCol
    	int m_ID = 1;
    	long m_idLen = 4;
    	TIMESTAMP_STRUCT m_time = {1999,10,03,23,59,59,999000000};
    	char m_timeChar[30] = "\0";
    	long m_timeLen = 16;
    	long sqlnts = SQL_NTS;
    
    //	miscellaneous variables	
    	char * strSQL = "Select * from MillisecTest";
    	char * strDropTable = "Drop table MillisecTest";
    	unsigned short status = 0;
    	unsigned long rowcount = 0;
    
    
    
    //	Allocate ODBC handles and connect
    	rc = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
    	rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3,0);
    	rc = SQLAllocHandle(SQL_HANDLE_DBC,henv, &hdbc);
    
    	rc = SQLConnect(hdbc, (unsigned char *)dsn,
    		SQL_NTS, (unsigned char *)uid,
    		SQL_NTS, (unsigned char *)pwd, SQL_NTS);
    
    	rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    
    //	Table creation 
    	CreateTable(hstmt);
    
    //	Set statement attributes so SQLSetPos can be used
    	rc = SQLSetStmtAttr( hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER)SQL_CONCUR_LOCK, 0 );
    	rc = SQLSetStmtAttr( hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0 );
    
    //	Bind the columns, using SQL_C_TIMESTAMP
    	rc = SQLBindCol(hstmt, 1, SQL_C_SHORT, &m_ID, 4, &m_idLen);
    	rc = SQLBindCol(hstmt, 2, SQL_C_TIMESTAMP, &m_time, sizeof(m_time), &m_timeLen);
    
    //	Execute the statement and use SQLSetPos to insert the date/time data
    	rc = SQLExecDirect(hstmt, (unsigned char *)strSQL, SQL_NTS);
    	rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &rowcount, &status );
    	rc = SQLSetPos(hstmt, 1, SQL_ADD, SQL_LOCK_NO_CHANGE);
    
    
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    
    
    	memset(&m_time, 0, sizeof(m_time));
    
    //	Re-execute the statement, and attempt to fetch back the new date/time value
    	rc = SQLExecDirect(hstmt, (unsigned char *)strSQL, SQL_NTS);
    	rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &rowcount, &status );
    
    	SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, 1, (unsigned char *)&mstate, &native, 
    				(unsigned char *)&mtext, 300, &mlength);
    	printf("\nError when attempting to bind as SQL_C_TIMESTAMP:\n\n");
    	printf("\tSQLSTATE\t%s\n\tNative Error\t%i\n\tMessage\t%s\n\n",mstate, native, mtext);
    
    
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    
    
    //	Bind the date/time column as SQL_C_CHAR this time
    	rc = SQLBindCol(hstmt, 2, SQL_C_CHAR, m_timeChar, sizeof(m_timeChar), &sqlnts);
    	rc = SQLExecDirect(hstmt, (unsigned char *)strSQL, SQL_NTS);
    	rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &rowcount, &status );
    	printf("\nInvalid hour when timestamp is bound as SQL_C_CHAR:  %s\n\n", m_timeChar); 
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	
    
    
    //	Cleanup
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	SQLExecDirect(hstmt, (unsigned char *)strDropTable, SQL_NTS);
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	SQLFreeStmt(hstmt, SQL_DROP);
    	SQLDisconnect(hdbc);
    	SQLFreeConnect(hdbc);
    	SQLFreeEnv(henv);
    
    	printf("\nDo the \"Press any key\" thing...");
    	getchar();
    	return(TRUE);
    };
    
    //------- CreateTable() ----------------
    
    void CreateTable(HSTMT hstmt)
    {
    
    	RETCODE rc = 0;
    	char SqlStatements[2][90] = 
    	{"Drop table MillisecTest",
    	"Create table MillisecTest (ID integer constraint index1 PRIMARY KEY, TimeTest datetime)"};
    
    	rc = SQLExecDirect(hstmt, (unsigned char *)SqlStatements[0], SQL_NTS);
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	rc = SQLExecDirect(hstmt, (unsigned char *)SqlStatements[1], SQL_NTS);
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    
    
    }
    					

A informação contida neste artigo aplica-se a:
  • Microsoft Data Access Components 2.1 Service Pack 2
  • Microsoft Data Access Components 2.1 Service Pack 1
  • Microsoft Data Access Components 2.1 Service Pack 2
  • Microsoft Data Access Components 2.5
  • Microsoft ODBC Driver para Microsoft SQL Server 3.7
Palavras-chave: 
kbmt kbhotfixserver kbqfe kbbug kbcodesnippet kbdatabase kbfix kbmdac210sp2fix kbqfe KB259691 KbMtpt
Tradução automáticaTradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 259691  (http://support.microsoft.com/kb/259691/en-us/ )