SQL 异常:将 nvarchar 值“[anyvalue]”转换为数据类型 int 时转换失败

Posted

技术标签:

【中文标题】SQL 异常:将 nvarchar 值“[anyvalue]”转换为数据类型 int 时转换失败【英文标题】:SQL EXCEPTION : conversion failed when converting the nvarchar value '[anyvalue]' to data type int 【发布时间】:2018-07-01 14:03:36 【问题描述】:

我正在使用 Visual Studio 2008 和 SQL Server 2008,我有一个表 bookdat 包含这些列:

title varchar(200), author varchar(100), publication varchar(200),
accno varchar(200) not null primary key, price int, quantity int

现在在 Visual Studio 中,我正在创建一个搜索数据库函数,用户可以使用任何一列(从复选框)搜索任何数据,并在文本框中输入值以在数据库表中查找该数据。

当我搜索 accno、价格和数量时,此功能效果很好。 但是在搜索标题、作者、出版物时会抛出异常。

我什至尝试将值相应地转换为字符串或整数(使用convert.tostring 等),但没有成功。

我的 C# 代码在这里(我已经在公共类中声明了 SqlConnection conSqlCommandSqlDataAdapter):

private void button3_Click(object sender, EventArgs e)

    if (!string.IsNullOrEmpty(comboBox2.Text) && !string.IsNullOrEmpty(textBox8.Text))
    
        cmd = new SqlCommand("SELECT * FROM bookdat WHERE title=@fdata OR author=@fdata OR publication=@fdata OR accno=@fdata OR price=@fdata OR quantity=@fdata", con);

        if (comboBox2.SelectedIndex == 0)
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
        else if (comboBox2.SelectedIndex == 1)
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
        else if (comboBox2.SelectedIndex == 2)
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
        else if (comboBox2.SelectedIndex == 3)
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
        else if (comboBox2.SelectedIndex == 4)
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
        else if (comboBox2.SelectedIndex == 5)
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);

        da = new SqlDataAdapter(cmd);

        try
        
            DataTable dt = new DataTable();
            con.Open();
            da.Fill(dt);

            cmd.ExecuteNonQuery();

            dataGridView2.DataSource = dt;
            con.Close();

            if (dt.Rows.Count> 0)
            
                MessageBox.Show("Record Found!!");
                comboBox2.Text = "";
                textBox8.Text = "";
            
            else
            
                MessageBox.Show("No Records Found!!");
            
        
        catch (Exception ex)
        
            MessageBox.Show(ex.ToString());
        
    
    else
    
        MessageBox.Show("Please Fill The Required Fields To Find Data !!");
    

【问题讨论】:

你为什么使用一堆嵌套的 if 语句,它们都做同样的事情?那应该是一个单一的声明。但实际上您的代码永远不会工作,因为您使用单个参数来搜索各种数据类型。您确实应该为每个可搜索的属性使用不同的参数。然后使用包罗万象的查询类型来查找数据。 sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries 使用 AddWithValue 一定要小心...blogs.msmvps.com/jcoehoorn/blog/2014/05/12/… @Sami 我不是; 对我的问题投反对票,为什么?? 【参考方案1】:

错误在于以下几行:

cmd.Parameters.AddWithValue("@fdata", textBox8.Text);

隐式转换失败,转成int

cmd.Parameters.AddWithValue("@fdata", Convert.ToInt32(textBox8.Text));

您必须确保 textBox8 中包含文本。

无论如何,您似乎有很多逻辑来完成一项更容易解决的任务。

例如,您的 if 声明可能会更简洁:

if (comboBox2.SelectedIndex == 0 || comboBox2.SelectedIndex == 1 || comboBox2.SelectedIndex == 2 || comboBox2.SelectedIndex == 3 || comboBox2.SelectedIndex == 4 || comboBox2.SelectedIndex == 5)

     cmd.Parameters.AddWithValue("@fdata", textBox8.Text);

【讨论】:

使用这种方式,我现在得到这个异常:输入字符串的格式不正确。 @FrazzerK 是不是同样的例外? 不,这个和我之前面对的不一样。 这是哪个? 异常:输入字符串的格式不正确。指向这一行: cmd.Parameters.AddWithValue("@fdata", Convert.ToInt32(textBox8.Text));【参考方案2】:

这里仍然有很多猜测,因为我们不知道表结构或很多细节,但这是我将如何处理这个问题。

第一步是创建一个存储过程,它可以根据各个列从 bookdat 中查找数据。像这样的东西应该工作。请注意重新编译选项。请参阅我原始评论中的文章,详细了解为什么这在这里如此重要。

create procedure bookdat_Search
(
    @title varchar(50)
    , @author varchar(50)
    , @publication  varchar(50)
    , @accno int
    , @price int
    , @quantity int
) WITH RECOMPILE as begin

    set nocount on;

    SELECT * --explicitly name columns here, not all columns in the table.
    FROM bookdat b
    WHERE title = coalesce(@title, b.title)
        OR author = coalesce(@author, b.author)
        OR publication = coalesce(@publication, b.publication)
        OR accno = coalesce(@accno, b.accno)
        OR price = coalesce(@price, b.price)
        OR quantity = coalesce(@quantity, b.quantity)

end

现在我们有了一种从数据库中检索数据的方法,我们需要设置我们的 dotnet 代码。请注意,我正在使用 USING 语句。这是您应该对继承 IDisposable 接口的对象执行的操作。它确保对象在超出范围时始终得到适当的处理。这对于数据库连接非常重要,否则您将超载连接池。

特别是因为您似乎仍在学习您真正使用有意义的对象名称的语言。仅使用默认编号的名称不是一个好习惯。当您将来必须维护您的代码时,您会疯狂地试图记住哪个文本框是哪个文本框,而名称却毫无意义。

private void button3_Click(object sender, EventArgs e)

    try
    
        if (string.IsNullOrEmpty(comboBox2.Text) || string.IsNullOrEmpty(textBox8.Text))
        
            MessageBox.Show("Please Fill The Required Fields To Find Data !!");
        
        else
        
            using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["YourConnectionString"].ConnectionString))
            
                conn.Open();

                using (SqlCommand cmd = new SqlCommand("bookdat_Search", conn))
                
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    switch (comboBox2.SelectedIndex)
                    
                        case 1:
                            cmd.Parameters.Add("@title", SqlDbType.VarChar, 50).Value = textBox8.Text;
                            break;
                        case 2:
                            cmd.Parameters.Add("@author", SqlDbType.VarChar, 50).Value = textBox8.Text;
                            break;
                        case 3:
                            cmd.Parameters.Add("@publication", SqlDbType.VarChar, 50).Value = textBox8.Text;
                            break;
                        case 4:
                            cmd.Parameters.Add("@accno", SqlDbType.Int).Value = int.Parse(textBox8.Text);
                            break;
                        case 5:
                            cmd.Parameters.Add("@price", SqlDbType.Int).Value = int.Parse(textBox8.Text);
                            break;
                        case 6:
                            cmd.Parameters.Add("@quantity", SqlDbType.Int).Value = int.Parse(textBox8.Text);
                            break;
                    
                    using (SqlDataReader reader = cmd.ExecuteReader())
                    
                        if (reader.Read())
                        
                            MessageBox.Show("Record Found!!");
                        
                        else
                        
                            MessageBox.Show("No Record Found!!");
                        
                    
                
            
        
    
    catch (Exception ex)
    
        MessageBox.Show(ex.ToString());
    

【讨论】:

你说得对,我实现它的方法太复杂了,尽管它并不需要太多。将坚持按主 ID 从该表中搜索数据,无论如何非常感谢您的帮助。是的,我会记住避免使用 Parameter.AddWithValue。另外,我正在测试我的想法,这就是为什么不关心更改文本框名称的原因,再次感谢。【参考方案3】:
 private void button3_Click(object sender, EventArgs e)

    if (!string.IsNullOrEmpty(comboBox2.Text) && !string.IsNullOrEmpty(textBox8.Text))
    
        StringBuilder sb = new StringBuilder();
        sb.Append("SELECT * FROM bookdat WHERE");


       SqlCommand cmd = new SqlCommand(con);

        if (comboBox2.SelectedIndex == 0)
            
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
            sb.Append(" title=@fdata ");
        
        else if (comboBox2.SelectedIndex == 1)
            
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
            sb.Append(" author=@fdata ");
            
        else if (comboBox2.SelectedIndex == 2)
            
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
            sb.Append(" publication=@fdata ");
            
        else if (comboBox2.SelectedIndex == 3)
            
            cmd.Parameters.AddWithValue("@fdata", textBox8.Text);
            sb.Append(" accno=@fdata ");
            
        else if (comboBox2.SelectedIndex == 4)
            
            cmd.Parameters.AddWithValue("@fdata",int.Parse( textBox8.Text));
            sb.Append(" price=@fdata ");
            
        else if (comboBox2.SelectedIndex == 5)
            
            cmd.Parameters.AddWithValue("@fdata",int.Parse( textBox8.Text));
            sb.Append(" quantity=@fdata ");
            
        cmd.CommandText  =sb.ToString();
        da = new SqlDataAdapter(cmd);

        try
        
            DataTable dt = new DataTable();
            con.Open();
            da.Fill(dt);

            cmd.ExecuteNonQuery();

            dataGridView2.DataSource = dt;
            con.Close();

            if (dt.Rows.Count> 0)
            
                MessageBox.Show("Record Found!!");
                comboBox2.Text = "";
                textBox8.Text = "";
            
            else
            
                MessageBox.Show("No Records Found!!");
            
        
        catch (Exception ex)
        
            MessageBox.Show(ex.ToString());
        
    
    else
    
        MessageBox.Show("Please Fill The Required Fields To Find Data !!");
    

【讨论】:

不是答案。只是一堆代码,没有任何解释。没有人应该推荐使用 AddWithValue,因为这是问题的一部分 - 请参阅 this 没问题,可以用别的方法加参数 这种方式不起作用,异常保持不变。 异常是使用AddWithValue引起的可以改成cmd.Parameters.Add(new SqlParameter("@parameterName", value)); محمدالنعيمي 是的,您的编码方式非常有效,非常感谢。我将您的解决方案标记为最佳答案,因为它更直接且易于理解。只是一个改变,你做错了这个陈述: cmd = new SqlCommand(con);它显示重载方法匹配错误,bcuz根据它也需要字符串语句的方法。因此您也可以在此处进行更改。

以上是关于SQL 异常:将 nvarchar 值“[anyvalue]”转换为数据类型 int 时转换失败的主要内容,如果未能解决你的问题,请参考以下文章

将 nvarchar 转换为日期时间/日期后的计算

将 nvarchar 值...转换为数据类型 int 时转换失败

将数据类型 nvarchar 转换为数值异常时出错

在sql server数据库中将一个nvarchar类型的空值转换成decimal(18,3)类型

在 SQL Server 2008 中将 NVARCHAR 转换为 INT 数据类型

在 VB 中声明一个 nvarchar/在 SQL 查询中匹配一个 nvarchar