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" quando é inserida uma 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 | Reduzir tudo

Sintomas

Quando utiliza o controlador ODBC do Microsoft SQL Server e utilize SQLSetPos para inserir ou valores de data ou hora de actualização que contêm os valores máximo permitidos para a hora, minuto, segundo e partes milisegundos (tal como 23:59:59:999 1999-10-03), a instrução de inserção com êxito mas valores incorrectos são guardados na base de dados.

Se tentar voltar a seleccionar os valores de data/hora novamente, a instrução gera um erro ou devolve valores incorrectos, dependendo de como o campo de data/hora está ligado. Se o campo está ligado como um SQL_C_TIMESTAMP, ocorre a mensagem de erro que se segue:
SQLState = 22007
[Microsoft][Controlador ODBC do ODBC do SQL Server]Formato de hora inválido
Ocorre quando o campo está ligado como um SQL_C_CHAR, sem erro; no entanto, são devolvidos valores incorrectos, tais como 24:00:00.000 1999-10-03. Este pode gerar erros na aplicação de recepção 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 controlador de ODBC para SQL Server (versão 3.70.820) e versões anteriores.

Causa

Erro no algoritmo que converte a data/hora não está a parte do tempo em horas à parte da data de dias.

Resolução

Agora é disponibilizada pela Microsoft uma correcção suportada, mas destina-se apenas a corrigir o problema descrito neste artigo. Aplique-a apenas em sistemas que tenham este problema específico. Esta correcção poderá submetida a testes adicionais. Por conseguinte, se não estiver a ser gravemente afectado por este problema, recomendamos que aguarde pelo próximo service pack do Microsoft Data Access Components que contenha esta correcção.

Para resolver este problema imediatamente, contacte o suporte técnico da Microsoft para obter a correcção. Para obter uma lista completa de números de telefone do suporte técnico da Microsoft e informações sobre os custos de suporte, visite o seguinte Web site da Microsoft:
http://support.microsoft.com/contactus/?ws=support (http://support.microsoft.com/contactus/?ws=support)
Nota : em casos especiais, os custos normalmente inerentes às chamadas de suporte poderão ser anulados se um técnico de suporte da Microsoft determinar que uma actualização específica resolverá o problema. Os custos de suporte normais se aplicarão perguntas de suporte adicionais e problemas que não se enquadrem na atualização específica em questão.



A versão inglesa desta correcção deverá ter os seguintes atributos de ficheiro 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

Seguem-se duas soluções possíveis para este problema:
  • Se possível, efectue as inserções e actualizações através de instruções de SQL directas, que lhe permite do SQL Server processam a conversão dos valores de data/hora.

    - ou -

  • Se não for necessário armazenamento de milissegundos, define o campo como um tipo de dados smalldatetime em vez de data/hora. O tipo de dados smalldatetime só utiliza 4 bytes para armazenamento e não inclui o milissegundo precisão.

Ponto Da Situação

A Microsoft confirmou que este erro ocorre nos produtos da Microsoft listados no início deste artigo.

Mais Informação

Instalação manual do ficheiro de correcção

  1. Saia de quaisquer aplicações ou serviços que utilizem o controlador ODBC para SQL Server, SQLSRV32.dll. Isto pode incluir Internet Information Server (IIS), Microsoft Transaction Server (MTS) e quaisquer aplicações de ODBC, Microsoft ActiveX Data Objects (ADO) ou OLE DB.
  2. Transfira a correcção para um directório temporário.
  3. Localize e mude o nome de versões actuais dos ficheiros Sqlsrv32.dll e Odbcbcp.dll, que deverão estar na pasta \Winnt\System32 em computadores com Microsoft Windows NT e na pasta \Windows\System em computadores com o Microsoft Windows 95 e Microsoft Windows 98.
  4. Copie os ficheiros de correcção para a mesma localização e reinicie os serviços e aplicações.

Passos para reproduzir o comportamento

  1. Copie o código no passo 2 para uma aplicação de consola do Microsoft Visual C++ e, em seguida, compilar o código. Por favor note que poderá ter alterar o nome da origem de dados, o id de utilizador e palavra-passe.
  2. Executar o código e tenha em atenção que ocorre um erro quando o valor de data/hora como SQL_C_TIMESTAMP de ligação e que um valor de hora inválido é devolvido quando o valor de data/hora como SQL_C_CHAR do enlace.
    #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
  • Controlador Microsoft ODBC 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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes 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/ )