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

如何在JavaScript浏览器应用中使用数据库兼容的排序规则?

可行方案汇总

1. 自定义C++排序规则并编译为Wasm

既然采用wasm32-unknown-unknown编译C++且不依赖WASI,可手动实现目标数据库的排序规则核心逻辑:

  • 针对SQL_Latin1_General_CP1_CI_AS:基于Latin1编码(代码页1252),先将字符串统一转小写(处理大小写不敏感),再对照SQL Server官方字符权重表逐个字符比较权重值。
  • 针对es-ci(Snowflake西班牙语大小写不敏感):参考Unicode西班牙语排序规则,处理ñ等特殊字符的优先级,实现对应的大小写转换与权重映射。
  • 编译时需避免WASI依赖,仅导出比较函数供JavaScript调用。

示例C++导出框架:

#include <emscripten.h>
#include <string>
#include <cctype>

// 简化版SQL_Latin1_General_CP1_CI_AS字符权重映射
int get_sql_latin1_weight(char c) {
    c = tolower(static_cast<unsigned char>(c));
    // 实际需替换为完整的SQL Server权重表
    return static_cast<int>(c);
}

extern "C" {
    EMSCRIPTEN_KEEPALIVE
    int compare_sql_latin1(const char* a, const char* b) {
        std::string str_a(a), str_b(b);
        size_t min_len = std::min(str_a.size(), str_b.size());
        for (size_t i = 0; i < min_len; ++i) {
            int w_a = get_sql_latin1_weight(str_a[i]);
            int w_b = get_sql_latin1_weight(str_b[i]);
            if (w_a != w_b) {
                return w_a - w_b;
            }
        }
        return str_a.size() - str_b.size();
    }
}

编译命令(使用Emscripten):

emcc compare.cpp -o compare.wasm -Os -s EXPORTED_FUNCTIONS=['_compare_sql_latin1'] -s STANDALONE_WASM=1

JavaScript调用示例:

async function loadWasm() {
    const wasm = await WebAssembly.instantiateStreaming(fetch('compare.wasm'));
    const compare = wasm.instance.exports.compare_sql_latin1;
    // 大小写不敏感比较,返回0表示相等
    console.log(compare("Apple", "apple"));
}
loadWasm();

2. 编译轻量版ICU4C到Wasm

虽然WASI不带ICU,但可手动裁剪并编译ICU4C核心排序模块到wasm32-unknown-unknown目标:

  • 仅保留ICU中排序规则相关的核心代码,移除IO、冗余本地化资源等非必要模块。
  • 配置编译选项禁用WASI依赖,生成静态链接的Wasm库。
  • 在C++中调用ICU的ucol_strcoll函数,指定目标排序规则(如"SQL_Latin1_General_CP1_CI_AS"或"es-ci"),再导出函数供JS调用。
  • 优势是规则实现精准对齐标准,缺点是Wasm体积比自定义实现大。

3. JavaScript端硬编码规则映射

若不想依赖Wasm,可在JS中手动维护目标排序规则的字符权重表:

  • 针对SQL_Latin1_General_CP1_CI_AS:用TextEncoder/TextDecoder将字符串转成Latin1编码,统一转小写后,对照权重表逐个字符比较。
  • 针对es-ci:实现西班牙语特定排序逻辑,比如让ñ排在n之后,处理特殊字符的大小写转换规则。
  • 缺点是需手动维护权重表,易遗漏边缘场景,适合规则简单的需求。

示例JS实现SQL_Latin1_General_CP1_CI_AS比较(简化版):

function compareSqlLatin1CIAS(a, b) {
    const encoder = new TextEncoder('iso-8859-1');
    const decoder = new TextDecoder('iso-8859-1');
    // 转Latin1并统一小写
    const aLatin1 = decoder.decode(encoder.encode(a)).toLowerCase();
    const bLatin1 = decoder.decode(encoder.encode(b)).toLowerCase();
    
    for (let i = 0; i < Math.min(aLatin1.length, bLatin1.length); i++) {
        const codeA = aLatin1.charCodeAt(i);
        const codeB = bLatin1.charCodeAt(i);
        if (codeA !== codeB) {
            return codeA - codeB;
        }
    }
    return aLatin1.length - bLatin1.length;
}

// 重音敏感比较,返回非0表示不相等
console.log(compareSqlLatin1CIAS("Café", "cafe"));

内容的提问来源于stack exchange,提问作者phantom bridge

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:27:42