【问题标题】:How do i prevent duplicate records in my database while updating records?更新记录时如何防止数据库中出现重复记录?
【发布时间】:2015-05-06 16:54:20
【问题描述】:

在我的 mysql 表中,我做了这个

ControlNum|Title  |NumOfEpis|Description|
001       |naruto |500      |some text  |
002       |conan  |700      |some text  |

现在我在 C# 中创建了一个用户控件,其中允许用户更新除主“ControlNum”之外的所有列。因此,假设每一列在该用户控件中都有自己的文本框,因此为了避免标题列中的重复,例如,如果用户编辑第 2 行标题并将其放入“火影忍者”,它也会被复制..所以我创建这个方法叫做 checkData();

void checkData()
    {
        SuspendLayout();
        try
        {
            MySqlConnection conn = new MySqlConnection(myConnection);
            conn.Open();
            MySqlCommand command = new MySqlCommand("SELECT * FROM maindatabase.animelist where TitleAnime=?Title;", conn);
            //command.Parameters.AddWithValue("?CN", int.Parse(a.ToString()));
            command.Parameters.AddWithValue("?Title", textBox3.Text);
            MySqlDataReader reader = command.ExecuteReader();

            int ctr = 0;
            while (reader.Read())
            {
                ctr++;

            }
            if (ctr == 1)
            {
                my = Form.ActiveForm as MyList;
                my.msg = new Message_Box();
                my.msg.Descrip.Text = "Record is already in the Database";
                my.msg.Title.Text = "Duplicate Record";
                my.msg.ShowDialog();
            }
            else
            {

                updateData();
            }


            conn.Close();
            ResumeLayout();
        }
        catch (Exception ex)
        {
            MessageBox.Show("" + ex);
        }
    }


它正在工作,但我的问题是,如果用户只更新 Epis 和 descrip 的数量并且并不真正打算更新标题,我的方法仍然检测到存在重复,因为我的逻辑是“如果(ctr == 1)"..我想我错过了一些方法,或者我在这里的方法有误..所以我希望有人能启发我..抱歉在这里是菜鸟 Y.Y

【问题讨论】:

  • 在您的数据库中,在“标题”列上放置一个唯一约束。在您的代码中,捕获约束冲突错误并向用户显示友好的错误消息。
  • 菜鸟没问题...我一直觉得自己像个菜鸟! :) 我要做的是首先寻求数据库解决方案。你要做的是确保你有一个主键/身份,比如 RowID 或其他东西,然后你想使用一个 UNIQUE CONSTRAINT。你可以在这里找到如何使用它们 --> w3schools.com/sql/sql_unique.asp
  • @mbeckish 唯一约束?在我的数据库中,我看到唯一索引是一样的吗?以及如何发现错误?比如 try catch 块?

标签: c# mysql sql-update unique


【解决方案1】:

如果您的应用程序支持多个用户,您需要确保在检查重复项和数据库更新之间没有其他用户进行更改。

最简单的方法是按照 mbeckish 的建议,在标题列上创建一个 UNIQUE 约束:

ALTER TABLE maindatabase.animelist 
ADD CONSTRAINT U_animelist_TitleAnime UNIQUE (TitleAnime)

然后,数据库引擎将强制执行唯一的标题,您的客户端可以通过捕获任何违反约束的异常来处理用户反馈:

void checkData()
{
    SuspendLayout();
    try
    {

        updateData();

    }
    catch (Exception ex)
    {
        MySqlException sqlEx = ex as MySqlExecption;
        // If there is a constraint violation error.
        // (I may have the wrong error number, please test.)
        if (sqlEx != null && sqlEx.Number == 1062) 
        {
            my = Form.ActiveForm as MyList;
            my.msg = new Message_Box();
            my.msg.Descrip.Text = "Record is already in the Database";
            my.msg.Title.Text = "Duplicate Record";
            my.msg.ShowDialog();
        } 
        else 
        {
            MessageBox.Show("" + ex);
        }
    }
    finally
    {
        ResumeLayout();
    }
}

【讨论】:

  • 这是正确的答案。 Steve 的代码解决方案有效,但您为自己和数据库做了额外的工作。
  • 同意,但我认为更重要的是其他解决方案不可靠。很难向用户解释您的应用程序将防止重复标题,除非两个用户同时更改内容,如果/当出现问题时。如果数据库引擎不强制执行,也很难追踪重复的来源。只是想强调这一点,因为我遇到了很多这类问题,它们真的让我很恼火:)
  • 哦,所以这里还有其他解决方案..好的,我会试试这个并检查结果..顺便说一句,谢谢你们帮助我^^,
  • 它在更新时工作正常,但我的问题是当我故意更新重复记录时的 catch 块,它没有捕获 if 语句并且总是返回 false(在 else 中)
  • 我的错误号可能有误,sqlEx.Number等于什么?还是 sqlEx 为空?
【解决方案2】:

您不希望有两个标题具有相同的内容。这可以通过该列上的唯一索引自动实现。但是,如果您不想为此添加索引,则可以将查询更改为

SELECT ControlNum FROM maindatabase.animelist 
WHERE TitleAnime=?Title;

那么你的逻辑也应该检查 ControlNum 的差异

int currentNum = int.Parse(a.ToString()));
while (reader.Read())
{
    int ctrlNum = reader.GetInt32(0);
    if(ctrlNum != currentNum)
        ctr++;

}
if (ctr > 0)
    ......

只有当检索到的 ControlNum 与您在界面中选择的不同时,您才会增加计数器

以下是另一种方法(请参阅下面来自@mbeckish 的评论)

SELECT 1 FROM maindatabase.animelist 
WHERE TitleAnime=?Title AND ControlNum <> ?CN

command.Parameters.AddWithValue("?CN", int.Parse(a.ToString()));
command.Parameters.AddWithValue("?Title", textBox3.Text);
object result = command.ExecuteScalar();
if(result != null)
{
    // Found a record with different ControlNum but with the same title
    // Error here
}

这可能比第一个更可取,因为您不需要循环,并且可以使用更简单且性能更高的 ExecuteScalar,它只返回第一行的第一列(在本例中为 1)而不构建 MySqlDataReader 对象

【讨论】:

  • 谢谢你的教训..ahhhm 我在 (ctr>0) 里面放什么更新方法或重复警报?
  • 嗯,当前代码,重复警告。如果当前记录具有相同的 ControlNum 存储在变量a 中,则上面的代码将跳过控制变量的增量,因此,如果在读取循环之后控制变量仍然为零,那么您就没有像原来那样的另一个标题,否则已经有一条记录(具有不同的 ControlNum)具有您的用户键入的标题
  • ohh tnx 所以其他的将是更新尝试一下
  • 为什么不在 SQL 查询中添加 ControlNum &lt;&gt; currentNum 呢?这样,您只需选择记录数,就可以摆脱 while 循环。
  • 如果您无法将唯一约束添加到数据库,更安全的方法是在事务中进行更新,在更新后检查重复项,然后回滚并在发现重复项时引发错误。
【解决方案3】:

更改重复查找SQL:

SELECT MAX(Title) as Count
FROM maindatabase.animelist
GROUP BY Title  , NumOfEpis, Description

如果 Count > 1 ,则存在重复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 2013-01-14
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 2012-12-07
    相关资源
    最近更新 更多