You need to enable JavaScript to run this app. 如何将DataTable作为参数传入PostgreSQL函数并实现批量插入?
优惠活动
大模型
产品
解决方案
定价
更多

如何将DataTable作为参数传入PostgreSQL函数并实现批量插入?

C#代码修正

你当前的C#代码存在命令未执行的问题,补充调整后代码如下:

public void InsertDataInBulk(DataTable dataTable, string functionName ,ILogger logger) 
{
    try
    {
        var connection = _dbConnect.OpenConnection(logger);
        using (DbCommand command = connection.CreateCommand())
        {
            command.CommandText = functionName; // 这里不要写死f_testbulkinsert,用传入的参数
            command.CommandType = CommandType.StoredProcedure;
            if (dataTable != null && dataTable.Rows.Count > 0)
            {
                var parameter = command.CreateParameter();
                parameter.ParameterName = "testtype";
                // 如果你用的是Npgsql驱动,建议指定参数类型为Jsonb,性能更优
                // parameter.DbType = DbType.Object;
                // ((NpgsqlParameter)parameter).NpgsqlDbType = NpgsqlDbType.Jsonb;
                parameter.Value = JsonConvert.SerializeObject(dataTable);
                // 不需要Formatting.Indented,格式化的空白字符无意义还增加传输体积
                command.Parameters.Add(parameter);
            }
            // 补充执行命令的逻辑
            command.ExecuteNonQuery();
        }
        _dbConnect.CloseConnection(connection, logger);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, ex.Message);
        throw;
    }
}
PostgreSQL函数实现

建议将入参类型从varchar改为jsonb,相比字符串类型支持原生JSON操作,性能更高。以下是完整的函数实现示例,假设你需要插入的目标表为public.test_table,结构如下:

CREATE TABLE public.test_table (
    id int4 PRIMARY KEY,
    user_name varchar(50) NOT NULL,
    age int4 NULL,
    create_time timestamp NOT NULL
);

对应的批量插入函数如下:

CREATE OR REPLACE FUNCTION public.f_testbulkinsert(
    testtype jsonb)
    RETURNS void
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE PARALLEL UNSAFE
AS $BODY$
BEGIN
  -- 将JSON数组转为结构化表数据,直接批量插入目标表
  INSERT INTO public.test_table(id, user_name, age, create_time)
  SELECT 
    t.id,
    t.user_name,
    t.age,
    t.create_time
  FROM jsonb_to_recordset(testtype) AS t(
    id int, 
    user_name varchar, 
    age int, 
    create_time timestamp
  );
  
  -- 如果需要处理主键冲突,比如冲突时更新字段,可以加ON CONFLICT逻辑,示例:
  -- ON CONFLICT (id) DO UPDATE SET 
  -- user_name = EXCLUDED.user_name,
  -- age = EXCLUDED.age;
END;
$BODY$;

注意:jsonb_to_recordset后面定义的临时表列名、列类型,必须和你C#中DataTable的列名、数据类型一一对应,否则会出现解析错误。如果你的DataTable列名和目标表列名不一致,在SELECT部分做别名映射即可。

补充说明

如果你的数据量特别大(单批超过10万行),JSON序列化+解析的方案性能会有损耗,建议用PostgreSQL原生的COPY命令实现批量插入,性能比存储过程方案高3-5倍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 08:45:07