Каковы двоичные форматы хранения для sqflt8, sqlmoney и других собственных типов данных SQL? - PullRequest
7 голосов
/ 20 января 2010

Согласно документации, собственные (двоичные) данные можно импортировать или экспортировать с помощью bcp, отформатированного в собственных форматах данных SQL Server.Примерами этого являются SQLFLT8, SQLFLT4, SQLMONEY или SQLNUMERIC.

Кто-нибудь знает, какие есть форматы данных для различных типов, или где может быть найдена документация, определяющая эти форматы.Например, SQLFLT8 хранится как число двойной точности IEEE или в каком-либо другом формате?

Редактировать: Из ответов kevchadders и Andrew У меня было небольшое прозрение, я немного погуглил #define и typedef, чтобы посмотреть, смогу ли я найти заголовочные файлы C с определениями.Это пришло с файлом odbcdss.h; ответ , который я разместил ниже, имеет некоторые недостатки из файла, который выглядит довольно многообещающе.

Ответы [ 3 ]

5 голосов
/ 20 января 2010

Дальнейшее поиск в 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
4 голосов
/ 20 января 2010

Я не уверен, верна ли теория, но выяснить внутреннее хранилище типов можно, используя некоторый 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 десятичных знака.

1 голос
/ 20 января 2010

Хороший вопрос.

Не так много в Интернете об этом, но я нашел это Собственные типы хранилищ файлов (Вторая таблица внизу), которая показывает каждый собственный тип хранилища файлов и чтоон записывается в соответствующий тип данных файла хоста.

например, float = SQLFLT8
real = SQLFLT4
money = SQLMONEY
numeric = SQLNUMERIC

Извинения, если вы уже сделалинаткнуться на этот список.

...