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

如何用C#生成含列名与列描述的SQL Server查询结果CSV文件

嘿,这个需求我之前帮不少ASP.NET开发者解决过,其实核心就是先手动生成包含列名和列描述的前两行,再把SQL查询出来的数据逐行追加进去就行!我给你完善代码示例,分两种场景来写,你可以按需选用:

场景1:固定列名和描述(适合查询结构不变的情况)

这种方式直接硬编码列名和对应的描述,简单直观:

protected void ExportCSV(object sender, EventArgs e)
{
    // 读取连接字符串
    string constr = ConfigurationManager.ConnectionStrings["YourConnectionString"].ConnectionString;
    // 你的SQL查询语句(注意列顺序要和下面的字典对应)
    string query = "SELECT Id, UserName, RegisterDate FROM dbo.Users";

    // 定义列名与对应描述的映射
    Dictionary<string, string> columnMeta = new Dictionary<string, string>
    {
        {"Id", "用户唯一标识ID"},
        {"UserName", "用户登录账号"},
        {"RegisterDate", "用户注册时间"}
    };

    // 准备响应,让浏览器触发下载
    Response.Clear();
    Response.Buffer = true;
    Response.ContentType = "text/csv";
    Response.AddHeader("Content-Disposition", "attachment;filename=UserExport.csv");
    // 用UTF8带BOM,避免中文乱码
    using (StreamWriter sw = new StreamWriter(Response.OutputStream, Encoding.UTF8))
    {
        // 第一行:写入列名(加双引号避免列名含逗号)
        string headerLine = string.Join(",", columnMeta.Keys.Select(col => $"\"{col}\""));
        sw.WriteLine(headerLine);

        // 第二行:写入列描述(和列名顺序一一对应)
        string descLine = string.Join(",", columnMeta.Values.Select(desc => $"\"{desc}\""));
        sw.WriteLine(descLine);

        // 执行SQL查询,写入数据行
        using (SqlConnection con = new SqlConnection(constr))
        {
            using (SqlCommand cmd = new SqlCommand(query, con))
            {
                con.Open();
                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        List<string> rowValues = new List<string>();
                        foreach (string colName in columnMeta.Keys)
                        {
                            // 处理空值,转义内容里的双引号(CSV规范要求把"换成"")
                            string value = dr[colName] != DBNull.Value ? dr[colName].ToString() : "";
                            rowValues.Add($"\"{value.Replace("\"", "\"\"")}\"");
                        }
                        sw.WriteLine(string.Join(",", rowValues));
                    }
                }
            }
        }

        sw.Flush();
        Response.End();
    }
}

场景2:动态获取列描述(从SQL Server系统视图读取,适合动态查询)

如果你的查询表是动态的,或者想直接用SQL Server里给列设置的扩展属性描述(就是SSMS里列的Description属性),可以通过系统视图自动获取:

protected void ExportCSV(object sender, EventArgs e)
{
    string constr = ConfigurationManager.ConnectionStrings["YourConnectionString"].ConnectionString;
    // 替换成你的目标表名(架构+表名)
    string targetTable = "dbo.Users";
    // 查询该表的所有列(和系统视图列顺序一致)
    string query = $"SELECT * FROM {targetTable}";

    // 从SQL Server系统视图获取列名和对应的描述
    Dictionary<string, string> columnMeta = new Dictionary<string, string>();
    using (SqlConnection con = new SqlConnection(constr))
    {
        string descQuery = @"
            SELECT c.name AS ColumnName, 
                   ISNULL(ep.value, '无描述') AS ColumnDescription
            FROM sys.columns c
            LEFT JOIN sys.extended_properties ep 
                ON c.object_id = ep.major_id 
                AND c.column_id = ep.minor_id 
                AND ep.name = 'MS_Description'
            WHERE c.object_id = OBJECT_ID(@TargetTable)
            ORDER BY c.column_id";
        
        using (SqlCommand cmd = new SqlCommand(descQuery, con))
        {
            cmd.Parameters.AddWithValue("@TargetTable", targetTable);
            con.Open();
            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    columnMeta.Add(dr["ColumnName"].ToString(), dr["ColumnDescription"].ToString());
                }
            }
        }
    }

    // 后续写入CSV的逻辑和场景1完全一致
    Response.Clear();
    Response.Buffer = true;
    Response.ContentType = "text/csv";
    Response.AddHeader("Content-Disposition", "attachment;filename=DynamicExport.csv");
    using (StreamWriter sw = new StreamWriter(Response.OutputStream, Encoding.UTF8))
    {
        // 写入列名行
        sw.WriteLine(string.Join(",", columnMeta.Keys.Select(col => $"\"{col}\"")));
        // 写入描述行
        sw.WriteLine(string.Join(",", columnMeta.Values.Select(desc => $"\"{desc}\"")));

        // 写入数据行
        using (SqlConnection con = new SqlConnection(constr))
        {
            using (SqlCommand cmd = new SqlCommand(query, con))
            {
                con.Open();
                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        List<string> rowValues = new List<string>();
                        foreach (string colName in columnMeta.Keys)
                        {
                            string value = dr[colName] != DBNull.Value ? dr[colName].ToString() : "";
                            rowValues.Add($"\"{value.Replace("\"", "\"\"")}\"");
                        }
                        sw.WriteLine(string.Join(",", rowValues));
                    }
                }
            }
        }

        sw.Flush();
        Response.End();
    }
}

关键注意点

  • 所有写入CSV的内容都加了双引号,避免内容里的逗号、换行符破坏CSV格式
  • 转义了内容中的双引号(把"替换成""),符合CSV官方规范
  • 用Encoding.UTF8带BOM写入,避免中文在Excel中显示乱码
  • 如果你的查询是自定义的多表联合查询,场景1的硬编码方式会更稳妥,确保列顺序完全匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:38:20