C# 重复密钥违反唯一约束
我有写日志的表历史记录 当我想插入日志时,我得到错误: 23505:重复密钥违反唯一约束 这是我的功能C# 重复密钥违反唯一约束,c#,database,postgresql,sequence,primary-key,C#,Database,Postgresql,Sequence,Primary Key,我有写日志的表历史记录 当我想插入日志时,我得到错误: 23505:重复密钥违反唯一约束 这是我的功能 public static void InsertLog(JobLogs log) { using (NpgsqlConnection con = new NpgsqlConnection(AppForms.connectionString)) { string insert = "Insert into jat.history Valu
public static void InsertLog(JobLogs log)
{
using (NpgsqlConnection con = new NpgsqlConnection(AppForms.connectionString))
{
string insert = "Insert into jat.history Values (@jobid, @year, @number, @datetime, @operator, @activity, @desc, nextval('jat.history_h_id_seq'))";
using (NpgsqlCommand cmd = new NpgsqlCommand(insert, con))
{
//MessageBox.Show(insert);
con.Open();
cmd.Parameters.AddWithValue("@jobid", log.JobId);
cmd.Parameters.AddWithValue("@year", log.jobMark.Year);
cmd.Parameters.AddWithValue("@number", log.jobMark.JobNumber);
cmd.Parameters.AddWithValue("@datetime", log.Time);
cmd.Parameters.AddWithValue("@operator", log.Operator.GetFullName());
cmd.Parameters.AddWithValue("@activity", log.Activity);
cmd.Parameters.AddWithValue("@desc", DBNull.Value);
cmd.ExecuteNonQuery();
}
}
}
表历史记录只有一个主键,它是->h_id。当我将insert query更改为此时:
string insert = "Insert into jat.history Values(@jobid, @year, @number, @datetime, @operator, @activity, @desc, (select max(h_id) + 1 from jat.history))";
它工作正常,但我听说我应该在多用户应用程序中使用序列,那么我的第一个函数和第一个查询有什么问题
编辑:
当我按照建议运行这两个查询时,会得到以下结果:
" (SELECT last_value FROM jat.history_h_id_seq)"; -- result:282
"SELECT (SELECT MAX(h_id) FROM jat.history)"; -- result:290
在表定义中,h_id字段是h_id serial NOT NULL。序列位意味着为该字段创建了一个序列,这样每当您向该表中插入一条新记录时,默认情况下,h_id字段将是nextval'jat.history_h_id_seq'的值 当一个字段被设置成这样时,在大多数情况下,您不应该在INSERT命令中手动指定该字段和一个值,因为这意味着nextval'jat.history_h_id_seq'不会被调用和递增,这可能会导致您遇到的问题 例如,让我们创建一个新表:create table t id SERIAL PRIMARY KEY,txt TEXT;。名为schema_name.t_id_seq的序列将与表一起自动创建。我还在id上放了一个主键,因为它也是表的主键 现在正确地插入一条新记录:插入t txt值“hello”;这将创建一个包含值id:1、txt:“hello”的记录。我根本没有指定id,但它自动得到值1。如果以相同的方式插入另一条记录,则新记录的id将为2 相反,我会错误地插入一条新记录:插入到t id中,txt值为2,'bye';。这很好,但是我手动设置了id的值,这意味着序列没有被使用,所以它的下一个值仍然是2。现在,如果我正确插入另一条记录:插入到t txt值“test”;,它将失败,并出现唯一的冲突错误,因为它试图使用序列的nextval值2作为id,但具有该id的记录已经存在,因为我手动指定了该字段 无论如何,这就是你的数据的问题。根据从表中获取MAXh_id和从序列中获取last_值的查询,表中的id比序列中的id高,而表中的最高id应该与序列的last_值相同或更低 要解决这个问题,首先从表中将序列更新为max id:选择SETVAL'jat.history_h_id_seq',从jat.history选择MAXh_id 这会将序列的当前值更新为表中的最高id,因此下次使用序列时,下一个id last/current+1将高于表中的任何值,因此不会重复
第二部分是确保在任何insert语句中都不指定h_id。只需允许它自动从序列中获取下一个值。否则,您将再次遇到此问题。如果您使用的是序列,则应将表配置为自动使用序列的下一个部分。在常规使用中,您不应该自己手动呼叫nextval。很可能您的表设置不正确,因此序列没有跟上实际的表值,因此调用nextval返回一个已经以其他方式手动输入的数字。@eurotrash那么您建议我如何将最高id插入数据库您能发布表架构吗?它将告诉我表格是如何设置的,我可以告诉你从那里该怎么做。请总是用谷歌搜索错误消息&你的问题/问题/目标的许多清晰、简洁和具体的版本/措辞,有或没有你的特定字符串/名称&“site:stackoverflow.com”&标记并阅读许多答案。将发现的相关关键字添加到搜索中。如果你找不到答案,就发布,使用1个变体搜索作为标签的标题和关键字。请参见文本上方的向下投票箭头鼠标。当您确实有一个非重复代码问题要发布时,请阅读并执行。@mikisa此查询应返回2个值;运行它并发布结果:从jat.history中选择SELECT MAXh_id,从jat.history中选择last_值