更新记录时如何防止数据库中出现重复记录?
How do i prevent duplicate records in my database while updating records?
在我的 mysql table 中我做了这个样子
ControlNum|Title |NumOfEpis|Description|
001 |naruto |500 |some text |
002 |conan |700 |some text |
现在我在 C# 中创建了一个用户控件,允许用户更新除主列之外的所有列"ControlNum"。因此,假设每一列在该用户控件中都有自己的文本框,因此为了避免标题列中的重复,例如,如果用户编辑第 2 行标题并将其放入 "naruto",它也会被重复..所以我创建了这个名为 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 和描述的数量而不真正打算更新标题,我的方法仍然检测到有重复项,因为我逻辑是"if(ctr == 1)"..我想我错过了一些方法或者我在这里采用了错误的方法..所以我希望有人能启发我..很抱歉在这里成为菜鸟Y.Y
更改重复结果 SQL :
SELECT MAX(Title) as Count
FROM maindatabase.animelist
GROUP BY Title , NumOfEpis, Description
如果 Count > 1 ,则存在重复。
您不希望有两个内容相同的标题。这可以通过该列上的 UNIQUE 索引自动实现。但是,如果您不想为此添加索引,则可以将查询更改为
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 returns 仅第一行的第一列(在本例中为 1 ) 而无需构建 MySqlDataReader object
如果您的应用程序支持多个用户,您需要确保在检查重复项和数据库更新之间没有其他用户进行更改。
最简单的方法是按照 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();
}
}
在我的 mysql table 中我做了这个样子
ControlNum|Title |NumOfEpis|Description|
001 |naruto |500 |some text |
002 |conan |700 |some text |
现在我在 C# 中创建了一个用户控件,允许用户更新除主列之外的所有列"ControlNum"。因此,假设每一列在该用户控件中都有自己的文本框,因此为了避免标题列中的重复,例如,如果用户编辑第 2 行标题并将其放入 "naruto",它也会被重复..所以我创建了这个名为 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 和描述的数量而不真正打算更新标题,我的方法仍然检测到有重复项,因为我逻辑是"if(ctr == 1)"..我想我错过了一些方法或者我在这里采用了错误的方法..所以我希望有人能启发我..很抱歉在这里成为菜鸟Y.Y
更改重复结果 SQL :
SELECT MAX(Title) as Count
FROM maindatabase.animelist
GROUP BY Title , NumOfEpis, Description
如果 Count > 1 ,则存在重复。
您不希望有两个内容相同的标题。这可以通过该列上的 UNIQUE 索引自动实现。但是,如果您不想为此添加索引,则可以将查询更改为
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 returns 仅第一行的第一列(在本例中为 1 ) 而无需构建 MySqlDataReader object
如果您的应用程序支持多个用户,您需要确保在检查重复项和数据库更新之间没有其他用户进行更改。
最简单的方法是按照 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();
}
}