Access 2007 триггеры и процедуры эквиваленты? - PullRequest
6 голосов
/ 09 июля 2009

Хорошо, есть ли у кого-нибудь хорошие ресурсы для функций Access 2007, касающихся триггеров или хранимых процедур? Может ли это даже сделать их или что-то похожее на них? Каждый ресурс, который я нашел в справке Microsoft, ссылается на Access 2003, а также на многие справочные руководства в Интернете. В 2007 году все изменилось, поэтому переводить старые справочные руководства немного сложно. Я действительно хотел использовать ms sql, но был вынужден сделать этот небольшой проект в доступе, поэтому любые ресурсы будут полезны.

Круто, все ответы до сих пор были полезны. Просто хотел подтвердить много разрозненных знаний о доступе у меня. Я думаю, что смогу заставить его работать на этот проект. О, и я не могу использовать sql из-за большого количества ... волокиты.

Ответы [ 6 ]

16 голосов
/ 10 июля 2009

хранимые процедуры

Механизм базы данных Access в режиме запросов ANSI-92 поддерживает синтаксис CREATE PROCEDURE (SQL DDL), например.

CREATE PROCEDURE GetCompanies
(
 :company_type VARCHAR(30) = NULL
)
AS
SELECT company_registered_number, organisation_name, company_type
  FROM Companies 
 WHERE company_type = IIF(:company_type IS NULL, company_type, :company_type);

Таким образом, результирующий объект является PROCEDURE и сохраняется в файле базы данных вместе с таблицами. Акцент здесь делается на слове «сохранено» (а не «процедура»), то есть оно «близко к данным». Использование этих объектов способствует хорошему отделению передней части (FE) от задней части (BE), и я имею в виду логический, а не физический; например, SQL-код, хранящийся в коде VBA или в свойствах элемента управления Access Forms, не «близок к данным» и смешивает внутренний «слой» с внешним «слоем» и затрудняет обслуживание SQL-кода. например если вам нужно переименовать столбец в таблице, задача проста, если все, что вам нужно сделать, это просмотреть PROCEDURE s и VIEW s.

Еще одним преимуществом использования PROCEDURE является (или, скорее, было) то, что в сочетании с безопасностью на уровне пользователя (ULS) это может помочь в «удобстве использования». Чтобы использовать пример, часто спрашивают, как добавить столбец созданный_дат в таблицу и сохранить его значение. Добавление DEFAULT текущей временной метки дает вам только часть пути, например

CREATE TABLE Entities (
   entity_ID CHAR(8) WITH COMPRESSION NOT NULL UNIQUE, 
   CONSTRAINT entity_ID__pattern 
      CHECK (entity_ID NOT ALIKE '%[!0-9]%'), 
   entity_name VARCHAR(20) NOT NULL, 
   CONSTRAINT entity_name__whitespace
      CHECK (
             entity_name NOT ALIKE ' %'
             AND entity_name NOT ALIKE '% '
             AND entity_name NOT ALIKE '%  %'
             AND LEN(entity_name) > 0
            ), 
   created_date DATETIME DEFAULT NOW() NOT NULL
);

Но это не мешает явному значению, которое не является текущей отметкой времени. Конечно, мы могли бы добавить ограничение CHECK или Правило проверки, чтобы обеспечить выполнение этого:

ALTER TABLE Entities ADD
   CONSTRAINT entity_created_date__must_be_current_timestamp
      CHECK (created_date = NOW());

Проблема здесь в том, что ограничение CHECK и Правила проверки проверяются на уровне строк, т. Е. Если вы когда-либо пытаетесь изменить другой столбец, ограничение будет кусаться. Не хорошо, так что:

ALTER TABLE Entities DROP
   CONSTRAINT entity_created_date__must_be_current_timestamp;

Что делать? Один из подходов состоит в том, чтобы удалить привилегии из таблицы, чтобы конечные пользователи (и приложения в этом контексте тоже пользователи) не могли INSERT или UPDATE данные таблицы напрямую, а затем создать PROCEDURE s, чтобы данные могли быть изменен и вместо этого предоставит соответствующие привилегии PROCEDURE s, например

CREATE PROCEDURE AddEntity (
   :entity_ID CHAR(8), 
   :entity_name VARCHAR(20)
)
AS 
INSERT INTO Entities (entity_ID, entity_name, created_date) 
VALUES (:entity_ID, :entity_name, NOW());

EXECUTE EXECUTE AddEntity '00000001', 'Black';

Я использую прошедшее время, потому что, как вы, возможно, знаете, команда Access (или это была команда SharePoint? :)) удалила ULS из механизма ACE new-for-Access2007. Я не уверен, что могу порекомендовать использовать устаревшую функцию.

Теперь плохие новости. Многие (большинство?) Люди будут утверждать, что такой PROCEDURE не является процедурой, и у них есть хорошая точка зрения, потому что синтаксис SQL ядра СУБД Access не поддерживает управление потоком, объявление переменных, даже возможность выполнения более одного оператора SQL. Другими словами, PROCEDURE не может содержать процедурный код. Рассмотрим таблицу, которая ссылается на сущности:

CREATE TABLE FlyingEntities (
   entity_ID CHAR(8) WITH COMPRESSION NOT NULL UNIQUE 
      REFERENCES Entities (entity_ID) 
      ON DELETE CASCADE 
      ON UPDATE CASCADE
);

Было бы неплохо иметь PROCEDURE, который может создать строку в сущностях и, необязательно, создать строку в FlyingEntities на основе значения параметра, но это просто невозможно в одном операторе SQL. Поэтому ядро ​​базы данных Access PROCEDURE имеет ограниченную ценность, особенно теперь, когда ULS исчез.

Триггеры

Нельзя обойти стороной тот факт, что ядро ​​базы данных Access не имеет и никогда не имело триггеров. Вопрос в том, нужны ли они вам?

Несмотря на то, что я неравнодушен к простоте ядра СУБД Access, правда состоит в том, что много лет назад я перевел всю «серьезную» работу в более «промышленную мощь» и более совместимые с SQL Standard продукты, в первую очередь SQL Server. Однако в SQL Server я использую триггеры только для двух вещей, обе из которых могут быть выполнены без триггеров (в определенной степени) в ядре базы данных Access.

Первый из этих способов - справиться с тем, что ограничения CHECK SQL Server не поддерживают подзапросы; другими словами, они могут быть на уровне столбца и на уровне строки, но не на уровне таблицы. Ограничения ядра доступа к базе данных CHECK, введенные в Jet 4.0 и все еще присутствующие в ACE (2007), всегда на уровне таблиц ... ну, они в теории. Существует проблема (предполагаемая ошибка), когда они проверяются на уровне строк, когда их следует логически проверять на уровне операторов SQL. Они не поддерживают синтаксис SQL-92 DEFERRABLE, поэтому для этой проблемы не существует обходного пути (кстати, SQL Server испытывает ту же проблему при использовании FUNCTION для обхода ограничения без подзапросов). Не все ограничения CHECK столкнутся с этой проблемой, но ее существование заставляет меня немного насторожиться.

Второе и последнее использование триггеров в SQL Server для меня связано с другим ограничением: страшный «FOREIGN KEY ... может вызывать циклы или несколько каскадных путей» при попытке создать два REFERENCE s для одного и того же ключа, например. это разрешено в движке базы данных Access:

CREATE TABLE Marriages (
   entity_ID_1 CHAR(8) WITH COMPRESSION NOT NULL UNIQUE
      REFERENCES Entities (entity_ID) 
      ON DELETE CASCADE 
      ON UPDATE CASCADE, 
   entity_ID_2 CHAR(8) WITH COMPRESSION NOT NULL UNIQUE
      REFERENCES Entities (entity_ID) 
      ON DELETE CASCADE 
      ON UPDATE CASCADE,
   CONSTRAINT cannot_marry_yourself 
      CHECK (entity_ID_1 <> entity_ID_2)
);

Но перенести это на SQL Server (удалить WITH COMPRESSION и т. Д.), И это не разрешено. В этом случае never_marry_yourself будет предотвращать циклы, но SQL Server выполняет простой подсчет и решает, что 1 + 1 = слишком много. Грубый, но эффективный, я полагаю. Использование триггеров - единственный способ удовлетворительного обходного пути; CASCADE ссылочные действия - особая боль с триггерами.

С другой стороны, ядро ​​базы данных Access в каком-то смысле даже тупее, чем SQL Server, потому что оно вообще не пытается обнаруживать циклы. Если вы создадите цикл, вы не получите предупреждения, и результатом будет гонка за перезапись данных последней и трудная ситуация для отладки.

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

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


О, и не начинайте меня с документацией для ядра базы данных Access. Он фрагментирован, и многие из этих фрагментов со временем исчезли, и многие из них не существовали, например. Я упомянул CHECK ограничения выше, но никогда не было никаких подробностей, просто пара некорректных примеров (все, что я знаю об CHECK ограничениях, которые мне пришлось выучить методом проб и ошибок - то, что существует, на что я не наткнулся еще ?!) И фрагменты, которые существуют, содержат материальные ошибки и ошибки упущения ... даже ошибочно детализирующие функциональность, которой никогда не было! например CREATE TABLE Инструкция из справки Access2007 упоминает временные таблицы с именами NOT NULL ограничений и многостолбцовых NOT NULL ограничений, которые не существуют, но не упоминают DEFAULT или тот факт, что некоторые CONSTRAINT s не реализованы с использованием индексов. Но самое серьезное упущение IMO - это ссылка на выражения ядра базы данных Access, например, IIF() ведет себя не так, как IIf() в VBA, но, похоже, это в настоящее время недокументировано. Справка SQL для Jet 3 имела такой список, никакой версии с тех пор не было, и справка Jet 3 исчезла из MSDN год или два назад. Отсутствие хорошей документации действительно подрывает доверие к движку базы данных Access.

2 голосов
/ 09 июля 2009

Рассмотрим возможность использования Access 2007 в качестве внешнего интерфейса для SQL Express. Если ваш проблемный домен - это то, что может обрабатывать Access JET, SQL Express также может справиться с этим, и вы получаете такие вещи, как триггеры и хранимые процедуры «бесплатно». Самая близкая вещь, которую собственный Access / JET имеет к хранимым процедурам, - это запросы (действие и стандарт), и в родном Access / JET нет ничего похожего на триггер.

Также нет особых проблем с настройкой редакций Express, и Access прекрасно работает в качестве внешнего интерфейса для SQL Express. Вы не заметите большой разницы (за исключением стиля дизайнеров таблиц и тому подобного) при работе с таким бэкэндом, и вам не придется делать это, когда приложение масштабируется так, чтобы в любом случае нуждаться в реальном сервере базы данных.

2 голосов
/ 09 июля 2009

Согласно Википедии :

Microsoft Access - файловый сервер база данных. В отличие от клиентского сервера СУБД, Microsoft Access не реализовать триггеры базы данных, сохраненные процедуры или регистрация транзакций.

Были ли ресурсы, которые вы нашли для 2003, говорили о наших файлах ADP? Я думаю, что они могут быть, в этом случае могут быть связаны с триггерами / процедурами в бэкэнде SQL Server, для чего они и предназначены.

1 голос
/ 09 июля 2009

В Access нет триггера . Это относится ко всем версиям.

1 голос
/ 09 июля 2009

Хранимые процедуры в основном выполняются как запросы в Access. Практически любая документация для 03 будет соответствовать версии 07, поскольку функциональные различия довольно редки.

0 голосов
/ 09 июля 2009

Что касается триггеров, если вы используете проект данных доступа, то у вас нет локальных таблиц, и вы даже не используете jet. В этом случае будут спроектированы триггеры, созданные и написанные на SQL-сервере. Имейте в виду, что когда вы создаете проект данных доступа, вы не можете использовать любой другой сервер базы данных, кроме SQL-сервера. Для этой цели большинство версий office и access имеют версию сервера SQL на компакт-диске. Это изменилось в 2007 году, но, тем не менее, в этом случае вы не можете использовать локальные таблицы с проектами доступа к данным.

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

Если вы используете стандартный файл mdb или accDB и не используете сервер SQL, но используете JET (теперь называется ACE), у вас не будет доступных триггеров.

...