与this question相同,SQL Server
中与以下Postgres
语句等效的是什么?
select encode(some_field, 'escape') from only some_table
答案 0 :(得分:1)
如果您需要此功能,则将由您来实现。假设您只需要escape
变体,则可以尝试将其实现为T-SQL UDF。但是,将字符串分开,逐个字符地工作并建立新字符串并不是T-SQL的强项。您将看到一个WHILE
循环来计算输入字节长度的长度,SUBSTRING
来提取单个字节,而CHAR
来直接转换不包含字节的字节需要八进制编码。 1
如果您打算开始这条路线(特别是如果您想支持其他格式),我将考虑使用CLR support in SQL Server以.NET语言创建该功能(通常首选C#),然后在此使用更丰富的字符串操作功能。
以上两种情况均假设您真正想要的是复制escape
的{{1}}格式。如果您只想“获取此二进制数据并给我一个安全的字符串来表示它”,只需使用CONVERT
即可对二进制十六进制进行编码。
1 这是我的尝试。我建议您在生气之前使用很多进行测试和调整:
encode
答案 1 :(得分:1)
您已经被告知,SQL-Server并不是解决此类问题的最佳方法。
避免此类问题的最重要建议是:使用适当的数据类型存储您的值。按照最佳做法运行将二进制数据存储为十六进制字符串。但是有一些解决方法:
我使用从链接的问题中提取的十六进制字符串:
DECLARE @str VARCHAR(100)='0x61736461640061736461736400';
-在这里,我使用动态创建的SQL将HEX字符串作为实际二进制文件获取:
DECLARE @convBin VARBINARY(MAX);
DECLARE @cmd NVARCHAR(MAX)=N'SELECT @bin=' + @str;
EXEC sp_executeSql @cmd
,N'@bin VARBINARY(MAX) OUTPUT'
,@bin=@convBin OUTPUT;
-此真实二进制文件可以转换为VARCHAR(MAX)
。
-请注意,在这种情况下,输入包含00
,因为这是一个数组。
-可以在00
处拆分输入,但这已经很远了...
SELECT @convBin AS HexStringAsRealBinary
,CAST(@convBin AS VARCHAR(MAX)) AS CastedToString; --You will see the first "asda" only
-如果您的HEX字符串不超过10个字节,则存在未记录的函数:
-您会看到,最后一个AA
被切掉了,而较短的字符串将用零填充。
SELECT sys.fn_cdc_hexstrtobin('0x00112233445566778899AA')
SELECT CAST(sys.fn_cdc_hexstrtobin(@str) AS VARCHAR(100));
以下递归CTE将逐字符读取十六进制字符串。
此外,在这种情况下,它将对结果进行分组并返回两行。
此解决方案非常针对给定的输入。
DECLARE @str VARCHAR(100)='0x61736461640061736461736400';
WITH recCTE AS
(
SELECT 1 AS position
,1 AS GroupingKey
,SUBSTRING(@str,3,2) AS HEXCode
,CHAR(SUBSTRING(sys.fn_cdc_hexstrtobin('0x' + SUBSTRING(@str,3,2)),1,1)) AS TheLetter
UNION ALL
SELECT r.position+1
,r.GroupingKey + CASE WHEN SUBSTRING(@str,2+(r.position)*2+1,2)='00' THEN 1 ELSE 0 END
,SUBSTRING(@str,2+(r.position)*2+1,2)
,CHAR(SUBSTRING(sys.fn_cdc_hexstrtobin('0x' + SUBSTRING(@str,2+(r.position)*2+1,2)),1,1)) AS TheLetter
FROM recCTE r
WHERE position<LEN(@str)/2
)
SELECT r.GroupingKey
,(
SELECT x.TheLetter AS [*]
FROM recCTE x
WHERE x.GroupingKey=r.GroupingKey
AND x.HEXCode<>'00'
AND LEN(x.HEXCode)>0
ORDER BY x.position
FOR XML PATH(''),TYPE
).value('.','varchar(max)')
FROM recCTE r
GROUP BY r.GroupingKey;
结果
1 asdad
2 asdasd
提示:从SQL Server 2017 there is STRING_AGG()
开始,这将减少最终的SELECT
...