Каковы двоичные форматы хранения для sqflt8, sqlmoney и других типов данных SQL?
-
21-09-2019 - |
Вопрос
Согласно документации, собственные (двоичные) данные можно импортировать или экспортировать с помощью bcp, отформатированного в собственных форматах данных SQL Server.Примерами являются SQLFLT8, SQLFLT4, SQLMONEY или SQLNUMERIC.
Кто-нибудь знает, каковы форматы данных для различных типов или где можно найти документацию, определяющую эти форматы.Например, SQLFLT8 хранится как число двойной точности IEEE или в каком-то другом формате?
Редактировать: Из ответов автора Кевчаддеры и Андрей У меня было небольшое прозрение: я немного погуглил #define и typedef, чтобы посмотреть, смогу ли я найти заголовочные файлы C с определениями.Вот появился файл odbcdss.h
;тот отвечать Ниже я разместил некоторые выдержки из файла, которые выглядят весьма многообещающе.
Решение
Я не уверен, что теория верна, но выяснить внутреннее хранилище типов можно, используя немного SQL и немного разобравшись.Я сделал это для нового datetime2/datetimeoffset в своем блоге, чтобы специально получить внутренний двоичный формат, поскольку мне было интересно посмотреть, как они получили дополнительную точность.
В качестве примера для денег
declare @test money
set @test = 12.34
select @test -- shows 12.34 as expected
declare @binaryValue binary(8)
set @binaryvalue = convert(binary(8),@test)
select @binaryvalue
Выход :0x000000000001E208
Это 123400, если рассматривать его как десятичное число, деньги хранятся с точностью до 4 знаков после запятой, так что в качестве значения будет указано 12,3400, теоретически значение всего 1 в шестнадцатеричном формате должно быть 0,0001.
declare @test money
declare @binaryValue binary(8)
set @binaryvalue = 0x0000000000000001
set @test = convert(money,@binaryvalue)
select @test
Выходы 0,0001
Следующее, что я хотел бы проверить, это отрицательные числа,
declare @test money
set @test = -12.34
select @test -- shows -12.34 as expected
declare @binaryValue binary(8)
set @binaryvalue = convert(binary(8),@test)
select @binaryvalue
Выход :0xFFFFFFFFFFFE1DF8
Похоже, это 8-байтовое число со знаком, поскольку оно только что забрало число из FF... и т. д.Быстрая проверка с -0,0001 выдает все 0xFFF....FFF, как и ожидалось, а -0,0002 дает 0xFF....FFE, как и ожидалось.
Я не уверен, справедливо ли это для BCP, но в качестве внутреннего формата хранения я бы предположил 8-байтовое целое число со знаком, которое имеет предполагаемые 4 десятичных знака.
Другие советы
Дальнейший поиск в Google #define и typedef в сочетании с типами данных выявил этот заголовочный файл (odbcss.h
) связан здесь..В первой строке есть #Defines для магических констант, которые напрямую соответствуют именам типов данных SQL.В нижнем фрагменте есть некоторые определения типов и структур для разумного формата данных для типов.
Похоже, это могут быть соответствующие определения формата.
Соответствующие фрагменты:
// SQL Server Data Type Tokens. Returned by SQLColAttributes/SQL_CA_SS_COLUMN_SSTYPE.
#define SQLTEXT 0x23
#define SQLVARBINARY 0x25
#define SQLINTN 0x26
#define SQLVARCHAR 0x27
#define SQLBINARY 0x2d
#define SQLIMAGE 0x22
#define SQLCHARACTER 0x2f
#define SQLINT1 0x30
#define SQLBIT 0x32
#define SQLINT2 0x34
#define SQLINT4 0x38
#define SQLMONEY 0x3c
#define SQLDATETIME 0x3d
#define SQLFLT8 0x3e
#define SQLFLTN 0x6d
#define SQLMONEYN 0x6e
#define SQLDATETIMN 0x6f
#define SQLFLT4 0x3b
#define SQLMONEY4 0x7a
#define SQLDATETIM4 0x3a
#define SQLDECIMAL 0x37
#define SQLDECIMALN 0x6a
#define SQLNUMERIC 0x3f
#define SQLNUMERICN 0x6c
[ . . . ]
typedef char DBCHAR;
typedef unsigned char DBBINARY;
typedef unsigned char DBTINYINT;
typedef short DBSMALLINT;
typedef unsigned short DBUSMALLINT;
typedef long DBINT;
typedef double DBFLT8;
typedef unsigned char DBBIT;
typedef unsigned char DBBOOL;
typedef float DBFLT4;
typedef DBFLT4 DBREAL;
typedef UINT DBUBOOL;
typedef struct dbvarychar
{
DBSMALLINT len;
DBCHAR str[DBMAXCHAR];
} DBVARYCHAR;
typedef struct dbvarybin
{
DBSMALLINT len;
BYTE array[DBMAXCHAR];
} DBVARYBIN;
typedef struct dbmoney
{ // Internal representation of MONEY data type
LONG mnyhigh; // Money value *10,000 (High 32 bits/signed)
ULONG mnylow; // Money value *10,000 (Low 32 bits/unsigned)
} DBMONEY;
typedef struct dbdatetime
{ // Internal representation of DATETIME data type
LONG dtdays; // No of days since Jan-1-1900 (maybe negative)
ULONG dttime; // No. of 300 hundredths of a second since midnight
} DBDATETIME;
typedef struct dbdatetime4
{ // Internal representation of SMALLDATETIME data type
USHORT numdays; // No of days since Jan-1-1900
USHORT nummins; // No. of minutes since midnight
} DBDATETIM4;
typedef LONG DBMONEY4; // Internal representation of SMALLMONEY data type
// Money value *10,000
#define DBNUM_PREC_TYPE BYTE
#define DBNUM_SCALE_TYPE BYTE
#define DBNUM_VAL_TYPE BYTE
typedef const LPBYTE LPCBYTE;
typedef DBINT * LPDBINT;
#if (ODBCVER < 0x0300)
#define MAXNUMERICLEN 16
typedef struct dbnumeric
{ // Internal representation of NUMERIC data type
DBNUM_PREC_TYPE precision; // Precision
DBNUM_SCALE_TYPE scale; // Scale
BYTE sign; // Sign (1 if positive, 0 if negative)
DBNUM_VAL_TYPE val[MAXNUMERICLEN]; // Value
} DBNUMERIC;
typedef DBNUMERIC DBDECIMAL;// Internal representation of DECIMAL data type
#else // Use ODBC 3.0 definitions since same as DBLib
#define MAXNUMERICLEN SQL_MAX_NUMERIC_LEN
typedef SQL_NUMERIC_STRUCT DBNUMERIC;
typedef SQL_NUMERIC_STRUCT DBDECIMAL;
#endif
#endif // MAXNUMERICLEN
Хороший вопрос.
Кажется, в Интернете об этом не так много, но я нашел это Собственные типы хранилищ файлов (Вторая таблица вниз), в которой показан каждый собственный тип хранилища файлов и то, что он записан в соответствующем типе данных хост-файла.
напримерс плавающей запятой = SQLFLT8
реальный = SQLFLT4
деньги = SQLMONEY
числовой = SQLNUMERIC
Приносим извинения, если вы уже сталкивались с этим списком.