sql - 如何从 SQL Server 中的 VARCHAR() 中删除尾随的 CHAR(0)?

标签 sql sql-server xml

在 Microsoft SQL Server 中,我试图通过将 varbinary() 存储到上下文信息来将 varchar() 字符串传递给触发器。

通过 CONTEXT_INFO 本身传递数据不是问题。

我的问题是,我必须将 varchar() 转换为 varbinary() 才能将数据传递给上下文信息,然后再转换回varchar() 产生尾随 CHAR(0) 字符,我无法再正确处理它。

我试图找到 CHAR(0) 的第一个索引以子串到新的正确字符串,但没有成功。其他内置函数也无法正确处理 CHAR(0) 字符。

但是:

  • LEN() => 总是返回 128,
  • CHARINDEX() => 没有找到 CHAR(0),
  • RTRIM() => 不修剪不可打印的 CHAR(0) 字符,
  • REPLACE() => 不替换 CHAR(0),
  • 执行异常:

    SELECT * FROM (SELECT (@textbin) AS [blabla]) AS [result] FOR XML
    

特别是我需要传递的字符串,作为纯文本,没有尾随空格/CHAR(0) 将字符串放入 xml。

PS.: xml 中的 BINARY BASE64 表示不是我可以使用的选项!

这里是一个测试SQL脚本

DECLARE @text VARCHAR(128)
DECLARE @bintext BINARY(128)
DECLARE @textbin VARCHAR(128)

SET @text = 'test'
--SET @text = 'test' + CHAR(0)
--SET @text = 'test' + CHAR(0) + CHAR(1)
SET @bintext = CONVERT(BINARY(128), @text)
SET @textbin = CONVERT(VARCHAR(128), @bintext)

SET CONTEXT_INFO @bintext
SET @textbin = CAST(CONTEXT_INFO() AS VARCHAR(128))

SELECT
    @text AS [content], LEN(@text) AS [len], DATALENGTH(@text) AS [datalength]
    , REVERSE(@text) AS [reverse]
    , LEN(RTRIM(@text)) AS [len_rtrim]
    , CHARINDEX(CHAR(0), @text) AS [charindex]
    , (SELECT * FROM (SELECT @text AS [text]) AS [result] FOR XML AUTO, BINARY BASE64) AS [xml]
SELECT
    @bintext AS [content], LEN(@bintext) AS [len], DATALENGTH(@bintext) AS [datalength]
    , REVERSE(@bintext) AS [reverse]
    , CHARINDEX(CHAR(0), @bintext) AS [charindex]
    , (SELECT * FROM (SELECT @bintext AS [bintext]) AS [result] FOR XML AUTO, BINARY BASE64) AS [xml]
SELECT
    @textbin AS [content], LEN(@textbin) AS [len], DATALENGTH(@textbin) AS [datalength]
    , REVERSE(@textbin) AS [reverse]
    , LEN(LTRIM(@textbin)) AS [len_rtrim]
    , CHARINDEX(CHAR(0), @textbin) AS [charindex]
    , (SELECT * FROM (SELECT REPLACE(@textbin, CHAR(0), '?') AS [textbin]) AS [result] FOR XML AUTO, BINARY BASE64) AS [xml]

IF @textbin = @text
    SELECT '(@textbin = @text) => TRUE' AS [if]
ELSE
    SELECT '(@textbin = @text) => FALSE' AS [if]

IF @textbin = 'test'
    SELECT '(@textbin = ''test'') => TRUE' AS [if]
ELSE
    SELECT '(@textbin = ''test'') => FALSE' AS [if]

IF @textbin = 'test' + CHAR(0) + CHAR(1)
    SELECT '(@textbin = ''test'' + CHAR(0) + CHAR(1)) => TRUE' AS [if]
ELSE
    SELECT '(@textbin = ''test'' + CHAR(0) + CHAR(1)) => FALSE' AS [if]

IF @textbin LIKE 'test'
    SELECT '(@textbin LIKE ''test'') => TRUE' AS [if]
ELSE
    SELECT '(@textbin LIKE ''test'') => FALSE' AS [if]

IF @textbin LIKE 'test%'
    SELECT '(@textbin LIKE ''test%'') => TRUE' AS [if]
ELSE
    SELECT '(@textbin LIKE ''test%'') => FALSE' AS [if]

SELECT * FROM (SELECT (@textbin) AS [context_info]) AS [test] FOR XML AUTO, BINARY BASE64
-- SELECT * FROM (SELECT (@textbin) AS [context_info]) AS [test] FOR XML AUTO, TYPE, BINARY BASE64
-- SELECT * FROM (SELECT (@textbin) AS [context_info]) AS [test] FOR XML AUTO

-- relatet to "@textbin"
-- LEN() => returns always 128,
-- CHARINDEX() => does not find CHAR(0),
-- RTRIM() => does not trim non printable CHAR(0) chars,
-- REPLACE() => does not replace CHAR(0),
-- exception on executing: SELECT * FROM (SELECT (@textbin) AS [context_info]) AS [test] FOR XML AUTO, TYPE, BINARY BASE64
-- exception on executing: SELECT * FROM (SELECT (@textbin) AS [context_info]) AS [test] FOR XML AUTO

最佳答案

正如 Darka 所注意到的,

这是一个重复的问题: What is the Null Character literal in TSQL?

...谢谢你给我看。

此更改修复了我的代码:

SET @textbin = REPLACE(CAST(CAST(CONTEXT_INFO() AS VARCHAR(128)) COLLATE SQL_Latin1_General_CP1_CI_AS AS VARCHAR(128)), CHAR(0), '')

关于sql - 如何从 SQL Server 中的 VARCHAR() 中删除尾随的 CHAR(0)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21282545/

相关文章:

java - 使用 SAX 解析器捕获 XML 中的混合内容

SQL 查询列出员工未工作的城市

java - com.microsoft.sqlserver.jdbc.SQLServerException : Login failed for user 'sa'

sql - 内部连接顺序和位置对性能有影响吗

sql - 工作 SQL Server 2005 查询优化

javascript - 使用 XML 在 Google map 中创建多个标记

java - 生成递归目录搜索的 XML 映射

sql - 合并雪花 - 不匹配、更新和插入

mysql - 如何在 MySQL 表中选择特定范围的值?

sql - 替换 SQL 中的 JSON 格式字符串