共用方式為


SSVARIANT 結構

適用於:SQL Server Azure SQL 資料 Azure SQL 受控執行個體 Azure Synapse Analytics Analytics Platform System (PDW)

下載 OLE DB 驅動程式

定義於 msoledbsql.h 中的 SSVARIANT 結構會對應至 OLE DB Driver for SQL Server 中的 DBTYPE_SQLVARIANT 值。

SSVARIANT 是一個區分集合聯集。 根據 vt 成員的值而定,取用者可以判斷要讀取的成員。 vt 值會對應至 SQL Server 資料類型。 因此,SSVARIANT 結構可以保留任何 SQL Server 類型。 如需適用於標準 OLE DB 類型之資料結構的詳細資訊,請參閱類型指示器 \(英文\)。

備註

當 DataTypeCompat==80 時,數個 SSVARIANT 子類型會變成字串。 例如,下列 vt 值在 SSVARIANT 中會顯示為 VT_SS_WVARSTRING:

  • VT_SS_DATETIMEOFFSET

  • VT_SS_DATETIME2

  • VT_SS_TIME2

  • VT_SS_DATE

當 DateTypeCompat == 0 時,這些類型都會以原生形式出現。

如需 SSPROP_INIT_DATATYPECOMPATIBILITY 的詳細資訊,請參閱利用 OLE DB Driver for SQL Server 使用連接字串關鍵字

msoledbsql.h 檔案包含變數存取巨集,可簡化 SSVARIANT 結構中成員類型的取值 (Dereference)。 V_SS_DATETIMEOFFSET 即為一例,可以按照下列方式使用:

memcpy(&V_SS_DATETIMEOFFSET(pssVar).tsoDateTimeOffsetVal, pDTO, cbNative);  
V_SS_DATETIMEOFFSET(pssVar).bScale = bScale;  

如需適用於 SSVARIANT 結構中每個成員的完整存取巨集集合,請參考 msoledbsql.h 檔案。

下表將描述 SSVARIANT 結構的成員:

member OLE DB 類型指標 OLE DB C 資料類型 vt 值 註解
vt SSVARTYPE 指定包含在 SSVARIANT 結構中的值類型。
bTinyIntVal DBTYPE_UI1 BYTE VT_SS_UI1 支援 Tinyint SQL Server 資料類型。
sShortIntVal DBTYPE_I2 SHORT VT_SS_I2 支援 Smallint SQL Server 資料類型。
lIntVal DBTYPE_I4 LONG VT_SS_I4 支援 int SQL Server 資料類型。
llBigIntVal DBTYPE_I8 LARGE_INTEGER VT_SS_I8 支援 Bigint SQL Server 資料類型。
fltRealVal DBTYPE_R4 float VT_SS_R4 支援 real SQL Server 資料類型。
dblFloatVal DBTYPE_R8 double VT_SS_R8 支援 float SQL Server 資料類型。
cyMoneyVal DBTYPE_CY LARGE_INTEGER VT_SS_MONEY VT_SS_SMALLMONEY 支援 moneysmallmoney SQL Server 資料類型。
fBitVal DBTYPE_BOOL VARIANT_BOOL VT_SS_BIT 支援 bit SQL Server 資料類型。
rgbGuidVal DBTYPE_GUID GUID VT_SS_GUID 支援 uniqueidentifier SQL Server 資料類型。
numNumericVal DBTYPE_NUMERIC DB_NUMERIC VT_SS_NUMERIC 支援 numeric SQL Server 資料類型。
dDateVal DBTYPE_DATE DBDATE VT_SS_DATE 支援 date SQL Server 資料類型。
tsDateTimeVal DBTYPE_DBTIMESTAMP DBTIMESTAMP VT_SS_SMALLDATETIME VT_SS_DATETIME VT_SS_DATETIME2 支援 smalldatetimedatetimedatetime2 SQL Server 資料類型。
Time2Val DBTYPE_DBTIME2 DBTIME2 VT_SS_TIME2 支援 time SQL Server 資料類型。

包括下列成員:

tTime2Val (DBTIME2)

bScale (BYTE) 指定 tTime2Val 值的範圍。
DateTimeVal DBTYPE_DBTIMESTAMP DBTIMESTAMP VT_SS_DATETIME2 支援 datetime2 SQL Server 資料類型。

包括下列成員:

tsDataTimeVal (DBTIMESTAMP)

bScale (BYTE) 指定 tsDataTimeVal 值的範圍。
DateTimeOffsetVal DBTYPE_DBTIMESTAMPOFSET DBTIMESTAMPOFFSET VT_SS_DATETIMEOFFSET 支援 datetimeoffset SQL Server 資料類型。

包括下列成員:

tsoDateTimeOffsetVal (DBTIMESTAMPOFFSET)

bScale (BYTE) 指定 tsoDateTimeOffsetVal 值的範圍。
NCharVal 沒有對應的 OLE DB 類型指標。 struct _NCharVal VT_SS_WVARSTRING,

VT_SS_WSTRING
支援 NcharNvarchar SQL Server 資料類型。

包括下列成員:

sActualLength (SHORT) 指定 pwchNCharVal 指向之字串的實際長度。 不包括結尾的零。

sMaxLength (SHORT) 指定 pwchNCharVal 指向之字串的最大長度。

pwchNCharVal (WCHAR *) 指向字串的指標。

rgbReserved (BYTE[5] ) 指定定序資訊。

未使用的成員:dwReservedpwchReserved
CharVal 沒有對應的 OLE DB 類型指標。 struct _CharVal VT_SS_STRING,

VT_SS_VARSTRING
支援 charvarchar SQL Server 資料類型。

包括下列成員:

sActualLength (SHORT) 指定 pchCharVal 指向之字串的實際長度。 不包括結尾的零。

sMaxLength (SHORT) 指定 pchCharVal 指向之字串的最大長度。

pchCharVal (CHAR *) 指向字串的指標。

rgbReserved (BYTE[5] ) 指定定序資訊。

未使用的成員:

dwReservedpwchReserved
BinaryVal 沒有對應的 OLE DB 類型指標。 struct _BinaryVal VT_SS_VARBINARY,

VT_SS_BINARY
支援 binaryvarbinary SQL Server 資料類型。

包括下列成員:

sActualLength (SHORT) 指定 prgbBinaryVal 指向之資料的實際長度。

sMaxLength (SHORT) 指定 prgbBinaryVal 指向之資料的最大長度。

prgbBinaryVal (BYTE *) 指向二進位資料的指標。

未使用的成員:dwReserved
UnknownType 未使用 未使用 未使用 未使用
BLOBType 未使用 未使用 未使用 未使用

已知問題

可能的窄字串資料損毀

在 OLE DB 驅動程式 18.4 版之前,若下列所有條件都成立,則 sql_variant 資料行中的插入可能會導致伺服器上的資料損毀:

  • 用戶端電腦字碼頁不符合資料庫定序字碼頁。
  • 要插入的用戶端緩衝區,包含以用戶端字碼頁編碼的非 ASCII 窄字串字元。
  • 下列任一條件都成立:
    • DBPARAMBINDINFO 結構中的 pwszDataSourceType 欄位,其描述對應至 sql_variant 資料行的參數已設定為 L"DBTYPE_SQLVARIANT"L"DBTYPE_VARIANT"L"sql_variant"。 如需詳細資料,請參閱:ICommandWithParameters::SetParameterInfo

      or

    • 用於插入的參數化 SQL 查詢已準備妥當。

更明確的說,OLE DB 驅動程式不會在插入資料之前,將其翻譯成資料庫定序字碼頁。 然而,此驅動程式錯誤地向伺服器指出,資料庫定序字碼頁中的資料已編碼。 此行為導致資料與其儲存在 sql_variant 欄中的對應字碼頁不相符。

同樣地,在擷取相同的值時,OLE DB 驅動程式不會將字串翻譯成用戶端字碼頁。 然而,由於插入的資料已經在用戶端字碼頁中 (請參閱上面的段落),因此用戶端應用程式可正確地解譯資料。 就算如此,使用其他驅動程式的應用程式,也會以損毀的格式擷取這些值。 會發生損毀是因為其他驅動程式在資料庫定序字碼頁中解譯了字串,並嘗試將其翻譯成用戶端字碼頁。

自 18.4 版起,OLE DB Driver 會在插入之前,將窄字串翻譯成資料庫定序字碼頁。 同樣地,驅動程式也會在擷取時,將資料翻譯回用戶端字碼頁。 因此,依賴上述 Bug 的用戶端應用程式,可能會在擷取使用舊版 OLE DB Driver 插入的資料時遇到問題。 下方復原程序旨在提供解決這些問題的指引。

復原程序

重要

執行下列復原步驟之前,請務必備份現有的資料。

若應用程式在切換至 OLE DB 驅動程式 18.4 版之後,在從 sql_variant 資料行擷取資料時遇到問題,則必須修改損毀的資料,使其定序與儲存資料的資料庫相同。 下列指令碼可用來從 sql_variant 資料行復原單一值。 指令碼是範本,必須加以調整以符合情況。

重要

由於不會儲存資料的原始字碼頁,因此必須告知伺服器初始如何編碼資料。 若要執行這項操作,請在資料庫的內容中執行指令碼,其字碼頁與初始插入資料的用戶端其字碼頁相同。 例如,若從使用字碼頁 932 所設定用戶端插入損毀的資料,則必須在具有日文定序的資料庫內容 (例如 Japanese_XJIS_100_CS_AI) 中執行下列指令碼。

/*
    Description:
        Template that can be used to recover the corrupted value inserted into the sql_variant column.

    Scenario:
        The database is named [YourDatabase] and it contains a table named [YourTable], which contains the corrupted value.
        Schema is named [dbo].
        The corrupted value is stored in a column of type sql_variant named [YourColumn].
        The corrupted value is sql_variant of BaseType char. For details on sql_variant properties, see:
            https://zcusa.951200.xyz/sql/t-sql/functions/sql-variant-property-transact-sql
*/

-- Base type in sql_variant can hold a maximum of 8000 bytes
-- For details see: 
--  https://zcusa.951200.xyz/sql/t-sql/data-types/sql-variant-transact-sql#remarks
DECLARE @bin VARBINARY(8000)

-- In the following lines we convert the sql_variant base type to binary.
-- <FilterExpression>
--      Is a placeholder and must be replaced with an expression that filters a single corrupted value to be recovered.
--      Therefore, the expression must result in a single value being returned only.
SET @bin = (SELECT CAST([YourColumn] AS VARBINARY(8000)) FROM [YourDatabase].[dbo].[YourTable] WHERE <FilterExpression>)

-- In the following lines we store the binary value in char(59) (a fixed-size character data type).
-- IMPORTANT NOTE: 
--      This example assumes the corrupted sql_variant's base type is char(59).
--      You MUST adjust the type (that is, char/varchar) and size to match your scenario exactly.
DECLARE @char CHAR(59)
SET @char = CAST((@bin) AS CHAR(59))
DECLARE @sqlvariant sql_variant

-- The following lines recover the corrupted value by translating the value to the collation of the database.
-- <DBCollation>
--      Must be replaced with the collation (for example, Latin1_General_100_CI_AS_SC_UTF8) of the database holding the data.
SET @sqlvariant = @char collate <DBCollation>

-- Finally, we update the corrupted value with the recovered value.
-- "<FilterExpression>"
--      Is a placeholder and must be replaced with an expression that filters a single corrupted value to be recovered.
--      Therefore, the expression must result in a single value being returned only.
UPDATE [YourDatabase].[dbo].[YourTable] SET [YourColumn] = @sqlvariant WHERE <FilterExpression>

另請參閱

資料類型 (OLE DB)