Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重复密钥违反唯一约束_C#_Database_Postgresql_Sequence_Primary Key - Fatal编程技术网

C# 重复密钥违反唯一约束

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

我有写日志的表历史记录

当我想插入日志时,我得到错误:

23505:重复密钥违反唯一约束

这是我的功能

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_值