我有以下两个MySQL表:
questions:
question_id (PK, AI), module_id (FK), author_id (FK), approved, question, correct_answer_id (FK)
answers:
answer_id (PK, AI), question_id (FK), answer
我希望能够在'questions'表格中插入新行,在'answers'表格中插入多行。
'answers'表中的新行应该与'questions'行中新生成的'question_id'值具有相同的'question_id'。此外,'questions'表中的'correct_answer_id'字段应该等于'answers'表中插入的第一行的'answer_id'。
除了以下步骤之外,还有更有效的方法吗?:
代码:
string connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
MySqlConnection conn = new MySqlConnection(connStr);
string queryUpdateQuestions = "INSERT INTO questions (module_id, author_id, approved, question) VALUES (@module_id, @author_id, @approved, @question)";
MySqlCommand cmdUpdateQuestions = new MySqlCommand(queryUpdateQuestions, conn);
cmdUpdateQuestions.Parameters.Add("@module_id", MySqlDbType.VarChar);
cmdUpdateQuestions.Parameters["@module_id"].Value = ddlModules.SelectedValue.ToString();
cmdUpdateQuestions.Parameters.Add("@author_id", MySqlDbType.VarChar);
cmdUpdateQuestions.Parameters["@author_id"].Value = Session["UserID"].ToString();
cmdUpdateQuestions.Parameters.Add("@approved", MySqlDbType.VarChar);
cmdUpdateQuestions.Parameters["@approved"].Value = 'N';
cmdUpdateQuestions.Parameters.Add("@question", MySqlDbType.VarChar);
cmdUpdateQuestions.Parameters["@question"].Value = txtQuestion.Text;
try
{
conn.Open();
cmdUpdateQuestions.ExecuteNonQuery();
}
catch
{
lblError.Text="Unable to add question.";
}
finally
{
conn.Close();
}
//????? = get last question_id in 'questions'
int a = Convert.ToInt32(ddlNoOfAnswers.SelectedValue.ToString());
for (int b=1; b <= a; b++)
{
string queryUpdateAnswers = "INSERT INTO answers (question_id, answer) VALUES (@question_id, @answer)";
MySqlCommand cmdUpdateAnswers = new MySqlCommand(queryUpdateAnswers, conn);
cmdUpdateAnswers.Parameters.Add("@answer", MySqlDbType.VarChar);
cmdUpdateAnswers.Parameters["@answer"].Value = ((TextBox)this.FindControl("txtAnswer" + b)).Text;
cmdUpdateAnswers.Parameters.Add("@question_id", MySqlDbType.VarChar);
cmdUpdateAnswers.Parameters["@question_id"].Value = ?????;
try
{
conn.Open();
cmdUpdateAnswers.ExecuteNonQuery();
}
catch
{
lblError.Text="Unable to add answer.";
}
finally
{
conn.Close();
}
}
//update 'correct_answer_id' in 'questions'
答案 0 :(得分:1)
可以进行一些简化。首先,你需要将所有命令都包含在一个事务中,因为这是经典的情况,其中插入的记录是严格的关系,并且有一些部分完成的记录是没有意义的。
using(MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
using(MySqlTransaction tr = conn.BeginTransaction())
{
...
// MySqlCommand code goes here
...
tr.Commit();
}
}
现在,您可以更改插入问题sql以添加第二个语句,该语句返回插入的最后一个ID
string queryUpdateQuestions = @"INSERT INTO questions (.....);
SELECT LAST_INSERT_ID()";
using(MySqlCommand cmdUpdateQuestions = new MySqlCommand(queryUpdateQuestions, conn, tr))
{
// build the parameters for the question record
......
// Instead of ExecuteNonQuery, run ExecuteScalar to get back the result of the last SELECT
int lastQuestionID = Convert.ToInt32(cmdUpdateQuestions.ExecuteScalar());
..
}
注意在MySqlCommand构造函数中如何传递对当前事务的引用。这对于打开事务的连接是必需的。
第二部分事情有点复杂。添加第二个sql语句的相同技巧也可以应用于插入答案的循环,但如果第一个问题是正确的,则需要向后循环
string queryUpdateAnswers = @"INSERT INTO answers (question_id, answer)
VALUES (@question_id, @answer);
SELECT LAST_INSERT_ID()";
using(MySqlCommand cmdUpdateAnswers = new MySqlCommand(queryUpdateAnswers, conn, tr))
{
// next move the loop inside the using and prepare the parameter before looping to
// to avoid unnecessary rebuild of the parameters and the command
cmdUpdateAnswers.Parameters.Add("@answer", MySqlDbType.VarChar);
cmdUpdateAnswers.Parameters.Add("@question_id", MySqlDbType.Int32);
int lastAnswerID = 0;
// Loop backward so the last answer inserted is the 'correct' one and we could get its ID
for (int b=a; b >= 1; b--)
{
cmdUpdateAnswers.Parameters["@answer"].Value = ((TextBox)this.FindControl("txtAnswer" + b)).Text;
cmdUpdateAnswers.Parameters["@question_id"].Value = lastQuestionID;
lastAnswerID = Convert.ToInt32(cmdUpdateAnswers.ExecuteScalar());
}
....
}
现在您可以运行使用lastAnswerID
更新问题的最后一个命令(最后一点,我认为字段question_id和answer_id是数字类型,而不是varchar,这要求这些字段的参数是Int32而不是varchar)
答案 1 :(得分:0)
是的,您概述的方法效率最高。您需要检索分配给每行INSERTED的AUTO_INCREMENT列的值。但要小心你如何检索这个值。
MySQL提供LAST_INSERT_ID()
功能。这是在成功执行INSERT
语句之后,MySQL提供的用于检索分配给AUTO_INCREMENT列的值的机制。 (使用单例插入,它非常简单;只需在插入后立即调用。)
参考:http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id
许多客户端库提供了内置函数来执行此操作,因此不必准备和执行单独的SELECT语句。 (例如,使用PHP,PDO提供lastInsertId
,mysqli提供$insertid
。可能是MySQL的C#连接器具有类似的功能。)