Right Trimming Binary Data in SQL Server

一笑奈何 提交于 2020-01-14 12:43:28

问题


Scenario:

I am inserting a string into a binary field (CONTEXT_INFO) and then later attempting to pull it out and convert it back to a string. When I do, the resulting string has a length of 128 because it has trailing null characters.

Example:

DECLARE @string VARCHAR(128)
DECLARE @binary VARBINARY(128)

SET @string = 'abcdefg'
SET @binary = CONVERT(VARBINARY(128), @string) --0x61626364656667000000...
SET CONTEXT_INFO @binary
SET @binary = CONTEXT_INFO()

-- I would like to change the following line so it trims trailing null chars
SET @string = CONVERT(VARCHAR(128), @binary)

SELECT
    @binary AS [binary],
    DATALENGTH(@binary) AS [binary.Length], --128 as expected
    @string AS [string],
    DATALENGTH(@string) AS [string.Length] --This is 128, but I need it to be 7

Question:

How can I trim the trailing null characters when I convert the binary field to a string?


回答1:


Try this, works on Sql-Server 2008. Here is Sql Fiddle.

Please note that I am assuming that the original string has NOT got Char(0) in it as this could simply replace it even from the original string.

-- I would like to change the following line so it trims trailing null chars
SET @string = CONVERT(VARCHAR(128), @binary)
SET @string = REPLACE(@string, Char(0),'') 



回答2:


Here was my solution. I went this way because of what CONTEXT_INFO makes the value look like (pads to the right).

DECLARE @string VARCHAR(128)
DECLARE @binary VARBINARY(128)

SET @string = 'abcdefg'
SET @string = REPLICATE(CHAR(0),128-LEN(@string))+@string
SET @binary = CONVERT(VARBINARY(128), @string)
SET CONTEXT_INFO @binary
SET @binary = CONTEXT_INFO()

SET @string = CONVERT(VARCHAR(128), REPLACE(@binary,CHAR(0),''))

SELECT
    @binary AS [binary],
    DATALENGTH(@binary) AS [binary.Length],
    @string AS [string],
    DATALENGTH(@string) AS [string.Length]



回答3:


For the record, this will trim the trailing 0x00 and leave the 0x00 in place if they happen in the middle of the data:

cast(substring(CONTEXT_INFO(), 1, len(REPLACE(REPLACE(CONTEXT_INFO(), 0x20, 0x21), 0x00, 0x20))) as varbinary(128))

This gives a result as a varbinary, if you want a string, remove the outer cast

Most of the other solutions either end up removing the 0x00 in the middle, or changing it to a 0x20.




回答4:


Converting from nvarchar(x) to varbinary(x) back to nvarchar(x) will always round-trip correctly. The core issue described here occurs because SELECT CONTEXT_INFO() always returns 128 bytes, regardless of the length of the varbinary source used to set CONTEXT_INFO.

There are two workarounds.

First workaround: starting in SQL Server 2016, sp_set_session_context may be used to set the vastly superior session_context.

Second workaround: context_info can be retrieved from sys.dm_exec_sessions in the way CONTEXT_INFO() should work. This query will return the context_info associated with the current connection:

SELECT context_info FROM sys.dm_exec_sessions WHERE session_id = @@SPID

Here's a comparison of the two retrieval methods in SSMS:

SET CONTEXT_INFO 0x010200340056;
GO

SELECT CONTEXT_INFO(); -- 0x0012003400560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
SELECT context_info FROM sys.dm_exec_sessions WHERE session_id = @@SPID; -- 0x001200340056

SET CONTEXT_INFO 0x;
GO

SELECT CONTEXT_INFO(); -- NULL
SELECT context_info FROM sys.dm_exec_sessions WHERE session_id = @@SPID; -- 0x

Caveat: Setting CONTEXT_INFO should be executed in a batch separate from retrieving context_info via sys.dm_exec_sessions (as seen above via the SSMS batch-separator GO).



来源:https://stackoverflow.com/questions/14162672/right-trimming-binary-data-in-sql-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!