Quais são os formatos de armazenamento binário para SQFLT8, SQLMoney e outros tipos de dados nativos do SQL?

StackOverflow https://stackoverflow.com/questions/2099919

  •  21-09-2019
  •  | 
  •  

Pergunta

De acordo com a documentação, os dados nativos (binários) podem ser importados ou exportados com formatados BCP nos formatos de dados nativos do SQL Server. Exemplos destes são SQLFLT8, SQLFLT4, SQLMONEY ou SQLNUMERIC.

Alguém sabe quais são os formatos de dados para os vários tipos ou onde a documentação especificando esses formatos pode ser encontrada. Por exemplo, um SQLFLT8 é armazenado como um número de precisão dupla IEEE ou em algum outro formato?

Editar: Das respostas por Kevchadders e Andrew Eu tive um pouco de epifania fiz um pouco de Google para #Define e Typedef para ver se conseguia encontrar arquivos de cabeçalho C com definições. Isso surgiu com um arquivo odbcdss.h; a responda Eu publiquei abaixo algumas exaltadas do arquivo, o que parece bastante promissor.

Foi útil?

Solução

Não tenho certeza se a teoria se manterá, mas descobrir o armazenamento interno dos tipos pode ser alcançado usando algum SQL e um pouco de descoberta. Eu fiz isso para o novo DateTime2 / DateTimeOffset no meu blog para obter o formato binário interno, pois estava interessado em ver como eles obtiveram precisão adicional.

Como exemplo de dinheiro

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 

Saída: 0x000000000001E208

Isso é 123400, quando considerado um número decimal, o dinheiro é armazenado em 4 locais decimais, o que indicaria 12.3400 como o valor, revertendo isso em teoria, um valor de apenas 1 em hexadecimal deve ser 0,0001

declare @test money
declare @binaryValue binary(8)
set @binaryvalue = 0x0000000000000001
set @test = convert(money,@binaryvalue)
select @test

Saídas 0,0001

A próxima coisa que eu verificaria são os números negativos,

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 

Saída: 0xffffffffffe1df8

Então, parece que é um número de 8 bytes assinado, pois apenas retira o número do FF ... etc. Uma verificação rápida com -0.0001 fornece todos os 0xfff .... fff conforme o esperado e -0.0002 fornece 0xff .... ffe conforme o esperado.

Se isso vale para o BCP, não tenho certeza, mas como um formato de armazenamento interno, eu adivinharia um número inteiro de 8 bytes assinado que tem 4 locais decimais assumidos.

Outras dicas

Alguns pesquisando mais no Google para #define e typedef em conjunto com os tipos de dados, apareceu este arquivo de cabeçalho (odbcss.h) vinculado aqui.. A primeira linha possui #Defines for Magic Constants que correspondem diretamente aos nomes dos tipos de dados SQL. O snippet inferior possui alguns tipos de letra e definições de estrutura para formatos de dados de aparência sensata para os tipos.

Parece que essas podem ser as definições de formato relevantes.

Os trechos relevantes são:

// 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

Boa pergunta.

Não parece muito na web sobre isso, mas eu achei isso Tipos de armazenamento de arquivos nativos (Segunda tabela para baixo), que mostra cada tipo de armazenamento de arquivo nativo e o que é gravado no tipo de dados do arquivo de host correspondente.

por exemplo, float = sqlflt8
real = sqlflt4
dinheiro = sqlmoney
numérico = sqlnumeric

Desculpas se você já se deparou com esta lista.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top