我正在尝试将一个位值(真或假)写入数据库中名为“已处理”的字段中。我目前正在尝试通过传入 bool 值来实现此目的,但收到一条错误消息,指出无法从 varchar 类型转换为 bit。有人能看出我的逻辑是怎么回事吗?
protected void CheckBoxProcess_CheckedChanged(object sender, EventArgs e)
{
bool update;
bool trueBool = true;
bool falseBool = false;
string checkedString = "UPDATE SecureOrders SET processed = '%" + trueBool + "%' WHERE fName LIKE '%" + DefaultGrid.SelectedRow.Cells[2].Text + "%' AND lName LIKE '% " + DefaultGrid.SelectedRow.Cells[3].Text + "%'";
string uncheckedString = "UPDATE SecureOrders SET processed = '%" + falseBool + "%' WHERE fName LIKE '%" + DefaultGrid.SelectedRow.Cells[2].Text + "%' AND lName LIKE '% " + DefaultGrid.SelectedRow.Cells[3].Text + "%'";
CheckBox cb = (CheckBox)sender;
GridViewRow gvr = (GridViewRow)cb.Parent.Parent;
DefaultGrid.SelectedIndex = gvr.RowIndex;
update = Convert.ToBoolean(DefaultGrid.SelectedValue);
orderByString = orderByList.SelectedItem.Value;
fieldString = searchTextBox.Text;
System.Configuration.ConnectionStringSettings connectionString;
connectionString = rootWebConfig.ConnectionStrings.ConnectionStrings["secureodb"];
// Create an SqlConnection to the database.
using (SqlConnection connection = new SqlConnection(connectionString.ToString()))
{
connection.Open();
SqlCommand checkedCmd = new SqlCommand(checkedString, connection);
SqlCommand uncheckedCmd = new SqlCommand(uncheckedString, connection);
dataAdapter = new SqlDataAdapter("SELECT * FROM SecureOrders", connection);
// create the DataSet
dataSet = new DataSet();
// fill the DataSet using our DataAdapter
dataAdapter.Fill(dataSet, "SecureOrders");
DataView source = new DataView(dataSet.Tables[0]);
DefaultGrid.DataSource = source;
if (cb.Checked == true)
{
checkedCmd.ExecuteNonQuery();
}
else
{
uncheckedCmd.ExecuteNonQuery();
}
connection.Close();
}
}
您需要根据真假将位字段设置为
1
或 0
。
所以:
string checkedString = "UPDATE SecureOrders SET processed = 1 WHERE fName LIKE '%" + DefaultGrid.SelectedRow.Cells[2].Text + "%' AND lName LIKE '% " + DefaultGrid.SelectedRow.Cells[3].Text + "%'";
string uncheckedString = "UPDATE SecureOrders SET processed = 0 WHERE fName LIKE '%" + DefaultGrid.SelectedRow.Cells[2].Text + "%' AND lName LIKE '% " + DefaultGrid.SelectedRow.Cells[3].Text + "%'";
此外,正如评论中提到的,直接从用户输入构建 SQL 语句是成为 SQL 注入攻击受害者的最简单方法。在这些情况下,最好使用参数化查询(甚至存储过程)。
....
string checkedString = "UPDATE SecureOrders SET processed = 1 WHERE fName LIKE @p1 AND lName LIKE @p2";
string uncheckedString = "UPDATE SecureOrders SET processed = 0 WHERE fName LIKE @p1 AND lName LIKE @p2";
然后您可以创建参数传递给您的
ExecuteNonQuery
调用
SqlParameter p1 = new SqlParameter("@p1",SqlDbType.Varchar) { Value = string.Format("%{0}%",DefaultGrid.SelectedRow.Cells[2].Text) };
SqlParameter p2 = new SqlParameter("@p2",SqlDbType.Varchar) { Value = string.Format("%{0}%",DefaultGrid.SelectedRow.Cells[3].Text) };
if (cb.Checked == true)
{
checkedCmd.Parameters.Add(p1);
checkedCmd.Parameters.Add(p2);
checkedCmd.ExecuteNonQuery();
}
else
{
uncheckedCmd.Parameters.Add(p1);
uncheckedCmd.Parameters.Add(p2);
uncheckedCmd.ExecuteNonQuery();
}
虽然如果您在 SQL 语句中注入字符串“1”表示 True,“0”表示 False,确实可以解决您的问题,但解决此问题的“正确”方法是参数化您的 SQL 语句并将参数添加到命令对象。然后由框架完成从 VB
Boolean
到 SqlDbType.Bit
的类型转换。
尝试:
string sqlString = "UPDATE SecureOrders SET processed = @Processed WHERE fName LIKE '%' + @FirstName + '%' AND lName LIKE '%' + @LastName + '%'";
并且:
SqlCommand objCmd = new SqlCommand(sqlString, connection);
objCmd.Parameters.AddWithValue("Processed", cb.Checked);
objCmd.Parameters.AddWithValue("FirstName", DefaultGrid.SelectedRow.Cells[2].Text);
objCmd.Parameters.AddWithValue("LastName", DefaultGrid.SelectedRow.Cells[3].Text);
最后:
objCmd.ExecuteNonQuery();
如果您要编写数据驱动的 Web 应用程序,了解如何避免 SQL 注入安全漏洞非常重要。有关更多信息:MSDN 如何:防止 ASP.NET 中的 SQL 注入
在 SQL 中,位值是 1 或 0,而不是“true”或“false”。在更新中将“true”和“false”更改为 1 和 0,应该就可以了。 (注意 0 和 1 也没有引号。)
您的 SQL 语法错误 - 您传递一个字符串作为值来设置
processed
列值,但您不能这样做。
最简单的方法是将您的布尔值转换为 Convert.ToInt16 。这将得出真/假、0 或 1。
布尔值被连接为“true”|“false”。尝试使用三元运算符来显示“1”或“0”:
string checkedString = "UPDATE SecureOrders SET processed = '%" + (trueBool ? "1" : "0") + "%' WHERE fName LIKE '%" + DefaultGrid.SelectedRow.Cells[2].Text + "%' AND lName LIKE '% " + DefaultGrid.SelectedRow.Cells[3].Text + "%'";
您的 SQL 语句并不是尝试设置任何类型的布尔值,而是尝试设置文本
%True%
或 %False%
。
由于您将数据库字段描述为“位”而不是“布尔值”,因此在构造字符串时您可能需要使用类似
"processed = " + (trueBool ? 1 : 0) + "
的内容。但根据您使用的 SQL 服务器,您可能能够摆脱诸如 processed = " + trueBool + "
或 processed = '" + trueBool + "'
之类的内容。
或者,在这种特殊情况下,您可以跳过插值
trueBool
并仅使用完全恒定的字符串,就像大多数其他答案所建议的那样。
另外,顺便说一句,请注意,通过将未经检查的用户输入插入到 SQL 语句中,您将面临错误和 SQL 注入的风险。例如,如果有人输入“O'Brian”作为姓氏,您将收到错误,并且通过更恶意的值选择,他们可能能够更改数据库中的任何内容。
很老的问题,但我希望这可以帮助别人。
要从代码隐藏 C# 将位值写入 sql 数据库,请遵循此示例。
1.- 首先声明一个变量来获取值 0 或 1(在本例中它取决于 Checkbox1 状态):
int isenable = 0;
if (CheckBox1.Checked == true)
{
enable = 1;
}
2.- 然后创建连接、sql 查询并执行它:
string connetionString1 = null;
SqlConnection connection1;
connetionString1 = "Data Source=SERVERNAME;Initial Catalog=Scrapper;Persist Security Info=True;User ID=myUser;Password=Mypassword123";
connection1 = new SqlConnection(connetionString1);
connection1.Open();
SqlCommand command1 = new SqlCommand(
"INSERT INTO usuarios(numgaffete, windowsid, name, enable, email) VALUES ('" + txtgafete.Text + "', '" + txtwindowsid.Text + "', '" + txtname.Text + "', '" + Convert.ToInt16(isenable) + "', '" + Email.Text + "')",
connection1);
command1.ExecuteNonQuery();
请注意,在 SQL INSERT 命令中,您的 int 变量(isenable)必须转换为 int 16,以避免执行命令时出现错误。