Восклицательные знаки в запросе SQL

Я читаю этот запрос и наткнулся на строку, в которой я не понимаю, вот эта строка

[FETT List]![FETT Search]
  1. FETT List — это таблица
  2. Поиск FETT — это столбец в списке FETT.

Кто-нибудь может объяснить, что означает восклицательный знак?

Спасибо


person ChickSentMeHighE    schedule 18.05.2010    source источник
comment
Пожалуйста, добавьте соответствующие теги к вашему вопросу. Я добавил ms-access, потому что думаю, что это в Access, но могу ошибаться. Пожалуйста, убедитесь, что все в порядке.   -  person Will Marcouiller    schedule 18.05.2010
comment
В этом вопросе нет ничего специфичного для версии 2007, поэтому на самом деле ms-access является адекватным тегом (хотя в вопросе можно упомянуть версию 2007).   -  person David-W-Fenton    schedule 21.07.2010


Ответы (3)


Обычно вы видите это в коде MS Access (восклицательный знак, точка для SQL-сервера). Вы можете ссылаться на столбец с помощью table.column или, если вы дадите таблице псевдоним, то с помощью alias.column. Вы можете сделать это, если хотите быть конкретными при использовании соединений, или вам может потребоваться сделать это, когда две (или более) таблицы в запросе/объединении имеют одинаковое имя столбца в каждой таблице.

person Thyamine    schedule 18.05.2010
comment
! — это нестандартный способ указания полей в инструкциях SQL в Access. Это обрабатывается, но теперь хорошо, так как [Table]![Field] назначается псевдоним на лету в QBE, а Table.Field наследует имя поля (т. е. без псевдонимов). - person David-W-Fenton; 19.05.2010

Что ж, каждый день узнаешь что-то новое!

Первоначально я планировал объяснить, что если бы вы сказали, что ссылка была [Формы]![Список FETT]![Поиск FETT], то это было бы легко объяснить как ссылку на элемент управления [Поиск FETT] на [ Список FETT]. Но без родительской коллекции (либо Reports, либо Forms) это не выглядит как действительная ссылка в любом контексте в операторе SQL.

Но потом я решил проверить это и обнаружил (к моему удивлению), что этот оператор SQL считается допустимым в форме Access:

  SELECT [tblCustomer]![LastName] AS LastName 
  FROM tblCustomer;

В Access это на 100% эквивалентно этому оператору SQL:

  SELECT tblCustomer.LastName 
  FROM tblCustomer;

…поэтому я не понимаю, зачем кому-то это писать, за исключением случаев, когда они забыли контекст (или вообще никогда не понимали его). Это может быть случай неправильного наложения псевдонимов, но это не то, что я считаю хорошим тоном.

Теперь длинный ответ на общий вопрос о ! (челка) и . (точка):

Как правило, в Access оператор bang определяет набор по умолчанию объекта и его элементов. Оператор точки описывает объект и его методы, свойства и члены.

Это для Access и применяется к объектам Access и объектной модели для Access.

Но вы также используете SQL в Access, поэтому у вас также есть TableName.FieldName в SQL, где оператор точки разделяет элемент в коллекции по умолчанию. TableName.FieldName можно считать сокращением от TableName.Fields("FieldName"), поскольку вы обнаружите, что Forms!MyForm!MyControl эквивалентно Forms!MyForm.Controls("MyControl"). Но это правило не применяется в SQL — TableName.Fields("FieldName") не является допустимым SQL, допустимым является только TableName.FieldName.

Таким образом, вы должны четко понимать, какая парадигма управляет пространством имен, в котором вы работаете, т. е. пространство имен Access или пространство имен SQL.

Forms!MyForm также эквивалентен Forms.Item("MyForm"), поэтому сверхдлинная форма будет Forms.Items("MyForm").Controls("MyControl"). Обратите внимание, что оператор взрыва является сокращением для более длинной версии с оператором точки, поэтому оператор взрыва довольно часто используется вместо оператора точки. Также обратите внимание, что более длинная форма в конечном итоге используется, когда вам нужно сослаться на элемент, имя которого хранится в переменной, что невозможно с оператором взрыва:

  Dim strForm As String

  strForm = "MyForm"
  ' This is OK
  Debug.Print Forms(strForm).Controls.Count
  ' This is not
  Debug.Print Forms!strForm.Controls.Count

Кроме того, в коде VBA корпорация Майкрософт предприняла некоторые меры, чтобы скрыть это различие в формах и отчетах, где раньше считалось, что Me!MyFavoriteControl допустимо в качестве ссылки на элемент управления, а Me.MyFavoriteControl допустимо только в качестве ссылки на пользовательское свойство (или модуль). -level переменная, которая будет членом объекта). Вы также можете неразумно назвать функцию или подпрограмму MyFavoriteControl, и на нее можно ссылаться с помощью оператора точки.

Но с введением VBA MS представила неявно созданные (и поддерживаемые) скрытые оболочки свойств для всех элементов управления, чтобы вы могли использовать оператор точки. У этого было одно огромное преимущество — проверка ссылок на элементы управления во время компиляции. То есть, если вы наберете Me.MyFavoriteControl, а в пространстве имен формы/отчета нет ни элемента управления с таким именем, ни какого-либо другого члена с таким именем, то вы получите ошибку времени компиляции (действительно, вы будете сообщено об ошибке, как только вы покинете строку кода, в которой допустили ошибку). Итак, если у вас был этот код:

  Debug.Print Me.Control1

... и вы переименовали Control1 в MyControl, вы получите сообщение об ошибке при следующей компиляции кода.

Что может быть недостатком проверки во время компиляции? Ну, несколько вещей:

  1. код становится труднее понять программисту с первого взгляда. В прошлом Me!Reference означал элемент в коллекции по умолчанию формы/отчета (которая представляет собой объединение коллекций Fields и Controls). Но Me.Reference может быть элементом управления, или полем, или пользовательским свойством, или общедоступной переменной уровня модуля, или общедоступной подпрограммой/функцией, или, или, или... Таким образом, он жертвует непосредственной понятностью кода.

  2. вы зависите от неявного поведения VBA и его компиляции. Хотя обычно это нормально (особенно если вы заботитесь о своем коде), VBA компиляция очень сложна и может быть повреждена. На протяжении многих лет опытные разработчики сообщали, что использование оператора точки делает код более подверженным повреждению, поскольку он добавляет еще один слой скрытого кода, который может не синхронизироваться с частями приложения, которые вы можете изменить явно.

  3. поскольку вы не можете контролировать эти неявные оболочки свойств, когда они идут не так, вам приходится заново создавать объект, несущий модуль, с нуля (обычно SaveAsText достаточно, чтобы устранить повреждение без потери чего-либо).

Таким образом, многие опытные разработчики (включая меня) не используют оператор точки для элементов управления в формах/отчетах.

Это не такая большая жертва, как некоторые могут подумать, если вы используете стандартный набор соглашений об именах. Например, с привязанными элементами управления в формах разрешите им использовать имена по умолчанию (т. е. имя поля, к которому привязан элемент управления). Если я не ссылаюсь на элемент управления в коде, я никогда не меняю его имя. Но когда я впервые ссылаюсь на него в коде, я меняю его имя, чтобы имя элемента управления отличалось от имени поля, к которому он привязан (это устранение неоднозначности имеет решающее значение в определенных контекстах). Итак, текстовое поле MyField становится txtMyField в тот момент, когда я решаю сослаться на него в коде. Единственный раз, когда я когда-либо менял имя поля после написания кода, это если я каким-то образом решил, что поле было названо неправильно. В этом случае достаточно просто выполнить поиск/замену.

Некоторые утверждают, что они не могут отказаться от Intellisense, но это неправда, что вы полностью отказываетесь от него, когда используете оператор взрыва. Да, вы отказываетесь от действительно интеллектуального Intellisense, то есть версии, которая ограничивает список Intellisense методами/свойствами/членами выбранного объекта, но мне это не нужно для этого — мне нужен Intellisense для экономии нажатий клавиш, и с помощью Ctrl+ПРОБЕЛ вы получите полный список Intellisense, который автоматически дополняется так же, как контекстно-зависимый Intellisense, а затем может сократить набор текста.

Еще одна область путаницы с точкой и взрывом связана с наборами записей DAO в коде VBA, в котором вы используете оператор точки для SQL, который вы используете для открытия набора записей, и оператор взрыва для ссылки на поля в результирующем наборе записей:

  Dim rs As DAO.Recordset

  Set rs = CurrentDB.OpenRecordset("SELECT MyTable.MyField FROM MyTable;")
  rs.MoveFirst
  Debug.Print rs!MyField

  rs.Close
  Set rs = Nothing

Если вы помните, в каком пространстве имен вы работаете, это не так запутанно — точка используется в операторе SQL, а удар — в коде DAO.

Итак, резюмируя:

  1. в SQL вы используете оператор точки для полей в таблицах.

  2. в формах и отчетах вы используете оператор взрыва для элементов управления и оператор точки для свойств/методов (хотя вы также можете использовать оператор точки, но это не обязательно рекомендуется).

  3. в коде VBA ссылки на элементы управления в формах и отчетах могут использовать либо точку, либо удар, хотя точка может быть подвержена возможному повреждению кода.

  4. в SQL вы можете увидеть использование оператора bang, но только если есть ссылка на элемент управления в форме или отчете Access в форме Form!FormName!ControlName или Report!ReportName!ControlName.

  5. в коде VBA, работающем с наборами записей DAO, вы можете увидеть как оператор точки, так и оператор удара, первый для определения SQL, который используется для открытия набора записей, а второй — для ссылки на поля в результирующем наборе записей после его открытия.

Это достаточно сложно для вас?

person David-W-Fenton    schedule 18.05.2010
comment
Это самый длинный ответ, который я когда-либо видел на SO. - person msarchet; 21.07.2010
comment
Я писал гораздо дольше, чем это! - person David-W-Fenton; 21.07.2010

Я думаю, что восклицательный знак — это всего лишь условный разделитель.

В Oracle PL/SQL вы используете точку:

[Список FETT].[Поиск FETT]

Любые другие подсказки?!

person UltraCommit    schedule 18.05.2010
comment
Разрешает ли Oracle пробел в имени таблицы/столбца? Я думаю, что в Oracle это, вероятно, будет FETT_List.FETT_Search. - person FrustratedWithFormsDesigner; 18.05.2010
comment
Да, Oracle допускает использование пробелов в имени таблицы или столбца, НО вы должны заключить всю строку в кавычки, как в следующем примере: CREATE TABLE goofy (мой столбец VARCHAR2 (1000)); - person UltraCommit; 18.05.2010
comment
Обратите внимание на пробел между словом ‹my› и словом ‹column› - person UltraCommit; 18.05.2010
comment
Другой пример: CREATE TABLE super mario land (мой столбец VARCHAR2 (1000)); - person UltraCommit; 18.05.2010
comment
В Jet/ACE SQL скобки используются для полей с пробелами или нестандартными символами. ! является нестандартным использованием, хотя Access адаптируется к нестандартному и интерпретирует его полукорректно. - person David-W-Fenton; 19.05.2010