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

如何在C#中统计SQL Server表各列的NULL、非NULL及总行数

C#实现SQL Server表列的NULL/非NULL值统计

原有获取列名代码的修正

你提供的GetColumns方法存在两个问题:一是直接拼接SQL字符串有SQL注入风险,二是读取查询结果时仅获取了第一行数据,无法拿到所有列名。以下是修正后的版本:

using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;

public List<string> GetColumns(string tableName)
{
    var columns = new List<string>();
    
    // 使用参数化查询避免SQL注入
    var selectQuery = @"SELECT COLUMN_NAME 
                       FROM INFORMATION_SCHEMA.COLUMNS 
                       WHERE TABLE_NAME = @TableName";

    using (var conn = new SqlConnection(_sqlServerConnectionString.SqlServerConnectionString))
    {
        conn.Open();
        using (var cmd = new SqlCommand(selectQuery, conn))
        {
            cmd.Parameters.AddWithValue("@TableName", tableName);
            using (var reader = cmd.ExecuteReader())
            {
                // 循环读取所有列名
                while (reader.Read())
                {
                    columns.Add(reader["COLUMN_NAME"].ToString());
                }
            }
        }
        // using块会自动关闭连接,无需手动调用conn.Close()
    }           

    return columns;
}

实现列统计功能

要高效统计每列的总行数、NULL值数量和非NULL值数量,我们可以通过一次SQL查询获取所有列的统计数据,避免多次连接数据库。以下是完整实现:

1. 定义统计结果模型

public class ColumnStatistics
{
    public string ColumnName { get; set; }
    public int TotalRows { get; set; }
    public int NullCount { get; set; }
    public int NonNullCount { get; set; }
}

2. 统计方法实现

public List<ColumnStatistics> GetColumnStatistics(string tableName)
{
    var columnStats = new List<ColumnStatistics>();
    var columns = GetColumns(tableName);

    if (columns.Count == 0)
        return columnStats;

    // 构建统计SQL:COUNT(*)获取总行数,COUNT(列名)获取非NULL数量
    var statsQueryParts = new List<string>();
    // 先获取总行数(所有列总行数一致,只需计算一次)
    statsQueryParts.Add("COUNT(*) AS TotalRows");
    // 为每个列添加非NULL统计
    foreach (var column in columns)
    {
        statsQueryParts.Add($"COUNT({QuotedIdentifier(column)}) AS {QuotedIdentifier($"NonNull_{column}")}");
    }

    var statsQuery = $"SELECT {string.Join(", ", statsQueryParts)} FROM {QuotedIdentifier(tableName)}";

    using (var conn = new SqlConnection(_sqlServerConnectionString.SqlServerConnectionString))
    {
        conn.Open();
        using (var cmd = new SqlCommand(statsQuery, conn))
        {
            using (var reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    int totalRows = reader.GetInt32(reader.GetOrdinal("TotalRows"));
                    // 遍历每个列,计算NULL数量并封装结果
                    foreach (var column in columns)
                    {
                        int nonNullCount = reader.GetInt32(reader.GetOrdinal($"NonNull_{column}"));
                        columnStats.Add(new ColumnStatistics
                        {
                            ColumnName = column,
                            TotalRows = totalRows,
                            NonNullCount = nonNullCount,
                            NullCount = totalRows - nonNullCount
                        });
                    }
                }
            }
        }
    }

    return columnStats;
}

// 辅助方法:为列名/表名添加引号,处理包含特殊字符或关键字的情况
private string QuotedIdentifier(string name)
{
    return $"[{name}]";
}

3. 使用示例

// 调用统计方法
var stats = GetColumnStatistics("YourTableName");
// 输出结果
foreach (var stat in stats)
{
    Console.WriteLine($"列名: {stat.ColumnName}");
    Console.WriteLine($"总行数: {stat.TotalRows}");
    Console.WriteLine($"NULL值数量: {stat.NullCount}");
    Console.WriteLine($"非NULL值数量: {stat.NonNullCount}");
    Console.WriteLine("---");
}

关键说明

  • 避免SQL注入:所有与用户输入相关的表名、列名都通过QuotedIdentifier方法添加方括号,同时原获取列名的方法使用了参数化查询。
  • 高效查询:仅执行一次SQL查询就获取所有列的统计数据,相比逐列查询大幅提升效率。
  • 资源自动释放:所有SqlConnection、SqlCommand、SqlDataReader都使用using块,确保数据库资源被正确释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 04:25:17