T-SQL, on delete cascade засада, как избежать?

Eugenia_2005

Скрипт простейший, ловит ошибку 1785 во всех версиях (и в 2008м тоже):
create table A
(
id int primary key
)
go
create table B
(
id int primary key,
aid1 int references A(id) on delete cascade,
aid2 int references A(id) on delete cascade
)
go
И вот необходимо этой ошибки избежать
Помогите пожалуйста =)

SPARTAK3959

С хранением графов в базах данных всегда проблема...

klyv


This is a restriction in all versions of SQL Server that supports cascading constraints. You will have to implement the cascade action using triggers or in your SPs that perform the data modifications.

Eugenia_2005

Да это и не граф в общем-то. Простейший случай - первая таблица пользователи, а вторая - кто кого смотрел. Как гости в одноклассниках. Получается в ней надо две ссылки на пользователей. Такая вот засада.
Че делать не знаю. Хотелось бы шоб автоматом каскадно все удалялось.

Alexander08

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

Eugenia_2005

Совершенно не представляю, как это разбить?

Alexander08

опиши подробнее что нужно. или юзай тригеры как заметили раньше

Eugenia_2005

Ну вот как я сказал - есть таблица пользователей. И нужно учитывать, кто кого смотрел. Вот простейшая реализация - две таблицы:
create table Users
(id int primary key)
create table UserViews
(
id int primary key,
Who int references Users(id) on delete cascade,
Whom int references Users(id) on delete cascade
)
Так сделать было бы замечательно, но нельзя. Вот как бы обойти. Получается - либо FK заменить на триггеры, либо в процедуре удаления учитывать зависимость. Или можно что-то еще придумать?

klyv

разбей на несколько таблиц
такое будет неразумно и не поможет.

klyv

CREATE TRIGGER ON Users AFTER DELETE AS
DELETE FROM UserViews FROM deleted WHERE Who = deleted.id or Whom = deleted.id
DELETE FROM Users FROM deleted WHERE Users.id = deleted.id
и будет тебе счастие

Eugenia_2005

Для этого триггера нужно FK отменить.
Лучше уж тогда процедуру удаления усложнить.
Слушай, а что значит магическая конструкция "delete from table1 from table2"? после таблицы же сразу where-кляуза должна быть.

klyv

Для этого триггера нужно FK отменить.
не надо - только cascade убрать
Слушай, а что значит магическая конструкция "delete from table1 from table2"? после таблицы же сразу where-кляуза должна быть.
RTFM.
UPDATE table SET column=value FROM othertables  
не смыщает? Замени UPDATE-SET на DELETE-FROM.

pitrik2

не смыщает? Замени UPDATE-SET на DELETE-FROM.
меня обе конструкции смущают :(
делете я бы сделал без фролм:
DELETE FROM Users WHERE Users.id = deleted.id
и апдейт тоже без фром:
UPDATE table SET column=othertables.value

klyv

делете я бы сделал без фролм:
DELETE FROM Users WHERE Users.id = deleted.id
и апдейт тоже без фром:
UPDATE table SET column=othertables.value
и тебе бы торжественно выдали "multipart identifier cannot be bound"

pitrik2

хех
почитал в инете
оказывается это две фишки t-sql
1) deleted - это таблица
странное решение
не понимаю зачем триггеру срабатывать на пустой делит
2) операции удаления и апдейта джойнят таблицы через доп. from
тоже странное решение, sql создавался как "читаемый" на обычном, человеческом языке язык
а тут нарушение ентого

klyv

1) deleted - это таблица
странное решение
не понимаю зачем триггеру срабатывать на пустой делит
И я не понимаю. И разработчики. Потому deleted никогда не пусто в триггерах на delete.
2) операции удаления и апдейта джойнят таблицы через доп. from
тоже странное решение, sql создавался как "читаемый" на обычном, человеческом языке язык
а тут нарушение ентого
А как иначе указать, из какой таблицы удалять (какую апдейтить)?
имо, вполне читаемо "обнови таблицу, используя данные из..." или "удали из таблицы по данным из..."

pitrik2

имо, вполне читаемо "обнови таблицу, используя данные из..." или "удали из таблицы по данным из..."
ну дык тогда и было бы чтонить типа USING
delete from table1 using table2 where ...
а from from как-то странно
зато когда привыкнешь наверна удобно, не надо лишних слов помнить
и конструкция короче оракла получается
delete from table1 where column = (select value from othertables)

pitrik2

И я не понимаю. И разработчики. Потому deleted никогда не пусто в триггерах на delete.
или ты или мсдн врет :)

These triggers fire when any valid event is fired, regardless of whether or not any table rows are affected.

klyv

или ты или мсдн врет :)
сдаюсь :)
а почему бы и нет? вдруг триггеры используются для контроля доступа к объекту.

nekaya

а совсем по-тупому не хочешь?
сделать две таблицы связей по одному референсу с каскадом в каждой: "кто кого" смотрел и "кого кто смотрел".
это, конечно, задваивание записей, но зато удаляться будет влет.

klyv

вообще не тру.

nekaya

полностью согласен с предыдущим оратором - решение наихреновейшее, хотя и соответствует уровню вопроса :)
Оставить комментарий
Имя или ник:
Комментарий: