代码之家  ›  专栏  ›  技术社区  ›  ConcernedOfTunbridgeWells

sqflt8、sqlmmoney和其他本机SQL数据类型的二进制存储格式是什么?

  •  7
  • ConcernedOfTunbridgeWells  · 技术社区  · 15 年前

    根据文档,可以使用以本机SQL Server数据格式格式化的bcp导入或导出本机(二进制)数据。例如sqlflt8、sqlflt4、sqlmoney或sqlnumeric。

    是否有人知道各种类型的数据格式是什么,或者在哪里可以找到指定这些格式的文档?例如,sqlflt8是以IEEE双精度数字还是其他格式存储的?

    编辑: 根据答案 kevchadders Andrew 我有点顿悟,在google上搜索一下define和typedef,看看是否可以找到带有定义的C头文件。这是一个文件 odbcdss.h ; answer 我在下面发布了一些从文件中提取的内容,这看起来很有希望。

    3 回复  |  直到 15 年前
        1
  •  4
  •   Andrew    15 年前

    我不确定这个理论是否成立,但是通过一些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 
    

    输出:0x00000000001E208

    也就是说,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 
    

    输出:0xfffffffffe1df8

    所以它看起来像是一个有符号的8字节数字,因为它刚刚从ff…等中去掉了这个数字。快速检查-0.0001会按预期给出所有的0xfff…fff,而-0.0002会按预期给出0xff…ffe。

    我不确定这是否适用于BCP,但作为一种内部存储格式,我猜测一个有符号的8字节整数,它假定有4个小数点。

        2
  •  5
  •   ConcernedOfTunbridgeWells    15 年前

    在google上进一步搜索define和typedef以及数据类型,找到了这个头文件。( odbcss.h 链接 here. . 第一行定义了与SQL数据类型的名称直接对应的magic常量。下面的代码段有一些typefs和struct定义,以便为这些类型提供外观合理的数据格式。

    看起来这些可能是相关的格式定义。

    相关片段包括:

    // 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
    
        3
  •  1
  •   kevchadders    15 年前

    问得好。

    网上好像不太了解这个,但我发现了这个 Native File Storage Types (下一个表)显示每个本机文件存储类型以及在相应的主机文件数据类型中记录的内容。

    例如 浮标=SqLFLT8
    Real= SqLFLT4
    货币=sqlmoney
    数字=sqlnumeric

    如果你已经看到这个名单,请道歉。