Ответы с форумов MSDN

Использование bigint в ODBC

Date: 17.09.2020 4:29:57

По поводу платной поддержки см. здесь: https://social.msdn.microsoft.com/Forums/security/ru-RU/d0bf48b8-4b8a-4fc5-b0f8-953172d269ae/105810771093108710861076107610771088107810821072?forum=msdnfeedbackru

Что касается bigint, тут проблема на нескольких уровнях

1. Нужен ли здесь вообще bigint? "номера сделок и номера ордеров" как бы намекает, что поле будет использоваться не для вычислений, а как идентификатор, поэтому вместо bigint подойдет обычное текстовое поле.

2. bigint не способен хранить все возможные 19-значные числа. Например, 9234556789012345678 уже не входит в диапазон. То есть идея сомнительная.

3. В ODBC bigint действительно не пашет, даже подключиться к базе нельзя. И почему - вопрос интересный. Могу подтвердить, что это не глюк Квика, а воспроизводиться и на минимальной программе на С++. Пробовал запускать следующий код: 

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <sqlext.h>
#include <locale.h>

WCHAR szDSN[] = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\\Test\\Database2016.accdb";
WCHAR query[] = L"SELECT * FROM Table1";

void DisplayError(SQLSMALLINT t, SQLHSTMT h) {
	SQLWCHAR       SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
	SQLINTEGER    NativeError;
	SQLSMALLINT   i, MsgLen;
	SQLRETURN     rc;

	SQLLEN numRecs = 0;
	SQLGetDiagField(t, h, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);

	// Get the status records.
	i = 1;
	while (i <= numRecs && (rc = SQLGetDiagRec(t, h, i, SqlState, &NativeError,
		Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
		wprintf(L"Error %d: %s\n", NativeError, Msg);
		i++;
	}

}

int _tmain(int argc, _TCHAR* argv[])
{
	HENV    hEnv = NULL;
	HDBC    hDbc = NULL;
	HSTMT hStmt = NULL;
	int iConnStrLength2Ptr;
	WCHAR szConnStrOut[256];
	SQLINTEGER rowCount = 0;
	SQLSMALLINT fieldCount = 0, currentField = 0;
	SQLWCHAR buf[128], colName[128];
	SQLINTEGER ret;

	/* ODBC API return status */
	RETCODE rc;

	setlocale(LC_ALL, "Russian");

	/* Allocate an environment handle */
	rc = SQLAllocEnv(&hEnv);
	/* Allocate a connection handle */
	rc = SQLAllocConnect(hEnv, &hDbc);

	/* Connect to the database */
	rc = SQLDriverConnect(hDbc, NULL, (WCHAR*)szDSN,
		SQL_NTS, (WCHAR*)szConnStrOut,
		255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);

	if (SQL_SUCCEEDED(rc))
	{
		wprintf(L"Successfully connected to database. Data source name: \n  %s\n",
			szConnStrOut);

		/* Prepare SQL query */
		wprintf(L"SQL query:\n  %s\n", query);

		rc = SQLAllocStmt(hDbc, &hStmt);
		rc = SQLPrepare(hStmt, (SQLWCHAR*)query, SQL_NTS);

		/* Excecute the query */
		rc = SQLExecute(hStmt);
		if (SQL_SUCCEEDED(rc))
		{
			wprintf(L"\n- Columns -\n");

			SQLNumResultCols(hStmt, &fieldCount);
			if (fieldCount > 0)
			{
				for (currentField = 1; currentField <= fieldCount; currentField++)
				{
					SQLDescribeCol(hStmt, currentField,
						colName, sizeof(colName), 0, 0, 0, 0, 0);
					wprintf(L"%d: %s\n", (int)currentField, colName);
				}
				wprintf(L"\n");

				/* Loop through the rows in the result set */

				rc = SQLFetch(hStmt);
				while (SQL_SUCCEEDED(rc))
				{
					wprintf(L"- Record #%d -\n", (int)rowCount);

					for (currentField = 1; currentField <= fieldCount; currentField++)
					{
						rc = SQLGetData(hStmt, currentField, SQL_C_WCHAR, buf, sizeof(buf), &ret);

						if (SQL_SUCCEEDED(rc) == FALSE) {
							wprintf(L"%d: SQLGetData failed\n", (int)currentField);
							continue;
						}

						if (ret <= 0) {
							wprintf(L"%d: (no data)\n", (int)currentField);
							continue;
						}

						wprintf(L"%d: %s\n", (int)currentField, buf);
					}

					wprintf(L"\n");
					rc = SQLFetch(hStmt);
					rowCount++;
				};

				rc = SQLFreeStmt(hStmt, SQL_DROP);

			}
			else
			{
				wprintf(L"Error: Number of fields in the result set is 0.\n");
			}

		}
		else {
			wprintf(L"SQL Failed\n");
			DisplayError(SQL_HANDLE_STMT, hStmt);
		}
	}
	else
	{
		wprintf(L"Couldn't connect to %s\n", szDSN);
		DisplayError(SQL_HANDLE_DBC, hDbc);
	}

	/* Disconnect and free up allocated handles */
	SQLDisconnect(hDbc);
	SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
	SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

	getchar();
	return 0;
}

Результат:

Couldn't connect to Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\Test\Database2016.accdb
Error 63: [Microsoft][ODBC Microsoft Access Driver]General error Unable to open registry key Temporary (volatile) Ace DSN for process 0x26bc Thread 0xbb0 DBC 0x11a7a2c                                                              Jet'.
Error 63: [Microsoft][ODBC Microsoft Access Driver]General error Unable to open registry key Temporary (volatile) Ace DSN for process 0x26bc Thread 0xbb0 DBC 0x11a7a2c                                                              Jet'.
Error -1073: [Microsoft][ODBC Microsoft Access Driver] The database you are trying to open requires a newer version of Microsoft Access.

Можете эти данные скинуть в платную поддержку, если будете обращаться.

Стоит Access Database Engine 2016 (правда у меня 32-битный). Более новой версии не нашел. Ну то есть, Access 2019 то можно поставить, но драйвер ODBC то все равно ставиться отдельно (или нет)? Есть у кого купленный Office 2019?


Автор: VadimTagil

Главная страница - Список тем - Репозиторий на GitHub