You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server中Uri.EscapeDataString函数表现不符合预期

问题描述

我用.NET Framework 4.8控制台程序测试字符串转义,执行Console.WriteLine(Uri.EscapeDataString("*")),输出符合预期的%2A。
随后在另一个.NET Framework 4.8类库中编写了如下CLR函数:

[SqlFunction(DataAccess = DataAccessKind.None)]
[return: SqlFacet(MaxSize = -1)]
public static SqlString UrlEncode([SqlFacet(MaxSize = -1)] string url)
{
    return new SqlString(Uri.EscapeDataString(url));
}

将该类库作为CLR程序集添加到SQL Server 2022中,并创建对应的SQL函数:

CREATE FUNCTION [dbo].[UrlEncode](@url [nvarchar](max))
RETURNS nvarchar(max)
WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SqlClrFunctions].[Utils].UrlEncode
GO

执行查询select dbo.UrlEncode('*'),结果为*,显然不符合预期。同一函数为何表现不同?

问题分析与解决

这个差异的核心原因是SQL Server的CLR宿主环境对.NET框架的API行为做了调整:

  • 独立控制台程序中,Uri.EscapeDataString严格遵循RFC 3986标准,会将*这类保留字符转义为%2A。
  • 但在SQL Server CLR宿主里,默认启用兼容旧版编码规则的模式,*被视为无需转义的字符,因此直接输出原字符。

解决方式有两种:

  1. 改用HttpUtility.UrlEncode方法
    该方法的编码行为在CLR宿主环境中更稳定,会正确转义*。需要在类库中引用System.Web程序集,修改后的代码如下:

    using System.Web;
    using Microsoft.SqlServer.Server;
    using System.Data.SqlTypes;
    
    public class Utils
    {
        [SqlFunction(DataAccess = DataAccessKind.None)]
        [return: SqlFacet(MaxSize = -1)]
        public static SqlString UrlEncode([SqlFacet(MaxSize = -1)] string url)
        {
            return new SqlString(HttpUtility.UrlEncode(url));
        }
    }
    

    部署时需确保CLR程序集的权限设置允许访问System.Web。

  2. 手动实现严格的RFC 3986编码逻辑
    如果不想依赖System.Web,可以自己编写编码逻辑,遍历字符串并对包括*在内的保留字符进行转义。

另外,调整SQL Server CLR的PERMISSION_SET为UNSAFE并不能解决这个问题,因为该行为差异是宿主环境对API的适配导致的,和权限无关。

内容的提问来源于stack exchange,提问作者Ivan Debono

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 11:49:59