8

根据文档,可以使用原生 SQL Server 数据格式的 bcp 导入或导出原生(二进制)数据。这些示例包括 SQLFLT8、SQLFLT4、SQLMONEY 或 SQLNUMERIC。

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

编辑:kevchaddersAndrew的回答中,我有一点顿悟,对 #define 和 typedef 进行了一些谷歌搜索,看看是否可以找到带有定义的 C 头文件。这想出了一个文件odbcdss.h;我在下面发布的答案从文件中提取了一些内容,看起来很有希望。

4

3 回答 3

6

一些进一步的谷歌搜索#define 和 typedef 与数据类型一起出现了这个odbcss.h链接到这里的头文件 ()。. 第一行为与 SQL 数据类型名称直接对应的魔术常量提供了#Defines。下面的代码片段有一些 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
于 2010-01-20T10:32:25.510 回答
5

我不确定这个理论是否成立,但是可以使用一些 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 我不确定,但作为一种内部存储格式,我会猜测一个假设有 4 个小数位的有符号 8 字节整数。

于 2010-01-20T09:33:42.043 回答
1

好问题。

在网上似乎没有太多关于此的内容,但我发现了这个Native File Storage Types (Second table down),它显示了每个原生文件存储类型以及它在相应的主机文件数据类型中记录的内容。

例如 float = SQLFLT8
real = SQLFLT4
money = SQLMONEY
numeric = SQLNUMERIC

如果您已经遇到此列表,我们深表歉意。

于 2010-01-20T09:00:49.267 回答