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 con
、SqlCommand
和 SqlDataAdapter
):
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 值...转换为数据类型 int 时转换失败
在sql server数据库中将一个nvarchar类型的空值转换成decimal(18,3)类型