2011-12-11 64 views
8

我我在一個SQL Server表long值保存爲varbinary(max)SQL服務器VARBINARY BIGINT是不同的

var savedValue = BitConverter.GetBytes(longValue); 

現在我需要在T-SQL查詢值繼續工作,但是當我試圖獲得價值:

select cast(Value as bigint) from dbo.MyValues 

它返回不同的數值。例如,如果我在.NET中保存了-8588797048854775808,在T-SQL中我得到33802181122903688

請告訴我有什麼問題?有問題的解決方案嗎?

+3

你爲什麼首先保存一個64位整數作爲varbinary? – BrokenGlass

+0

通常情況下,您將在C#中將'long'作爲'bigint'存儲在SQL Server中。你有沒有特別的理由試圖將'long'存儲爲'varbinary'? – rsbarro

+0

因爲該數據庫字段不僅包含int64類型的值。 – Maybe

回答

11

varbinarybigint(和後面)的鑄造使用網絡字節順序(big-endian)。 BitConverter使用它運行的機器的endian-ness(x86和x64的little-endian)。

因此BitConverter.GetBytes上-8588797048854775808(0x88CE7696E7167800)運行爲{0x00,0x88,0xE9,0x18,0x69,0x89,0x31,0x77}和cast在{0x00,0x88,0xE9,0x18,0x69,0x89,0x31, 0x77}是0x0088E91869893177 = 38536887891734903.

顯而易見的事情是,首先將64位整數存儲爲64位整數。

如果你真的需要做這種轉換,則:

var savedValue = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(longValue)) 

會掉周圍的字節數,同時還便攜式的,如果一個big-endian的機器上運行它不會交換字節序。

另外,如果你不想使用System.Net命名空間出於某種原因,或者如果你想擴展到比三個IPAddress.HostToNetworkOrder handeles其他類型,使用方法:

var savedValue = BitConverter.GetBytes(longValue); 
if(BitConverter.IsLittleEndian) 
    Array.Reverse(savedValue); 
+0

謝謝你對這個問題的解釋。但我不打算再次將「長」價值保存到「varbinary」。我只需要一些工具來獲得該列中已有的'bigint'值,就像我在'.NET BitConverter.ToInt64'中獲取值一樣。我需要像'Array.Reverse(savedValue)';'只在'TSQL'查詢環境內 – Maybe

+1

Thanx Jon我找到了! 在這種情況下,我需要在'TSQL'中使用'reverse'函數: 'select cast(dave.MyValues' cast cast(reverse(Value)varbinary(max))bigint) – Maybe

+0

無論ASker的DB設計如何,當試圖實現T-SQL HASHBYTES函數的C#等價物時,這個問題幫助我解決了類似的問題。我甚至沒有意識到endian命令可能不同。謝謝! –