问题 删除条款'WHERE <>' not working

半人马座

成员
已加入
2017年12月17日
留言内容
12
地点
休斯顿
编程经验
3-5
我今天加入了C#Developer,这是我的第一篇文章。大家好!
我正在使用MS Access作为后端以及使用VS 2017作为前端的C#Win Form创建数据库。我在使用DELETE子句删除表中的行时遇到问题。

背景信息:
用户在名为Srch_Txtbx的文本框中输入搜索词,然后单击搜索按钮,其中将根据用户的搜索文本过滤我的DataGridView列表。因此,保留了具有用户搜索词的DataGridView内任何列中的任何行,而所有其他行均被过滤掉。然后,我在单独的临时表(原始副本)中删除不等于用户文本条目的行。顺便说一句,我正在使用原始表的副本(临时表),因为我正在基于文本框和组合框选择删除行。使用临时表使我可以基于其他组合框和文本框选择来过滤组合框,但是我遇到的问题是仅删除了类似于文本条目的行。

作为一个简单的例子:
用户输入搜索词:BIT-1000
我的DataGridView过滤器正确地显示仅对应于TAG_NAME列的一行。我的临时表应该完全相同,只显示一行包含TAG_NAME BIT-1000的行。相反,它会删除TAG_NAME以BIT开头的所有行,但保留BIT-1000行和TAG_NAME并非以BIT开头的所有其他行。请参阅下面的代码。我正在使用 <>操作员,但无法正常工作。我也尝试使用NOT LIKE代替<>那给我的结果和<>。我究竟做错了什么?

这是我的代码:

使用(OleDbCommand cmd = dbConn.CreateCommand())
{
dbConn.Open();
cmd.CommandText = "从[Temp_Tbl]删除" +
"WHERE [IO_CARD] <> '"+ Srch_Txtbx。文字+"'" +
" AND [PLC_PANEL] <> '"+ Srch_Txtbx。文字+"'" +
" AND [SLOT_NO] <> '"+ Srch_Txtbx。文字+"'" +
" AND [CHANNEL_NO] <> '"+ Srch_Txtbx。文字+"'" +
" AND [TAG_NAME] <> '"+ Srch_Txtbx。文字+"'";


cmd.Connection = dbConn;
cmd.ExecuteNonQuery();
dbConn.Close();
}
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,525
地点
悉尼,澳大利亚
编程经验
10+
您的SQL代码告诉数据库删除所有指定列都不等于指定值的记录。如果指定的值是"BIT-1000"那么这将导致所有记录中没有列等于"BIT-1000"被删除。您说某列等于的记录"BIT-1000"不会被删除,任何以"BIT"但不等于"BIT-1000"被删除。那正是您应该期望该SQL代码发生的事情。我怀疑SQL并不能真正代表您想要完成的工作。我怀疑您真正想要的是'='而不是'<>'and OR而不是AND。我将以我认为的方式重写您的代码,并记下我在VS中编写SQL代码以提高可读性的方式,以及在论坛中如何格式化代码以提高可读性:
var sql = "DELETE FROM [Temp_Tbl]
    WHERE [IO_CARD] = @IO_CARD
    OR [PLC_PANEL] = @PLC_PANEL
    OR [SLOT_NO] = @SLOT_NO
    OR [CHANNEL_NO] = @CHANNEL_NO
    OR [TAG_NAME] = @TAG_NAME";

using (OleDbCommand cmd = dbConn.CreateCommand(sql, dbConn))
{
    cmd.Parameters.AddWithValue("@IO_CARD", Srch_Txtbx.Text)
    cmd.Parameters.AddWithValue("@PLC_PANEL", Srch_Txtbx.Text)
    cmd.Parameters.AddWithValue("@SLOT_NO", Srch_Txtbx.Text)
    cmd.Parameters.AddWithValue("@CHANNEL_NO", Srch_Txtbx.Text)
    cmd.Parameters.AddWithValue("@TAG_NAME", Srch_Txtbx.Text)

    dbConn.Open();
    cmd.ExecuteNonQuery();
    dbConn.Close();
}

请注意,此处使用格式标记来使代码段更易读。在代码中,最重要的是,请注意对SQL代码所做的更改,以达到我认为您实际上要实现的目的,即删除任何列与指定值匹配的任何行。还请注意,使用多行字符串文字可以使SQL代码更具可读性。最后,请注意使用参数将值插入SQL代码。您绝不应该使用字符串连接来执行此操作,因为有很多事情可能出错。有些可能导致应用程序崩溃,有些则可能导致数据损坏或丢失。不幸的是,Access不支持多次使用相同的参数,因此此示例需要五个具有相同值的参数。我的博客上有一篇有关ADO.NET参数的文章,您可以在下面的我的签名中找到一个链接。
 

半人马座

成员
已加入
2017年12月17日
留言内容
12
地点
休斯顿
编程经验
3-5
感谢您的回复jmcilhinney。我将尝试您的解决方案,但实际上我的代码可以工作。我遇到的问题是我有太多连续的AND行。我相信上限是23或类似的数字。我在上一篇文章中显示的代码并未显示完整的代码,因此这是一个解决方法。我还将WHERE语句更改为:

"不在[IO_CARD] ='"+ Srch_Txtbx。文字+"'AND NOT [PLC_PANEL] ='"+ Srch_Txtbx。文字+"'" + ....etc.

这实际上是有效的,除非当Srch_Txtbx.Text的值为空或没有值时。当它为空时,出于某种原因保留该行,这不是我想要的。如果整个行不具有Srch_Txtbx.Text的值,但我不认为会保留该行,但是如果其中一个列单元格为空,则将其保留。再次,我将尝试您的解决方案。非常感谢您的反馈。
 

半人马座

成员
已加入
2017年12月17日
留言内容
12
地点
休斯顿
编程经验
3-5
我用Delete语句解决了大多数问题,但其中一个delete语句却产生了一些奇怪的结果。在下面的代码中,所有我的DELETE语句都按我希望的方式执行,除了最后一个以-开头的语句> 如果(cntrl_selection =="Instr_Type_Cbx")。例如,如果Instr_Type_Cbx.Text的值为FLOW XMTR,则应删除Temp_Tbl表中在INSTRUMENT_TYPE列中没有文本FLOW XMTR的所有行,但事实并非如此。我很困惑为什么要这样做b / c,除了表列名称和组合框名称之外,下面的所有4个if块都是相同的,但是只有前3个if块可以工作。最后一个过滤列INSTRUMENT_TYPE没有。我在删除语句中尝试了以下更改,以查看是否有帮助,但没有成功:

1)cmd.CommandText ="从[Temp_Tbl]删除[INSTRUMENT_TYPE]不喜欢'"+ Instr_Type_Cbx.Text +"'"; //与下面的if块中的内容没有区别
2)cmd.CommandText ="在[INSTRUMENT_TYPE]的[Temp_Tbl]中删除<> '"+ Instr_Type_Cbx.Text +"'"; //与下面的if块中的内容没有区别

有谁知道为什么会这样吗?只是没有意义。感谢您的帮助。


我当前的代码:
--------------------

//如果if块正常工作
如果(cntrl_selection =="IO_Card_Cbx")
{
使用(OleDbCommand cmd = dbConn.CreateCommand())
{
dbConn.Open();
cmd.CommandText = "从[Temp_Tbl]删除不在[IO_CARD] ='"+ IO_Card_Cbx.Text +"'";
cmd.ExecuteNonQuery();
dbConn.Close();
}
}



//如果if块正常工作
如果(cntrl_selection =="PLC_Pnl_Cbx")
{
使用(OleDbCommand cmd = dbConn.CreateCommand())
{
dbConn.Open();
cmd.CommandText = "从[Temp_Tbl]删除而不在[PLC_PANEL] ='"+ PLC_Pnl_Cbx.Text +"'";
cmd.ExecuteNonQuery();
dbConn.Close();
}
}



//如果if块正常工作
如果(cntrl_selection =="IO_Type_Cbx")
{
使用(OleDbCommand cmd = dbConn.CreateCommand())
{
dbConn.Open();
cmd.CommandText = "从[Temp_Tbl]删除,而不是[IO_TYPE] ='"+ IO_Type_Cbx.Text +"'";
cmd.ExecuteNonQuery();
dbConn.Close();
}
}



//如果if块正在删除错误的行和尚未删除的行
//已删除,即使我删除了列行中的某些信息,
//在我的WHERE中没有关于这些列的任何内容。

如果(cntrl_selection =="Instr_Type_Cbx")
{
使用(OleDbCommand cmd = dbConn.CreateCommand())
{
dbConn.Open();
cmd.CommandText = "从[Temp_Tbl]删除,而不是[INSTRUMENT_TYPE] ='"+ Instr_Type_Cbx.Text +"'"; //对于此示例,Instr_Type_Cbx.Text = FLOW XMTR
cmd.ExecuteNonQuery();
dbConn.Close();
}
}
 

半人马座

成员
已加入
2017年12月17日
留言内容
12
地点
休斯顿
编程经验
3-5
我终于发现了我的错误。在我的delete语句中,我没有处理列单元格为null的情况。更正后的DELETE语句如下:


cmd.CommandText ="从[Temp_Tbl]的位置删除(不是[INSTRUMENT_TYPE] ='"+ Instr_Type_Cbx.Text +"'OR [INSTRUMENT_TYPE]为NULL)";


其他3个DELETE语句起作用的原因是b / c都具有值(没有一个为null)。在我看来,我不得不添加 或[INSTRUMENT_TYPE]为NULL 使其符合我的DELETE语句中的WHERE标准。我不必添加 不为空 当我过滤一个等于组合框值的字段以使其忽略空单元格时,请按照SELECT语句中的WHERE条件执行操作,但是当它是DELETE语句时,则执行此操作。是否有原因或我做错了什么?
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,525
地点
悉尼,澳大利亚
编程经验
10+
如果字段包含NULL,则它不包含任何值,因此与值的比较(无论是相等还是不相等)不能为TRUE。如果X为NULL,则'X = @SomeValue'或'X<>@SomeValue'为TRUE。如果您尝试将记录与值匹配,那么您将固有地排除NULL,但是如果您尝试将记录与NOT值匹配,那么您还将排除NULL。如果您有三个记录,其中X列分别包含TRUE,FALSE和NULL,则'X = TRUE'的过滤器将仅匹配第一条记录,而'X =的过滤器<>TRUE”将仅匹配第二条记录。与值的比较(正或负)都不会匹配第三条记录。

显然,特定的数据库可以以不同的方式实现事物,但是我所描述的似乎是实现它的常用方法。
 
最佳 底部