更新Sql查询,其中数据来自2个表

时间:2012-05-13 09:13:40

标签: sql c#-4.0

我需要知道我有3个表,其中一个带有主要密钥会话标识的会话标记,另一个表学生具有学生ID作为主键,第三个表数据具有学生ID和会话ID作为外键。 现在我需要在网格视图中更新每个学生的标记,以便标记存储在会话标记表中。  我正在使用此查询

        string hourly1;
        string hourly2;
        string student_id;

        for (int i = 0; i < this.dataGridView1.Rows.Count - 1; i++)
        {
            hourly1 = dataGridView1[1,i].Value.ToString();
            hourly2 = dataGridView1[2,i].Value.ToString();
            student_id = Convert.ToString(dataGridView1[3, i].Value);

            SqlCommand cmd = new SqlCommand("UPDATE SessionalMarks  SET " +
            "SessionalMarks.Hourly1Marks = '" + hourly1 + "'," + "SessionalMarks.Hourly2Marks = '" + hourly2 + "'from Student,DATA  where Student.StudentId=DATA.StudentId AND Student.StudentId='" + student_id + "'", conn);

            conn.Open();
            cmd.ExecuteNonQuery();
            conn.Close();

但是此查询在需要的每一行中添加相同的标记,以更新放置在网格视图中的标记 我认为有一个问题可以让一个人帮助我。

1 个答案:

答案 0 :(得分:1)

您的SQL架构看起来很不清楚,但在更新语句中,FROM之后的所有内容都没有用于任何目的。您的WHERE子句未提及SessionalMarks,因此每次循环执行for循环时,您都会更新该表中所有行。

如果您发布这三个表的SQL架构,它可能有助于我们了解数据的形状并帮助您编写更好的查询。你描述它的方式,听起来像DATA表应该包含每个学生的标记,但你显然把这些数据放在SessionalMarks表中。

但是,除了您提到的代码之外,您的代码还存在一些问题:

  • 您通过将字符串连接在一起来编写SQL查询,看起来这些字符串可能来自用户。这会使您暴露于SQL注入攻击,或者至少如果用户键入'您的程序将会出现错误行为。

  • 您正在重复打开和关闭数据库连接,而不是打开一次并在完成后关闭它。

要解决这些问题,您可能应该(a)使用参数化SQL查询,(b)打开和关闭循环外的数据库连接。

这不完美,但这是一个开始:

// this query needs to be fixed
string query = @"UPDATE SessionalMarks 
                SET SessionalMarks.Hourly1Marks = @hourly1
                   ,SessionalMarks.Hourly2Marks = @hourly2
                FROM Student,DATA
                WHERE Student.StudentId = DATA.StudentId
                AND Student.StudentId = @studentid";

// Make sure we dispose of the SqlCommand when we're finished with it
using (SqlCommand cmd = new SqlCommand(query, conn))
{
    // Create my three parameters, don't need a value yet
    // Need to make sure we have the right SqlDbType specified
    cmd.Parameters.Add( new SqlParameter("@hourly1", SqlDbType.Decimal) );
    cmd.Parameters.Add( new SqlParameter("@hourly2", SqlDbType.Decimal) );
    cmd.Parameters.Add( new SqlParameter("@studentid", SqlDbType.Int) );

    conn.Open();

    try
    {
        // For each row in our DataGridView
        // We could also use foreach(DataGridViewRow row in dataGridView1.Rows)
        for (int i = 0; i < this.dataGridView1.Rows.Count - 1; i++)
        {
            // Fill in our parameters with our values
            cmd.Parameters[0].Value = dataGridView1[1,i].Value.ToString();
            cmd.Parameters[1].Value = dataGridView1[2,i].Value.ToString();
            cmd.Parameters[2].Value = Convert.ToString(dataGridView1[3, i].Value);

            cmd.ExecuteNonQuery();
        }
    }
    finally
    {
        // Close our database connection even if cmd.ExecuteNonQuery() throws
        conn.Close();
    }
}