Возвращать только строки с пустым полем?

У меня есть таблица, в которой одно из полей может быть пустым. Я пытаюсь вернуть только те строки, где это поле пусто. Но я продолжаю получать ошибки, просто делая WHERE field = ""... WHERE field = ''... WHERE field = null

Любые идеи, что мне не хватает?


person Mik0r    schedule 10.01.2011    source источник
comment
Что ты пишешь в ...?   -  person Mark Peters    schedule 11.01.2011
comment
Я думаю, что это иллюстрирует три возможных оператора Where.   -  person Fionnuala    schedule 11.01.2011


Ответы (5)


В SQL совершенно пустое поле называется NULL. Для поиска NULL вы не используете равенство (=), а используете специальный оператор IS NULL:

 SELECT * FROM table WHERE field IS NULL

Access позволяет вам иметь не пустые пустые поля, если вы разрешаете пустые строки, это плохая идея, поскольку это затрудняет визуальное различие между значением NULL и строкой длины 0, поэтому я предлагаю вам не разрешать это в вашем база данных.

person Larry Lustig    schedule 10.01.2011
comment
Возможна строка с пробелами и нулевой длины, поэтому для покрытия всех баз вы можете использовать Trim(field & )=. - person Fionnuala; 11.01.2011
comment
Я приму строки нулевой длины как пустые, но лично я бы не считал строку, дополненную пробелами, пустой. В любом случае, исходя из вопроса, я почти уверен, что проблема OP заключается не в идентификации различных типов пустых строк, а в незнании оператора IS NULL. - person Larry Lustig; 11.01.2011

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

ОБНОВЛЕНИЕ: вот демонстрация того, как «заполнение ANSI» работает в движке базы данных Access (ACE, Jet, что угодно), что так или иначе кажется необходимым (конечно, каждый продукт SQL в стране работает таким образом...?): просто вставьте в любой модуль VBA (Access, Excel, Word и т. д.) или VB6 и запустить (ссылки и т. д. не требуются): если верно, что один пробел равен строке нулевой длины (ZLS) или «неопределенному» количеству пробелы, то вы увидите список Ys:

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) (хотя применяется и другой синоним), который действительно дополняет значения столбца до фиксированной длины...

Какой тип данных имеет NCHAR(10) в конструкторе таблиц Access?

Я не буду правильно отображать в конструкторе таблиц. Пользовательский интерфейс Access все еще отстает от технологии Jet 4.0, таких упущений много. В данный момент у меня не установлен Access — возможно, кто-нибудь может запустить следующий код, открыть .mdb в пользовательском интерфейсе Access и сообщить нам...?

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
person onedaywhen    schedule 11.01.2011
comment
@Remou: он действительно проверяет ZLS или неопределенное количество пробелов. - person onedaywhen; 11.01.2011
comment
Хм? Как? Мне кажется, что он проверяет наличие одного пробела и возвращает ZLS или любое другое количество пробелов, если начальное условие IIf() не соответствует. И он не будет использовать индексы, поэтому мне кажется очень плохой идеей. - person David-W-Fenton; 12.01.2011
comment
@Davide-W-Fenton и @Remou: у вас обоих есть значки MS-Access здесь, на SO, это фундаментальные вещи! Стандартное поведение при сравнении двух строк на равенство заключается в том, что конец завершается более короткими символами пробела. Даже если вы не знали об этом (шокирует!) или на мгновение забыли, вам, конечно же, было бы очень легко проверить это. В таком сообществе, как это, я ожидаю, что вы все равно будете тестировать мой код, рецензировать его и все такое. Но я полагаю, что мне придется опубликовать свое доказательство как действительно простой для запуска код (при условии, что у вас есть любезность, чтобы потрудиться запустить его!) - person onedaywhen; 12.01.2011
comment
Я не знал об этом и считаю это бесполезной вещью. Я никогда не сталкивался с этим, потому что я не разрешаю хранить пробелы в своих таблицах данных. Если все базы данных ведут себя таким образом, я бы сказал, что они неверны, поскольку не существует способа поиска поля с одним пробелом с использованием индекса. И, конечно же, если вы разрешаете хранить пробелы в своем поле данных, это должно что-то означать, и один пробел должен означать что-то отличное от двух. Назовите меня идиотом, если хотите, но это похоже на артефакт древнего хранилища данных в стиле dBase. Конечно, Jet/ACE не дополняет поля до фиксированной длины! - person David-W-Fenton; 19.01.2011
comment
@David-W-Fenton: Назовите меня идиотом, если хотите, но это похоже на артефакт древнего хранилища данных в стиле dBase - это артефакт SQL-92, который сам по себе немного длинноват. Я бы не назвал вас идиотом, но хотел бы отметить, что принятие новой реальности — это то, с чем у вас, похоже, проблемы. - person onedaywhen; 19.01.2011
comment
@David-W-Fenton: я не разрешаю хранить пробелы в моих таблицах данных - я предполагаю, что вы не запрещаете пробелы при любых обстоятельствах, например. один пробел между двумя словами — это нормально, верно? :) Я обычно добавляю ограничение CHECK ко всем текстовым столбцам, чтобы запретить: 1) пробел нулевой длины, 2) начальный пробел, 3) конечный пробел, 4) два последовательных пробела. - person onedaywhen; 19.01.2011
comment
Какой тип данных имеет NCHAR(10) в конструкторе таблиц Access? - person David-W-Fenton; 21.01.2011
comment
@David-W-Fenton: Да, вам понадобится SQL DDL в режиме запросов ANSI-92 для создания таких объектов базы данных. Вам даже может понадобиться OLE DB для обнаружения их присутствия и отображения их свойств. Однако это не означает, что их не существует, и IMO любой уважающий себя специалист по доступу должен быть в состоянии хотя бы описать проблемы, для решения которых они были разработаны. - person onedaywhen; 21.01.2011
comment
@David-W-Fenton: этот ответ дополнительно обновлен кодом для создания нового .mdb с таблицей, содержащей столбец NCHAR(10). Возможно, вы могли бы запустить код, открыть .mdb в Access и рассказать нам, что вы видите? ТИА. - person onedaywhen; 21.01.2011
comment
Я разработчик Access, а не разработчик Jet/ACE. Я хочу задать этот вопрос, чтобы поднять вопрос, ПОЧЕМУ Jet/ACE поддерживает NCHAR(10). Я предполагаю, что это для совместимости с внешними стандартами, которые не имеют никакого значения для разработчика Access. Я не могу понять, зачем мне это когда-либо понадобилось. Можете ли вы придумать причину, по которой я должен побеспокоиться о том, чтобы узнать о функции, которую мне никогда не понадобится использовать, о той, которая введена в механизм базы данных для совместимости с вещами за пределами моей рабочей среды? - person David-W-Fenton; 22.01.2011
comment
@David-W-Fenton: ПОЧЕМУ Jet/ACE поддерживает NCHAR(10) - это тип данных с фиксированной шириной для данных с фиксированной шириной, который чрезвычайно распространен. Большинство стандартных отраслевых идентификаторов, с которыми я сталкиваюсь, имеют фиксированную ширину, например. до сих пор я использовал коды стран ISO 3166-1 alpha-3, коды валют ISO 4217 и отраслевые коды SIC. - person onedaywhen; 24.01.2011
comment
@David-W-Fenton: Можете ли вы придумать причину, по которой я должен потрудиться узнать о функции, которую мне никогда не понадобится использовать - я действительно сказал, что вы должны знать проблемы, для решения которых они были разработаны, т.е. чтобы вы не повторяли одни и те же недостатки в продуктах ваших клиентов. Каковы ваши доводы в пользу знания только подмножества типов данных языка? - person onedaywhen; 24.01.2011
comment
Я использую Jet/ACE только через Access, и, поскольку Access не предоставляет эти типы данных как пригодные для непосредственного использования, я не собираюсь их использовать. Я действительно не понимаю, почему формат данных с переменной длиной выигрывает от наличия опции фиксированной длины. Но, может быть, я даже не понимаю, что это значит (я предполагаю, что фиксированная ширина означает фиксированную ширину, дополненную пробелами, а-ля xBase c. 1988). - person David-W-Fenton; 25.01.2011

Что вы имеете в виду под ошибками?

Но если вы хотите получить только те строки, где поля пусты, попробуйте что-то вроде этого:

SELECT * FROM MyTable WHERE LTRIM(RTRIM(ISNULL(MyField, ''))) = ''
person Stephen Wrighton    schedule 10.01.2011
comment
Для доступа вы должны использовать Nz, а не ISNULL (MyField, ''). IsNull не принимает более одного аргумента. - person Fionnuala; 11.01.2011
comment
Это правда. Конечно, я не пользуюсь доступом, поэтому я склонен забывать подробности того, как Access истязает SQL. - person Stephen Wrighton; 11.01.2011
comment
Все механизмы баз данных имеют вариации диалекта SQL. -1 за публикацию ответа без доступа. - person David-W-Fenton; 12.01.2011
comment
хорошее решение, путем предварительной квалификации значения NULL, превращения в пустую строку, а затем обрезки обеих сторон гарантирует, что он получит строку символов для теста final = ''. - person DRapp; 10.03.2011

В вашем запросе есть три предложения WHERE? Если это так, измените вторые два на ИЛИ

person Parris Varney    schedule 10.01.2011

Да, я столкнулся с тем же. Но, наконец, я попробовал следующий запрос mysql, он сработал и спас меня.

  SELECT * from your_table_name WHERE field_name IS NULL;

Продолжайте с этим запросом, он выберет только пустые строки.

person Deepak N    schedule 25.11.2017