【发布时间】:2014-01-22 12:08:23
【问题描述】:
在 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
【问题讨论】:
-
尝试使用 DATALENGTH 获取字段长度
-
我觉得重复的可以看这里stackoverflow.com/q/2828333/1692632
-
如果您认为需要将数据传递给触发器,那么设计中就会发生一些非常奇怪的事情。您正在使用触发器,就好像它们是存储过程一样。
-
LEN 和 DATALENGTH 总是返回 128。我需要字符串本身的长度
标签: sql sql-server xml