2013-12-04 2 views
0

Я пытаюсь использовать базу данных для школьного проекта, и я использую триггеры для настройки ссылочной целостности для одной таблицы. У меня есть стол «Адреса», в котором хранится адрес для людей, студий и директоров. Затем у меня есть таблица с названием Address Reference. В этой таблице указывается таблица адресов, и у нее есть два поля: ReferenceID и TableName, чтобы показать, для какой таблицы и строки указан этот адрес. У меня есть Constraint, поэтому TableName всегда будет действительным.Используйте имя столбца для указания предопределенной таблицы

Я пытаюсь настроить триггер, чтобы убедиться, что все вставленные строки действительны, и я могу это сделать, я просто пытаюсь его улучшить. Мой код будет выглядеть так:

SELECT * 
    FROM inserted 
     WHERE ReferenceID IN 
      (SELECT PersonID 
       FROM inserted.TableName) 

Однако я нашел, что мне нужно использовать динамический sql. Поэтому я подумал примерно так:

SELECT * 
    FROM inserted 
     WHERE ReferenceID IN 
      (EXEC('SELECT PersonID FROM' + inserted.TableName)) 

Что не сработало, даже когда я удалил exec.

Я делаю это в SQL Server Management Studio с SQL Server 11.0.3128

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

+0

Зачем вам нужен динамический SQL? Требуется для задания? Кроме того, это очень полезно прочитать по теме: http://www.sommarskog.se/dynamic_sql.html – Anon

+0

Чтобы уточнить, ваш триггер определен в таблице AddressReference? Это триггер AFTER или INSTEAD OF? – swandog

+0

Помните, что таблица «вставлена» может содержать несколько строк, если имеется несколько вложений/обновлений.Что произойдет, если будет несколько строк с разными таблицами? Есть ли в таблице Studio столбец 'PersonID', как было предложено в вашей попытке, или manic sql также изменил имя столбца? – GarethD

ответ

1

Это плохой способ поддержания ссылочной целостности. Есть несколько способов, которыми вы могли бы приблизиться к этому.

Первым будет иметь адресную таблицу, а затем несколько таблиц, содержащих ссылки, например.

CREATE TABLE StudioAddress 
(  StudioID INT NOT NULL, 
     AddressID INT NOT NULL, 
    CONSTRAINT PK_StudioAddress__StudioID_AddressID PRIMARY KEY (StudioID, AddressID), 
    CONSTRAINT FK_StudioAddress__StudioID FOREIGN KEY (StudioID) REFERENCES Studio (StudioID), 
    CONSTRAINT FK_StudioAddress__AddressID FOREIGN KEY (AddressID) REFERENCES Address (AddressID) 
); 

Это поддерживает вашу referenctial целостность без необходимости триггерами, и по-прежнему обслуживает на 1 ко многим.

Другим вариантом будет иметь 3 столбца с нулевым значением в вашей таблице адресов (StudioID, PersonID, DirectorID), каждый с внешним ключом в соответствующую таблицу, вы можете добавить контрольное ограничение, чтобы обеспечить только один из трех полей (если это необходимо).

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


ADENDUM

Если имеет быть сделано с помощью триггеров, то я думаю, вам нужно будет использовать что-то вроде этого:

IF EXISTS( SELECT 1 
      FROM inserted i 
      WHERE NOT EXISTS 
        ( SELECT 1 
         FROM People p 
         WHERE p.PersonID = i.ReferenceID 
         AND  i.TableName = 'People' 
         UNION ALL 
         SELECT 1 
         FROM Studios s 
         WHERE s.StudioID = i.ReferenceID 
         AND  i.TableName = 'Studios' 
         UNION ALL 
         SELECT 1 
         FROM Directors d 
         WHERE d.DirectorID = i.ReferenceID 
         AND  i.TableName = 'Directors' 
        ) 
     ) 
     BEGIN 
      ROLLBACK TRANSACTION; 
      RAISERROR('Referential integrity error', 16, 1); 
     END 

Это по существу проверяет, что для все вставленные/обновленные строки, запись существует с соответствующим идентификатором в соответствующей таблице.

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

+0

К сожалению, хотя это был мой первый выбор, мой профессор хотел создать таблицу таким образом. Это было не для меня. – Dan

Смежные вопросы