在C#中将IANA TLD文件插入SQL数据库时遇超长字符串问题
解决SQL插入超长TLD字符串时的引号异常问题
错误原因分析
你遇到的No closing quotation mark after the string异常,核心原因有两个:
- SQL字符串常量长度限制:SQL Server中,普通Unicode字符串常量(
N'...')的最大长度是4000字符,非Unicode是8000字符。当你把大量TLD拼接成超长字符串直接写入SQL脚本时,字符串会被截断,导致末尾的闭合引号丢失,触发语法错误。 - 潜在的特殊字符风险:虽然IANA的TLD通常不含单引号,但如果后续TLD列表出现特殊字符,直接拼接也会破坏SQL语法结构。
原代码中用Split("GO")拆分脚本无法解决问题,因为错误根源不是脚本批次分割,而是字符串本身的语法破坏。
解决方案
方案1:使用参数化查询(推荐)
直接在C#中读取TLD并通过参数化命令执行插入/更新,彻底规避字符串长度和特殊字符问题,同时更安全(防止SQL注入)。
示例代码:
// 读取并处理IANA的TLD列表 var tldContent = await new HttpClient().GetStringAsync("https://data.iana.org/TLD/tlds-alpha-by-domain.txt"); var tldString = string.Join(",", tldContent.Split('\n') .Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith("#")) .Select(line => line.Trim().ToLower()) // 转小写可选,根据需求调整 ); // 执行SQL操作 using (var conn = new SqlConnection("你的数据库连接字符串")) { await conn.OpenAsync(); // 检查记录是否存在 var checkCmd = new SqlCommand( "SELECT COUNT(ID) FROM MediaSettings WHERE [Key] = 'TopLevelDomains'", conn ); var recordCount = (int)await checkCmd.ExecuteScalarAsync(); if (recordCount == 0) { // 插入新记录 var insertCmd = new SqlCommand(@" INSERT INTO MediaSettings (ID, Name, [Key], Value, CreateDate) VALUES (NEWID(), 'TopLevelDomains', 'TopLevelDomains', @TldValues, GETDATE())", conn ); insertCmd.Parameters.Add("@TldValues", SqlDbType.NVarChar, -1).Value = tldString; await insertCmd.ExecuteNonQueryAsync(); } else { // 更新已有记录 var updateCmd = new SqlCommand(@" UPDATE MediaSettings SET Value = CONCAT(Value, ',', @TldValues) WHERE [Key] = 'TopLevelDomains'", conn ); updateCmd.Parameters.Add("@TldValues", SqlDbType.NVarChar, -1).Value = tldString; await updateCmd.ExecuteNonQueryAsync(); } }
方案2:修改SQL脚本(不推荐,仅适用于必须用脚本的场景)
如果坚持使用SQL脚本文件,不要直接将超长TLD字符串写入脚本,而是通过变量或文件读取的方式传入:
- 在脚本中定义
NVARCHAR(MAX)变量,分批次拼接TLD值; - 或者使用
OPENROWSET直接读取IANA文件内容(需要配置数据库权限)。
但这种方式复杂度高,不如参数化查询简洁可靠。
额外注意点
- 读取IANA文件时,要过滤开头的注释行(
#开头),避免把注释内容混入TLD列表; - 若需要去重TLD,可以在拼接前添加
.Distinct()方法。
内容的提问来源于stack exchange,提问作者Ch.D.
相关产品推荐
相关产品推荐

