我尝试使用 example 推断其单行更新插入,以在 PostgrSQL/Timescale 表上执行多行更新插入,但收到以下错误:
ON CONFLICT DO UPDATE command cannot affect row a second time
SQL语句为:
INSERT INTO tablename
(time, Column2Name, Column3Name)
VALUES ($1, $2, $3),
($1, $2, $3)
ON CONFLICT (time) DO UPDATE SET
Column2Name = excluded.Column2Name,
Column3Name = excluded.Column3Name;
我这样设置 Npgsql 参数:
var parameterList1 = new List<NpgsqlParameter>();
var timeParameter = new NpgsqlParameter(null, NpgsqlDbType.TimestampTZ);
timeParameter.Value = reading1.dateTimeOffsetValue.UtcDateTime;
parameterList1.Add(timeParameter);
var column2Parameter = new NpgsqlParameter(null, NpgsqlDbType.Double);
column2Parameter = reading1.column2Value;
parameterList1.Add(column2Parameter);
var column3Parameter = new NpgsqlParameter(null, NpgsqlDbType.Double);
column3Parameter = reading1.column3Value;
parameterList1.Add(column3Parameter);
var parameterList2 = new List<NpgsqlParameter>();
var timeParameter2 = new NpgsqlParameter(null, NpgsqlDbType.TimestampTZ);
timeParameter2.Value = reading2.dateTimeOffsetValue.UtcDateTime;
parameterList2.Add(timeParameter2);
var column2Parameter2 = new NpgsqlParameter(null, NpgsqlDbType.Double);
column2Parameter2 = reading2.column2Value;
parameterList2.Add(column2Parameter2);
var column3Parameter2 = new NpgsqlParameter(null, NpgsqlDbType.Double);
column3Parameter2 = reading2.column3Value;
parameterList2.Add(column3Parameter2);
然后执行sql为:
using var connection = _dataSource.OpenConnection();
{
using var cmd = new NpgsqlCommand(sql, connection);
cmd.Parameters.AddRange(parameterList1.ToArray());
cmd.Parameters.AddRange(parameterList2.ToArray());
cmd.ExecuteNonQuery();
connection.Close();
};
然后我收到错误:
ON CONFLICT DO UPDATE command cannot affect row a second time
我已经确认,在执行此示例时,reading1.DateTimeOffsetValue 和 Reading2.DateTimeOffsetValue 是唯一的,但传入的数据可能在要写入的数组记录中存在重复项,并且数据库中已有一条记录。
线索?
Timescale 支持最终回答了这个问题。占位符在整个语句中必须是唯一的,而不仅仅是每行,正确的 sql 是:
VALUES ($1, $2, $3), ($4, $5, $6)
此外,虽然更新插入将更新该时间戳处的现有行,但重要的是确保您尝试写入的新值没有任何重复的时间戳。