如何移除/规避SQL Server行延续功能解决BLOB字符丢失问题
问题解答
关于禁用SQL Server的Line Continuation功能
SQL Server的「行延续(Line Continuation)」是SQL语法解析层面的规则,仅当SQL语句末尾使用反斜杠\时才会触发,将下一行视为当前语句的延续。该功能没有提供可在存储过程或服务器端禁用的配置选项。你遇到的字符丢失问题,根源更可能是两方面:
- 使用
Encoding.ASCII.GetString转换字节数组时,大于127的字节会被替换为?,直接丢失数据; - Blob中的换行、回车等控制字符,被查询聚合的打包逻辑误判为SQL语句的分隔符,导致字符串被截断。
无需修改数据的规避方案
结合你的现有约束(查询聚合机制不可弃、低配置设备/弱网络、遗留代码难修改),推荐以下两种方案,优先选择第一种:
方案1:使用十六进制字符串传输(最优)
将字节数组转为十六进制字符串传输,完全避免特殊字符问题,体积仅为原Blob的2倍(比Base64的2.6倍更节省带宽),转换逻辑简单,适配现有场景。
客户端C#修改:
替换原ASCII转换代码为:
// 将字节数组转为无分隔符的十六进制字符串 string hexBlob = BitConverter.ToString(Blob).Replace("-", "");
构造SQL语句时直接传入该字符串(无需替换单引号,十六进制仅包含0-9、A-F字符):
INSERT INTO 表名 (blob列) VALUES (CONVERT(VARBINARY(MAX), '" + hexBlob + "', 2))
服务器端处理:
使用CONVERT的第三个参数2(表示输入为十六进制字符串),即可准确还原字节数组:
CONVERT(VARBINARY(MAX), @BLOB, 2)
方案2:替换编码+完善特殊字符转义
如果无法使用十六进制,可先解决编码丢失问题,再完善特殊字符转义:
客户端C#修改:
- 将
Encoding.ASCII替换为ISO-8859-1(单字节编码,完整保留所有字节的字符映射,无?替换丢失); - 除单引号外,将换行、回车等控制字符转义为SQL可识别的拼接形式,避免被聚合逻辑误判:
string blobStr = Encoding.GetEncoding("ISO-8859-1").GetString(Blob, 0, Blob.Length); // 转义单引号、回车、换行 blobStr = blobStr.Replace("'", "''") .Replace("\r", "'+CHAR(13)+'") .Replace("\n", "'+CHAR(10)+'");
服务器端处理:
保持原CONVERT语句即可,SQL会自动拼接字符串并还原控制字符:
CONVERT(VARBINARY(MAX), @BLOB)
方案对比
| 方案 | 体积增加 | 数据完整性 | 适配性(弱网络/低配置) | 修改复杂度 |
|---|---|---|---|---|
| 十六进制传输 | 2倍 | 完整保留 | 优 | 极低 |
| Base64传输 | 2.6倍 | 完整保留 | 中 | 低 |
| 编码替换+字符转义 | 无额外增加 | 完整保留 | 中 | 中 |
内容的提问来源于stack exchange,提问作者Johan Persson
相关产品推荐
相关产品推荐

