繁体   English   中英

更新表语句 - 违反主键约束

[英]update table statement - Violation of Primary Key constraint

如果记录存在,我尝试了这个c# 更新,如果记录存在,则插入新记录来更新我的表。

但我遇到了例外:“违反主键约束”。 由于这一行cmdCount.Parameters.AddWithValue("@local_programs_id", local_programs_id); 并且因为表中已经有local_programs_id的值

我做错了什么?

非常感谢。

SqlConnection connection = new SqlConnection(sqlConnection_String);
            

            SqlCommand cmdCount = new SqlCommand("SELECT count(*) FROM " + datenbankname + " WHERE local_programs_id = @local_programs_id" , connection);
            cmdCount.Parameters.AddWithValue("@local_programs_id", local_programs_id);

            connection.Open();

            int count = (int)cmdCount.ExecuteScalar();
            Console.WriteLine("count1 " + count);
         

            if (count > 0)
            {
                SqlCommand updateCommand = new SqlCommand("UPDATE " + datenbankname + 
                    " SET local_programs_Id = @local_programs_Id, " +
                    "program_name = @program_name, " +
                    "publisher_name = @publisher_name, " +
                    "program_version = @program_version, " +
                    "install_dir = @install_dir, " +
                    "uninstall_dir = @uninstall_dir, " +
                    "inserted_at = @inserted_at, " +
                    "direct_link_available = @direct_link_available", connection);

                updateCommand.Parameters.AddWithValue("@local_programs_Id", local_programs_id);
                updateCommand.Parameters.AddWithValue("@program_name", program_names);
                updateCommand.Parameters.AddWithValue("@publisher_name", publisher_names);
                updateCommand.Parameters.AddWithValue("@program_version", program_version);
                updateCommand.Parameters.AddWithValue("@install_dir", install_location);
                updateCommand.Parameters.AddWithValue("@uninstall_dir", uninstall_location);
                updateCommand.Parameters.AddWithValue("@inserted_at", DateTime.Now);
                updateCommand.Parameters.AddWithValue("@direct_link_available", direct_link_available);

                int rowsUpdated = updateCommand.ExecuteNonQuery();
                Console.WriteLine("rowsUpdated " + rowsUpdated);
            }
            else
            {

                Console.WriteLine("inserted1 ");
            
                string query = "INSERT INTO " + datenbankname + " (local_programs_Id, program_name, publisher_name, program_version, install_dir,  uninstall_dir, inserted_at)";
                query += " VALUES (@local_programs_Id, @program_name, @publisher_name, @program_version, @install_dir, @uninstall_dir, @inserted_at)";

                SqlCommand insertCommand = new SqlCommand(query, connection);
                
                insertCommand.Parameters.AddWithValue("@local_programs_Id", local_programs_id);
                insertCommand.Parameters.AddWithValue("@program_name", program_names);
                insertCommand.Parameters.AddWithValue("@publisher_name", publisher_names);
                insertCommand.Parameters.AddWithValue("@program_version", program_version);
                insertCommand.Parameters.AddWithValue("@install_dir", install_location);
                insertCommand.Parameters.AddWithValue("@uninstall_dir", uninstall_location);
                insertCommand.Parameters.AddWithValue("@inserted_at", DateTime.Now);

                int rowsInserted = insertCommand.ExecuteNonQuery();
            }

您的更新语句中没有 where 过滤器,并且您正在更新主键列。 你本质上是在做

  1. 检查是否有X主键值的行
  2. 如果有则更新每一行以具有该主键值。
  3. 如果没有则插入。

您永远不应该更新主键,即使在您不应该更改主键的情况下也是如此。 这可能会产生很多烦人的行为,我想到的是这个主键在另一个表的外键中引用的地方——这个更新语句会在另一个表上加锁(如果它是,则可能是一个完整的表锁)未编入索引)。

您也不应该使用 count(*) 来确定该行是否存在。 这只会告诉您该行是否在该时间点存在并且对您的 session 可见(您看不到未提交的事务)。 大多数 RDBMS 都有一个 MERGE 操作,您可以将其用于此行为,请查看您的 RDBMS 文档。 或者,乐观地尝试插入语句可能没问题,如果它抛出重复行错误,则执行更新语句。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM