更新数据库错误

Posted

技术标签:

【中文标题】更新数据库错误【英文标题】:Update Database error 【发布时间】:2014-02-14 16:45:24 【问题描述】:

我有一个表单,它在文本框中显示选定的 datagridviewrow 数据。我想编辑和更新此表单中的数据,并在用户单击更新时更新并保存到数据表中。 当我单击更新时,我收到一条错误消息: 解析查询时出错。 [令牌行号=1,令牌行偏移量=25,错误令牌=(]

private void editBTN_Click(object sender, EventArgs e)

    bool notEditable = true;
    if (editBTN.Text == "Update")
    
        UpdateDataBase();
        editBTN.Text = "Edit";
        deleteBTN.Visible = true;
        notEditable = true;
    
    else
    
        deleteBTN.Visible = false;
        editBTN.Text = "Update";
        deleteBTN.Visible = false;
        notEditable = false;
    
    firstTxt.ReadOnly = notEditable;
    surenameTxt.ReadOnly = notEditable;
    address1Txt.ReadOnly = notEditable;
    address2Txt.ReadOnly = notEditable;
    countyTxt.ReadOnly = notEditable;
    contactTxt.ReadOnly = notEditable;
    emailTxt.ReadOnly = notEditable;
    postTxt.ReadOnly = notEditable;



private void UpdateDataBase()

    if (MessageBox.Show("Customer information will be updated. This change cannot be undone. Are you sure you want to continue? ", "Confirm Edit", MessageBoxButtons.YesNo) == DialogResult.Yes)
    
        string constring = @"Data Source=|DataDirectory|\LWADataBase.sdf";
        string Query = "update customersTBL set ([First_Name] = '" + this.firstTxt.Text + "',surename= '" + this.surenameTxt.Text + "',[Address Line 1] = '" + this.address1Txt.Text + "',[Address Line 2] = '" + this.address2Txt.Text + "',County = '" + this.countyTxt.Text + "',[Post Code] = '" + this.postTxt.Text + "' , Email = '" + this.emailTxt.Text + "';,[Contact Number] = '" + this.contactTxt.Text + "');";
        SqlCeConnection conDataBase = new SqlCeConnection(constring);
        SqlCeCommand cmdDataBase = new SqlCeCommand(Query, conDataBase);
        SqlCeDataReader myReader;
        try
        
            conDataBase.Open();
            myReader = cmdDataBase.ExecuteReader();
            MessageBox.Show("Customer information has been updated", "Update Sucessful");
            while (myReader.Read())
            

            
            MessageBox.Show("Please exit the Customers window and re-open to update the table");
            this.Close();
            //displays a system error message if a problem is found
        
        catch (Exception ex)
        
            MessageBox.Show(ex.Message);
        

    

【问题讨论】:

首先,您确实需要为此使用参数。但问题出在this.emailTxt.Text + "';,[Contact Number] = '"。在更新命令结束之前,您有一个分号。删除它,它应该可以工作。 你应该使用参数化查询 我删除了分号,但仍然收到相同的错误消息 【参考方案1】:

您的代码存在一些问题。 一个是微不足道的,可以很容易地修复(删除[Contact Number]之前的分号,但还有其他可能更严重的隐藏问题。

首先:记住要始终关闭并丢弃一次性物品 (在这种情况下是连接和命令)。 using 语句确保 由 using 块包围的对象将正确关闭 并在异常情况下处理 第二:使用参数化查询。这避免了 Sql 注入和 解析问题。如果您的一个或多个输入数据包含一个 quote,用于构建 sql 命令文本的字符串连接 将导致无效命令 第三:更新命令作用于表中存在的所有记录 如果您不添加 WHERE 条件。通常 WHERE 条件是 添加以标识需要更新的唯一记录,它是 具有 UNIQUE 索引的字段的值或您的 PRIMARY KEY 桌子。当然,您可以使用 less 更新多个记录 限制性 WHERE 子句,但情况似乎并非如此

第四:对命令使用 ExecuteNonQuery 而不是 ExecuteReader 更新/插入数据库(它同样有效,但为什么要使用 应该保留用于其他用途的方法?)

private void UpdateDataBase(int customerID)

     string constring = @"Data Source=|DataDirectory|\LWADataBase.sdf";
     string Query = @"update customersTBL set [First_Name] = @fname,
                  surename = @sur, [Address Line 1] = @addr1,
                  [Address Line 2] = @addr2, County = @county,
                  [Post Code] = @pcode, Email = @mail, [Contact Number] = @ctNo
                  WHERE customerID = @id";
     using(SqlCeConnection conDataBase = new SqlCeConnection(constring))
     using(SqlCeCommand cmdDataBase = new SqlCeCommand(Query, conDataBase))
     
        try
        
            conDataBase.Open();
            cndDataBase.Parameters.AddWithValue("@fname", this.firstTxt.Text);
            cndDataBase.Parameters.AddWithValue("@sur", this.surenameTxt.Text );
            cndDataBase.Parameters.AddWithValue("@addr1", this.address1Txt.Text );
            cndDataBase.Parameters.AddWithValue("@addr2", this.address2Txt.Text );
            cndDataBase.Parameters.AddWithValue("@county", this.countyTxt.Text );
            cndDataBase.Parameters.AddWithValue("@pcode", this.postTxt.Text );
            cndDataBase.Parameters.AddWithValue("@mail", this.emailTxt.Text );
            cndDataBase.Parameters.AddWithValue("@ctNo", this.contactTxt.Text );
            cndDataBase.Parameters.AddWithValue("@id", customerID );
            int rowsUpdated = cmdDataBase.ExecuteNonQuery();
            if(rowsUpdate == 0)
                MessageBox.Show("No customer found to update");
        
        catch (Exception ex)
        
            MessageBox.Show(ex.Message);
        
    

如您所见,使用参数化查询更难编写带有隐藏问题的坏 sql 文本,并且引用作业被传递给更了解如何格式化参数值的数据库代码。

您需要解决的唯一问题是如何检索 customerID 的值或您可以在 WHERE 子句中使用以唯一标识您的客户记录的其他值

此时,您调用 UpdateDatabase 方法,该方法现在需要一个包含密钥的 UserID 变量来识别表上的用户

private void editBTN_Click(object sender, EventArgs e)

    bool notEditable = true;
    if (editBTN.Text == "Update")
    
        // Here you need to identify uniquely your modified user
        // Usually when you load the data to edit you have this info extracted from your 
        // database table and you have saved it somewhere 
        // (of course the user should not edit in any way this value
        int UserID = ... ???? (from an hidden textbox? from a global variable, it is up to you
        UpdateDataBase( UserID );

【讨论】:

我很高兴您为 OP 输入这些内容。在一个较小的查询中,我可能有主动权。看了这个然后决定,也许我应该回去工作;)史蒂夫一如既往的好答案! 谢谢!生病试一试。正如 Evan 所说,感谢您在很大程度上分析和修复我的代码。 我得到这个错误:方法'UpdateDataBase'没有重载需要0个参数 当然需要获取执行更新所需的UserID的值,并在调用UpdateDatabase方法时传递这个值 当您加载用户的记录并将其放入文本框中时,您可能还检索了表的 PrimaryKey。当您调用 UpdateDatabase 时,应保留此密钥以供重复使用。很难不知道如何检索要编辑的记录以及customersTbl的表结构是什么【参考方案2】:

我认为您将更新结构与插入混淆了。

对于您的更新,它看起来像这样:

更新客户 TBL 集 ([First_Name] = 'data', surename= '',[Address Line 1] = '',[Address Line 2] = '',County = '',[Post Code] = '' , 邮箱 = '';,[联系电话] = '');

你需要一个 where 子句。

Update/Set 不会将更改放入 ()

电子邮件后有一个';'

【讨论】:

我删除了分号。我在哪里写“where”子句? 在 set 子句之后。它当前的编写方式将更新数据库中的所有行。经典的错误。'

以上是关于更新数据库错误的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server修改表的时候出现错误:未更新任何行

无法在我的数据库中更新查询,收到有关可更新查询的错误

Alteryx“更新选项所需的主键”中的雪花插入/更新错误

当我已经更新数据时出现错误“无效更新:无效行数”

某些更新命令无法自动生成数据库返回以下错误意外错误

更新行给出错误操作必须使用可更新查询