只返回具有空字段的行?

3

我有一张表格,其中一个字段可能为空。我想只返回这些字段为空的行。但是我一直在尝试使用 WHERE field = "" ... WHERE field = '' ... WHERE field = null 时遇到错误。

你有什么建议吗?


1
你在 ... 里放了什么? - Mark Peters
我认为这说明了三种可能的Where语句。 - Fionnuala
5个回答

13

在SQL中,一个完全空的字段被称为NULL。对于NULL的搜索,您不使用等号(=),而是使用特殊的运算符IS NULL:

 SELECT * FROM table WHERE field IS NULL

如果允许空字符串,则Access允许您拥有非NULL空字段,但这是一个不好的主意,因为它使得很难区分NULL值和长度为0的字符串,所以我建议在数据库中不允许它。


3
可以存在空字符串和长度为零的字符串,因此为了涵盖所有情况,您可以使用Trim(field & "")=""。该语句不改变原意,但会使内容更通俗易懂。 - Fionnuala
2
我会将长度为0的字符串视为空字符串,但个人认为带有空格填充的字符串并不为空。无论如何,从问题中我很确定OP的问题不是识别不同类型的空字符串,而是不知道IS NULL运算符。 - Larry Lustig

4
SELECT * 
  FROM MyTable 
 WHERE IIF(MyField = ' ', NULL, MyField) IS NULL;

更新:这里有一个演示“ANSI填充”在Access数据库引擎(ACE,Jet等)中的工作方式的示例,这似乎是必要的(肯定每个SQL产品都是这样工作的...?):只需将其粘贴到任何VBA(Access,Excel,Word等)或VB6模块中并运行(不需要引用等):如果一个单一的空格等于零长度字符串(ZLS)或一个'未确定'数量的空格,那么你将看到一个Y列表:

Sub Fundamentals()

  On Error Resume Next
  Kill Environ$("temp") & "\DropMe.mdb"
  On Error GoTo 0

  Dim cat
  Set cat = CreateObject("ADOX.Catalog")
  With cat
    .Create _
        "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=" & _
        Environ$("temp") & "\DropMe.mdb"
    With .ActiveConnection

      Dim SQL As String
      SQL = _
      "SELECT IIF(SPACE(0) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(1) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(2) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(3) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(4) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(5) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(55) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(99) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(255) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(4321) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(54321) = SPACE(1), 'Y', 'N')," & vbCr & _
      "       IIF(SPACE(654321) = SPACE(1), 'Y', 'N');"

      .Execute SQL

      Dim rs
      Set rs = .Execute(SQL)
      MsgBox rs.GetString(, , vbCr)
    End With
    Set .ActiveConnection = Nothing
  End With
End Sub

更新2:

当然,Jet/ACE不会使字段填充到固定长度!

不正确。Access数据库有一个固定宽度的文本数据类型,通常称为NCHAR(n)(虽然有其他同义词),它确实将列值填充到固定长度...

Access表设计器中的NCHAR(10)是哪种数据类型?

我认为它在表设计器中不能正确显示。Access用户界面仍落后于Jet 4.0技术,存在许多这样的遗漏。我目前没有安装Access,也许有人可以运行以下代码,在Access UI中打开.mdb并告诉我们...

Sub AccessNChar()

  On Error Resume Next
  Kill Environ$("temp") & "\DropMe.mdb"
  On Error GoTo 0

  Dim cat
  Set cat = CreateObject("ADOX.Catalog")
  With cat
    .Create _
        "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=" & _
        Environ$("temp") & "\DropMe.mdb"
    With .ActiveConnection

      Dim Sql As String

      Sql = "CREATE TABLE TestNChar (col1 NCHAR(10));"
      .Execute Sql

      Sql = "INSERT INTO TestNChar (col1) VALUES (SPACE(1));"
      .Execute Sql

      Sql = "SELECT LEN(col1) FROM TestNChar;"

      Dim rs
      Set rs = .Execute(Sql)

      MsgBox rs.GetString
    End With
    Set .ActiveConnection = Nothing
  End With
End Sub

什么?怎么回事?在我看来,它似乎是在检查单个空格,并且如果初始的IIf()条件不匹配,它将返回一个ZLS或任意数量的空格。而且它不会使用索引,所以在我看来这是一个非常糟糕的想法。 - David-W-Fenton
@Davide-W-Fenton和@Remou:你们在SO上都拥有MS-Access徽章,这是基本的知识!当比较两个字符串是否相等时,标准行为是用空格字符填充短的字符串。即使你没有意识到这一点(令人震惊!)或者短时间内忘记了,你肯定可以轻松测试。在这样一个社区中,我希望你们总能对我的代码进行测试、同行评审等等。但我想我还是得发布我的证明作为真正易于运行的代码(假设你们有礼貌去运行它!)。 - onedaywhen
@David-W-Fenton:“如果你愿意,可以称呼我为白痴,但这似乎是古老的dBase风格数据存储的产物”——这是SQL-92的产物,本身也有点过时了。我不会称呼你为白痴,但我想指出的是,“拥抱新现实”似乎是你遇到的问题。 - onedaywhen
@David-W-Fenton: “我不允许在我的数据表中存储空格” - 我猜你并不是在所有情况下都禁止空格,比如两个单词之间的一个空格是可以的,对吗? :) 我习惯性地给所有文本列添加CHECK约束来禁止:1)零长度空格,2)前导空格,3)尾随空格,4)连续两个空格。 - onedaywhen
我只会通过Access使用Jet/ACE,由于Access不会直接暴露这些数据类型,因此我不会使用它们。我真的无法理解为什么变长数据格式需要固定长度选项。但也许我甚至不理解它的含义(我假设固定宽度意味着固定宽度,并用空格填充,类似于xBase c.1988)。 - David-W-Fenton
显示剩余8条评论

3
什么是错误?
但是,如果您想获取那些字段为空的行,请尝试类似以下的内容:
SELECT * FROM MyTable WHERE LTRIM(RTRIM(ISNULL(MyField, ''))) = ''

在Access中,您应该使用Nz而不是ISNULL(MyField, '')。IsNull不能接受多个参数。 - Fionnuala
那是真的。当然,我不使用Access,所以我倾向于忘记Access如何折磨SQL的细节。 - Stephen Wrighton
所有的数据库引擎在它们的SQL方言中都有所不同。回答非Access问题扣1分。 - David-W-Fenton
好的解决方案是,通过预先将NULL值转换为空字符串,然后修剪两侧来保证最终的= ''测试中获得字符字符串。 - DRapp

1

是的,我也遇到了同样的问题。但最终我尝试了以下的mysql查询语句,它起作用了并且帮助了我。

  SELECT * from your_table_name WHERE field_name IS NULL;

执行此查询,它将仅选择空行。


1

你的查询语句有三个WHERE子句吗?如果是这样,请将后两个改为OR。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接