代码之家  ›  专栏  ›  技术社区  ›  Rob Garrison

context_info()和convert

  •  6
  • Rob Garrison  · 技术社区  · 15 年前

    尝试为创建示例代码 this 问题,我遇到了一个问题 CONTEXT_INFO() .

    我要做的是将int转换为varbinary(128),这样我可以将它传递给 SET CONTEXT_INFO . 我可以在设置之前将varbinary转换回int,但是在设置之后,然后得到,convert总是返回零,即使varbinary值显然不是零。

    二进制不是我的强项,所以我可能缺少一些简单的东西。

    代码

    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
    

    是否尝试直接从 上下文信息() 或写 上下文信息() 对于一个变量, 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 回复  |  直到 15 年前
        1
  •  12
  •   Andomar    15 年前

    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字节。

        2
  •  3
  •   gbn    15 年前

    我就是这样做的。 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 无法很好地处理二进制文件,并因转换错误而失败

        3
  •  3
  •   Rob Garrison    15 年前

    答案似乎是来自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)值,则使转换生效的方法,但它需要双重转换。如果传入一个二进制(128)值,则只需要进行一次转换。