什么是SQL Server中的encode(<columnname>,'escape')PostgreSQL等效项?

时间:2019-01-04 13:50:23

标签: sql-server string tsql

this question相同,SQL Server中与以下Postgres语句等效的是什么?

select encode(some_field, 'escape') from only some_table

2 个答案:

答案 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 ...