在尝试为this问题构建示例代码时,我遇到了CONTEXT_INFO()
的问题。
我正在做的是将int转换为varbinary(128),以便将其传递给SET CONTEXT_INFO
。我可以在执行SET之前将varbinary转换回int,但在I SET然后GET之后,即使varbinary值明显不为零,CONVERT也总是返回零。
Binary不是我的强项,所以我可能会错过一些简单的东西。
SET NOCOUNT ON
USE tempdb
GO
DECLARE @number int
DECLARE @ContextInfo varbinary(128)
SET @number = 16777216
SET @ContextInfo = CONVERT(varbinary(128), @number)
SELECT @number AS [@number]
SELECT @ContextInfo AS [@ContextInfo]
SELECT CONVERT(int, @ContextInfo) AS [CONVERT(int, @ContextInfo)]
SET CONTEXT_INFO @ContextInfo
GO
SELECT CONTEXT_INFO() AS [CONTEXT_INFO()]
SELECT CONVERT(int, CONTEXT_INFO()) AS [CONVERT(int, CONTEXT_INFO()) (Zero)]
GO
DECLARE @ContextInfo varbinary(128)
SET @ContextInfo = CONTEXT_INFO()
SELECT @ContextInfo AS [@ContextInfo]
SELECT CONVERT(int, @ContextInfo) AS [CONVERT(int, @ContextInfo) (Zero)]
GO
@number
-----------
16777216
@ContextInfo
-----------------------------------
0x01000000
CONVERT(int, @ContextInfo)
--------------------------
16777216
CONTEXT_INFO()
-----------------------------------
0x0100000000000000[... more zeroes]
CONVERT(int, CONTEXT_INFO()) (Zero)
-----------------------------------
0
@ContextInfo
-----------------------------------
0x0100000000000000[... more zeroes]
CONVERT(int, @ContextInfo) (Zero)
-----------------------------------
0
我是否尝试直接从CONTEXT_INFO()
转换或将CONTEXT_INFO()
写入变量,CONVERT
的结果为零。
编辑:修正了链接文字
此示例显示转换为varbinary(128)的int如何在没有问题的情况下转换回来,但是CONTEXT_INFO()无法进行转换。
(这是与Andomar的持续对话。)
DECLARE @int int
DECLARE @varBin128 varbinary(128)
SET @int = 1
SET @varBin128 = CONVERT(varbinary(128), @int)
SET CONTEXT_INFO @varBin128
SELECT CONVERT(int, @varBin128) AS [Convert @varBin128)]
SELECT CONVERT(int, CONTEXT_INFO()) AS [Convert once]
SELECT CONVERT(int, CONVERT(varbinary(4), CONTEXT_INFO())) AS [Convert twice]
Convert @varBin128)
-------------------
1
Convert once
------------
0
Convert twice
-------------
1
答案 0 :(得分:12)
varbinary(128)是128字节的内存块。 int是4字节的内存块。所以你可以像这样恢复int:
select convert(int,convert(varbinary(4),CONTEXT_INFO()))
varbinary中的var表示实际长度不同,括号中的数字仅指定最大大小。所以这个SELECT语句显示一个4字节的varbinary:
select convert(varbinary(128), 1)
但是当你将CONTEXT_INFO()转换为varbinary(128)时,你真的得到一个128字节的varbinary。这个例子是一个很好的演示:
set context_info 1
select convert(int,convert(varbinary(5),context_info()))
这将打印256;整数1的最后3个字节,附加0字节。
答案 1 :(得分:3)
我就是这样做的。 SUBSTRING适用于二进制,因此我们不需要任何中间转换(到varbinary(4)):
SET CONTEXT_INFO 12345
SELECT
CONTEXT_INFO(),
CAST(CONTEXT_INFO() AS int), --zero
/*CAST(LEFT(CONTEXT_INFO(), 4) AS int),*/ --fails
CAST(SUBSTRING(CONTEXT_INFO(), 1, 4) AS int) --works
注意:LEFT对二进制文件无法正常运行,但失败并出现转换错误
答案 2 :(得分:3)
答案似乎是Andomar和gbn的建议以及我的一位同事的推荐。
如果使用二进制(128)而不是varbinary(128),一切都会更简单。
--<< ====================================================
--<< varbinary
--<< ====================================================
DECLARE @varbin128 varbinary(128)
SET @varbin128 = CONVERT(varbinary(128), 12345)
SET CONTEXT_INFO @varbin128
SELECT
@varbin128 AS [@varbin128],
CONTEXT_INFO() AS [CONTEXT_INFO()],
CONVERT(int, @varbin128) AS [Convert (@varbin128)],
CONVERT(int, CONTEXT_INFO()) AS [Convert (CONTEXT_INFO())],
CONVERT(int, CONVERT(varbinary(4), CONTEXT_INFO())) AS [Convert(x2) (CONTEXT_INFO())]
--<< ====================================================
--<< binary
--<< ====================================================
DECLARE @bin128 binary(128)
SET @bin128 = CONVERT(binary(128), 12345)
SET CONTEXT_INFO @bin128
SELECT
@bin128 AS [@bin128],
CONTEXT_INFO() AS [CONTEXT_INFO()],
CONVERT(int, @bin128) AS [Convert (@bin128)],
CONVERT(int, CONTEXT_INFO()) AS [Convert (CONTEXT_INFO())],
CONVERT(int, CONVERT(binary(4), CONTEXT_INFO())) AS [Convert(x2) (CONTEXT_INFO())]
@varbin128 CONTEXT_INFO() Convert (@varbin128) Convert (CONTEXT_INFO()) Convert(x2) (CONTEXT_INFO())
---------- ---------------- -------------------- ------------------------ ----------------------------
0x00003039 0x00003039000... 12345 0 12345
@bin128 CONTEXT_INFO() Convert (@bin128) Convert (CONTEXT_INFO()) Convert(x2) (CONTEXT_INFO())
--------------- --------------- ----------------- ------------------------ ----------------------------
0x000...0003039 0x000...0003039 12345 12345 0
因此,如果传入varbinary(128)值,是使转换工作的方法,但它需要双CONVERT。如果传入二进制(128)值,则只需要一个CONVERT。