Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Dmitry S. Kravchenko
Member

Откуда:
Сообщений: 92
В общем, мне надо сделать каскадное обновление, сервер напрямую не дает, а мне надо. Поэтому решил сделать на триггерах.

Я связь-таки сделал, но обновление там не указал.

Я хотел сделать триггер INSTEAD OF UPDATE, который просматривал бы таблицу inserted, вставлял из нее записи в родительсую таблицу, потом переподчинял бы дочерние записи этим новым записям, затем удалял бы из родительской все записи, которые лежат в deleted.

Звучит складно, но получается дилемма.

С одной стороны, я никак не могу установить соответствие между inserted и deleted, так как изменению подвергается именно ключевое поле. Иными словами, я не могу никак узнать, с какого на какое изменено значение.

Само по себе, кстати, парадокс!

С другой стороны, если я вставлю в таблицу еще одно поле, по которому можно было бы отождествлять записи друг с другом, то мне придется наложить на него индекс без повторов, но тогда я не смогу вставить данные из inserted не удалив перед этим данные deleted.

Замкнутый круг!

Как же быть-то? Что, каскадное обновление вообще невозможно на триггерах сделать?

Может есть какое-то поле, типа ROWID, по которому я бы мог идентифицировать строки?

Либо есть возможность временно отключать действие ключей или связи? Транзакции такого не позволяют?

Димс.
7 май 04, 16:30    [668284]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Glory
Member

Откуда:
Сообщений: 104764
С одной стороны, я никак не могу установить соответствие между inserted и deleted, так как изменению подвергается именно ключевое поле. Иными словами, я не могу никак узнать, с какого на какое изменено значение

По идеалогии РСУБД ПК не должен меняться. И никаких парадоксов в этом нет.

Соответствие между inserted и deleted можно сделать если разрешить измененеие только по одной записи. И никакого замкнутого круга опять не получается
7 май 04, 16:33    [668290]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Dmitry S. Kravchenko
Member

Откуда:
Сообщений: 92
Если по идеологии ПК не должен меняться, то зачем тогода ВООБЩЕ могут понадобиться каскадные обновления? Ведь они ВСЕГДА затрагивают ПК!

Димс.
7 май 04, 16:38    [668310]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Glory
Member

Откуда:
Сообщений: 104764
Ведь они ВСЕГДА затрагивают ПК!
Вот для тех не умеет правильно проектировать свои схемы данных их и добавили :)
7 май 04, 16:43    [668327]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Dmitry S. Kravchenko
Member

Откуда:
Сообщений: 92
Glory, ни фига Вы не понимаете в проектировании схем БД...

Для тех, кому интересно ДЕЛО, рассказываю, что я уже написал первую версию триггера, эмулирующего каскадное обновление.

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

Проверяйте (пока я сам не проверил) :-)))

Class - это родительская таблица, а Asset и Account - дочерние. Они связаны по полям ID-ClassID. В таблице Class есть уникальное поле Nam, которое используется для определения, что на что заменено.

ALTER TRIGGER Class_DistributeID
ON dbo.Class
INSTEAD OF UPDATE
AS
	IF UPDATE (ID) BEGIN

		BEGIN TRANSACTION

			DECLARE curdeleted CURSOR FOR SELECT ID, Nam FROM deleted
			DECLARE @oldID int, @newID int
			DECLARE @oldNam varchar(50)

			OPEN curinserted

			FETCH NEXT FROM curdeleted INTO @oldID, @oldNam
			WHILE @@FETCH_STATUS = 0 BEGIN 

				-- получаем новое соответствующее значение ключа

SELECT @newID = ID FROM inserted WHERE Nam = @oldNam -- отсоединяем дочерние записи
UPDATE Account SET ClassID = NULL WHERE ClassID = @oldID UPDATE Asset SET ClassID = NULL WHERE ClassID = @oldID -- заменяем ключ
UPDATE Class SET ID = @newID WHERE ID = @oldID -- подсоединяем дочерние записи
UPDATE Account SET ClassID = @newID WHERE ClassID IS NULL UPDATE Asset SET ClassID = @newID WHERE ClassID IS NULL FETCH NEXT FROM curdeleted INTO @oldID, @oldNam END COMMIT TRANSACTION END
7 май 04, 17:35    [668453]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
ChA
Member

Откуда: Москва
Сообщений: 10964
Glory, поздравляю !
7 май 04, 17:39    [668462]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
ChA
Member

Откуда: Москва
Сообщений: 10964
Каскад необязательно может ставиться на PK, может и на UNIQUE
7 май 04, 17:41    [668466]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 36691
автор
Glory, ни фига Вы не понимаете в проектировании схем БД...

Замечу осторожно, что если кто-то не понимает/не разделяет Вашу точку зрения на проектирование БД, то это не значит, что он в нем(проектировании) нифига не понимает.

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

А добавить в родительскую таблицу "рыбный" класс не судьба? Чтоб потом не париться с какскадным удалением? И обеспечивать целостность на уровне сервера? У меня сложилось впечатление, что Вы изобретаете велосипед, который давно был изобретен.

автор
Если по идеологии ПК не должен меняться, то зачем тогода ВООБЩЕ могут понадобиться каскадные обновления?

Неправильное суждение. Каскадные обновления возникают в случае изменения поля, а не наоборот. Пример - справочник из одной колонки, ключ и название одновременно. Вот для тех не умеет правильно проектировать свои схемы данных их и добавили :) - высказывание для этого(и всех остальных) случаев.
7 май 04, 17:45    [668477]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Glory
Member

Откуда:
Сообщений: 104764
2ChA
У нас демократия однако. Каждый волен сам наступать на грабли невзирая на чужой опыт

2Dmitry S. Kravchenko
И зачем спрашивается там курсор если "есть уникальное поле Nam, которое используется для определения, что на что заменено" ???
7 май 04, 18:21    [668554]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Dmitry S. Kravchenko
Member

Откуда:
Сообщений: 92
1) Сергей, у меня "не точка зрения", а знание, котороое я могу обосновать. А вот у этого самого "кого-то" всего лишь точка зрения: прокукарекал и потом хоть не расцветай.

2)

а) Рыбный класс ничем не лучше NULL-а, кроме того, в моем случае это невозможно - действует дополнительное условие по типу.

б) каскадное удаление мне не нужно (точнее говоря, "нужно не"), корректное удаление (если надо) будет производиться на уровень выше, в процедурах

в) пора Вам уже переходить от впечатлений, точек зрения и осторожных замечаний, к уверенности в себе

3) Не надо защищать утверждение о том, что каскадные обновления противоречат идеологии реляционных СУБД - это утверждение попросту неверное, говорящее лишь о квалификации того, кто его сделал.

Димс.
7 май 04, 18:23    [668558]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Dmitry S. Kravchenko
Member

Откуда:
Сообщений: 92
Glory,

<<
И зачем спрашивается там курсор если "есть уникальное поле Nam, которое используется для определения, что на что заменено" ???
>>

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

Димс.
7 май 04, 18:27    [668564]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Glory
Member

Откуда:
Сообщений: 104764
это утверждение попросту неверное, говорящее лишь о квалификации того, кто его сделал.

И что же оно интересно говорит о его квалификации ?
7 май 04, 18:28    [668568]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
nibbles
Member

Откуда: Moscow
Сообщений: 2378
автор
каскадное удаление мне не нужно (точнее говоря, "нужно не"), корректное удаление (если надо) будет производиться на уровень выше, в процедурах


Внятно объясните, чем Вас не устраивает каскадное обновление/удаление. Рекомендую также написать триггеры и хп, заменяющие ключи и индексы - дабы получить всю полноту власти (и ответственности) над целостностью базы данных.

автор
пора Вам уже переходить от впечатлений, точек зрения и осторожных замечаний, к уверенности в себе


Вашими бы устами, батенька... Увы, конец граблей бьет в самоуверенный лоб гораздо больней, чем в лобешник, закрытый ушанкой, каской и шлемом осторожности
7 май 04, 18:35    [668579]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Old Nick
Member

Откуда: Санкт-Петербург
Сообщений: 3124
Странно, я вот никогда не пользовался триггерами и представить не могу где это может понадобиться
7 май 04, 18:36    [668581]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Glory
Member

Откуда:
Сообщений: 104764
А потому что изменений ключа может быть несколько и их нельзя произвести скопом через NULL, потом не различишь, какая где, нужно поочереди. А просто проапдейтить за один шаг дочерние таблицы нельзя - связь не разрешит.

Все равно не пойму - если inserted и deleted т.е. newId и oldId можно сразу связать через Nam, то зачем это делать пошагово ?
7 май 04, 18:50    [668598]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Dmitry S. Kravchenko
Member

Откуда:
Сообщений: 92
nibbles

Внятно объясните, чем Вас не устраивает каскадное обновление/удаление.


Каскадное обновление меня очень бы устроило, но сервер не разрешает. Приходится эмулировать, вначале ведь ясно написано!

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

Между прочим, именно для таких случаев сделана ГАЛОЧКА, которую можно включать и выключать.

nibbles

Увы, конец граблей бьет в самоуверенный лоб гораздо больней, чем в лобешник, закрытый ушанкой, каской и шлемом осторожности


Проверять приходилось? Или это просто самооправдание из-под ушанки? ;-)

Димс.
8 май 04, 01:06    [668870]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Dmitry S. Kravchenko
Member

Откуда:
Сообщений: 92
Glory

Все равно не пойму - если inserted и deleted т.е. newId и oldId можно сразу связать через Nam, то зачем это делать пошагово ?


Установлена связь.

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

Поэтому, я СНАЧАЛА вынужден отсоединить дочерние записи. ПОСЛЕ этого можно изменить родительскую. И только ПОСЛЕ этого переподсоединить к ним дочерние. Три шага. За раз не сделаешь, хоть и данные все есть.

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

В конце концов, предложите свой вариант! Сколько можно ходить вокруг да около в ушанке и бояться высказаться? Если Вы ошибетесь - будет Вам урок. Если я - мне. От ошибок только лучше становится!

Димс.
8 май 04, 01:14    [668871]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 30748
Рискуя быть обвинённым в ламерстве, ещё раз посоветую не менять ПК :-)
8 май 04, 01:36    [668876]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 30748
2Dmitry S. Kravchenko
А насчёт пошагово - глори имел в виду курсор. Действительно непонятно, зачем он нужен - делайте просто три групповых операции с связкой через name
8 май 04, 01:45    [668878]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
ChA
Member

Откуда: Москва
Сообщений: 10964
Dmitry S. Kravchenko

есть возможность временно отключать действие ключей или связи?

Смотрите ALTER TABLE. Но, изменяя PK, - создаете себе проблему,
впрочем, хозяин - барин...
8 май 04, 04:48    [668901]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
MVM
Member

Откуда:
Сообщений: 271
Dmitry S. Kravchenko

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



Ага! Вот в чем собака порылась! У Вас сама постановка не верна! Вы, мил человек, излишне эмоциональны и хвост задираете на уважаемых мною людей, но дабы Ваши пользователи не пострадали - все-таки отвечу.

Задача, как я понимаю такова. Есть план счетов. Есть проводки. Счета в проводках с планом счетов соединены форинкеем. Ошибка номер раз. Вместо этого - делаете триггер на insert на таблицу проводок с проверкой плана счетов.
Далее. На всем скаку Ваши пользователи хотят менять план счетов. Тут два варианта.
1) Стандартное изменение, то есть в прошлом отчетном году счет закрывается, его сальдо переносится на другой счет. Здесь ничего нельзя удалять, ибо отчетный период закрыт, отчеты сданы, и таблица проводок должна им соответствовать. Делается стандартными бух методами, и только.
2) Нестандартное изменение - открыли новый счет пару месяцев поработали, а потом выяснили, что у него номер другой должен быть. Так как отчеты еще не сданы - можно и сделать то что Вы задумали. Только не на триггере (я Вас умоляю). Пишете процедуру. В ней параметром запоминаете счет как он был и как он должен быть. Делаете update проводок, потом плана счетов. Да, на проводках - ОБЯЗАТЕЛЬНО - триггер на проверку закрытого периода, дабы не поменять случайно, то что менять нельзя. Все.
8 май 04, 09:30    [668918]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
Glory
Member

Откуда:
Сообщений: 104764
В конце концов, предложите свой вариант! Сколько можно ходить вокруг да около в ушанке и бояться высказаться? Если Вы ошибетесь - будет Вам урок. Если я - мне. От ошибок только лучше становится!
Ну если вы так стремитесь переложить бремя тестирования вашей(!) идеи на других(!) то пожалуйста - вот вам рабочий(! а не приблизительный) и протестированный скрипт
use tempdb
go
if object_id('dbo.asset') is not null drop table dbo.asset
go
if object_id('dbo.account') is not null drop table dbo.account
go
if object_id('dbo.class') is not null drop table dbo.class
go
create table dbo.class (id int primary key, class_name varchar(20) unique)
go
create table dbo.asset(pk_id int identity, class_id int, asset_name varchar(20))
go
create table dbo.account(pk_id int identity, class_id int, account_name varchar(20)) 
go
create trigger tru_class ON dbo.class
FOR UPDATE
AS
IF UPDATE(id) AND NOT UPDATE(name)
BEGIN
	UPDATE a SET class_id = i.id
	FROM dbo.asset a
	INNER JOIN deleted d ON d.id = a.class_id
	INNER JOIN inserted i ON i.class_name = d.class_name
	UPDATE a SET class_id = i.id
	FROM dbo.account a
	INNER JOIN deleted d ON d.id = a.class_id
	INNER JOIN inserted i ON i.class_name = d.class_name
END
go

insert dbo.class(id, class_name)
select 1, 'class 1'
union all select 2, 'class 2'
union all select 3, 'class 3'
union all select 4, 'class 4'

insert dbo.asset (class_id, asset_name)
select 1, 'asset 1_1'
union all select 1, 'asset 1_2'
union all select 3, 'asset 3_1'
union all select 3, 'asset 3_2'
union all select 2, 'asset 2_1'


insert dbo.account (class_id, account_name)
select 1, 'acount 1_1'
union all select 1, 'acount 1_2'
union all select 3, 'acount 3_1'
union all select 3, 'acount 3_2'
union all select 2, 'acount 2_1'
go
select *
from class a
left outer join asset b on b.class_id = a.id
left outer join account c on c.class_id = a.id
go
update class set id = id + 10
go
select *
from class a
left outer join asset b on b.class_id = a.id
left outer join account c on c.class_id = a.id
go
update class set id = id - 20
go
select *
from class a
left outer join asset b on b.class_id = a.id
left outer join account c on c.class_id = a.id
if object_id('dbo.asset') is not null drop table dbo.asset
go
if object_id('dbo.account') is not null drop table dbo.account
go
if object_id('dbo.class') is not null drop table dbo.class
go
По аналогии можно сделать триггера для INSERT и DELETE

Я делаю в триггере то, что делал бы сам человек, вручную изменяя значение ключа и соблюдая целостность..
Человеческая логика как известно сильно отличается от машинной. Но вот мне лично стремление использовать в РСУБД позаписную обработку вместо обработки множеств многое говорит о квалификации автора :)
8 май 04, 12:34    [668990]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
nibbles
Member

Откуда: Moscow
Сообщений: 2378
автор
Я делаю в триггере то, что делал бы сам человек, вручную изменяя значение ключа и соблюдая целостность..


Мысли под ушанкой:
Тогда, уважаемый, вы забиваете гвозди микроскопом, используя сервер с двумя процами и шустрой оперативкой для выполнения доисторической инкрементной операции "один-плюс-один-плюс-один". Если вам не подходит теория реляционных баз данных - разрабатывайте свою. Кстати... За время этого флейма Вы вполне могли решить проблему без помощи закостнелых носителей ушанок и касок - а поскольку вы таки даете себе труд участвовать в дискуссии, в которой вас хором уговаривают вернуться в лоно поклонников СУРБД, можно сделать вывод о нашей совместной любви к флейму ;))
8 май 04, 15:03    [669068]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
andrej2005
Member

Откуда:
Сообщений: 142
извиняюсь, что поднимаю давнюю тему, в последнем скрипте, я так понял, надо еще удалять и снова ставить связи между табличками, иначе констрейнт не разрешит провести изменения?
7 апр 14, 17:39    [15845278]     Ответить | Цитировать Сообщить модератору
 Re: Эмуляция каскадных обновлений (это не ТО ЖЕ САМОЕ!!!!)  [new]
andrej2005
Member

Откуда:
Сообщений: 142
так как у нас тут дела? может кто-нибудь ответить на мой вопрос?! :)
8 апр 14, 11:28    [15848017]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить