CONTEXT_INFO()和CONVERT

时间:2009-10-23 22:19:44

标签: sql sql-server tsql

在尝试为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

3 个答案:

答案 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。