0

主キー セッション ID を持つセッション マークを持つ 3 つのテーブルと、主キーとして学生 ID を持つ別のテーブル学生と、外部キーとして学生 ID とセッション ID を持つ 3 番目のテーブル データがあることを知る必要があります。ここで、マークがセッション マーク テーブルに格納されるように、グリッド ビューで各生徒のマークを更新する必要があります。私はこのクエリを使用しています

        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();

しかし、このクエリは、グリッド ビューに配置されているマークを更新する必要がある各行に同じマークを追加しています。どこの句に問題があると思いますか。

4

1 に答える 1

1

SQL スキーマがどのように見えるかは非常に不明確ですが、更新ステートメントでは、それ以降のすべてFROMが何の目的にも使用されていません。あなたのWHERE句は言及していないSessionalMarksので、ループをループするたびに、そのテーブルのすべての行をfor更新しています。

これら 3 つのテーブルの 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();
    }
}
于 2012-05-13T16:50:20.373 に答える