Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как поступить правильно, соблюдая каноны программирования? [D7, WinXP]


Страницы:   1 2

kyn66 ©   (2005-08-19 11:12:00) 

Уважаемые мастера, САБЖ. Есть таблица Таб1, в которой (после фильтра, к примеру) имеется 30 записей.
Каждая запись ессно имеет свой ID. У нее в подмастерьях имеется ешшо одна таблица Таб2, которая по ID
связана с Таб1. Мне нужно удалить все записи из Таб1 и ессно все подчиненные записи Таб2. Есть два варианта
удаления:
1) Я в цикле прохожу по всем записям Таб1 и через SQL-запрос удаляю все записи из Таб2, где есть связь по ID Таб1

while not Таб1.EOF do
  begin
       SQL.Add(Format('DELETE FROM %s WHERE OperID = :p1', [Tab2]));
       Parameters[0].Value := Таб1.FieldByName('ID').Value;
       ExecSQL;
       SQL.Clear;
       Таб1.Next;
  end;


2) Я опять-же в цикле прохожу по Таб1, в некую переменную (S : TStrings) собираю все ID таблицы Таб1, затем SQL-запрос
   выполняю тока 1 раз

       SQL.Add(Format('DELETE FROM %s WHERE OperID IN (S)', [Tab2]));
       ExecSQL;


И тот и другой способ отработают, но меня интересует как правильно нужно поступать?


Ega23   (2005-08-19 12:46:00) [21]

Делаешь один раз и забываешь про эту проблему навсегда.

Угу. Удаляешь потом одну запись и теряешь пол-базы.
Не, автоматическое каскадное удаление - это зло. Хуже только сифилис.


afanasic   (2005-08-19 12:45:00) [22]

Прошу прощения, Таб1 и Таб2 необходимо поменять местами!!!


afanasic   (2005-08-19 12:44:00) [23]

Пример для Oracle

alter table Таб1 add constraint Имя_надстройки foregn key (id) references Таб2(id) on delete cascade;

Делаешь один раз и забываешь про эту проблему навсегда.
Что-то подобное должно быть и в других СУБД обязательно...


alex_***   (2005-08-19 12:37:00) [24]

DELETE T2 FROM T2 INNER JOIN T1 ON T2.OrderID = T1.ID AND {условие}

DELETE FROM T1 WHERE {условие}

хотя, если надо снести всё, то проще [1]


Ega23   (2005-08-19 12:09:00) [25]

А какая разница?
Всё дело в уровне абстракции. Сервер - это сервер. Клиент - это клиент. Могут оба физически находиться на одной машине. Могут - на разных. Механизм подключения-то - общий.


kyn66   (2005-08-19 12:03:00) [26]

>> Ega23
Во, млин, спасибо, ща буду пробывать разбираться. Да, но это относится  если ты пишешь  клиент-сервер? А если я просто на сервере держу базы а работаю с ними в обычном режиме?


Ega23   (2005-08-19 11:55:00) [27]

Вот тебе пример ХП для MS SQL, с каскадным удалением:

Print  'S_RTTIProc - процедура для работы с RTTI системы'
go
if exists (select * from sysobjects where id = object_id(N'[S_RTTIProc]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [S_RTTIProc]
GO
CREATE PROCEDURE S_RTTIProc

@ActNam varchar(32)='NONE',
 .........
-- Остальные параметры
 .........

As
declare  
 @NULLGUID uniqueidentifier,
 @result int,
 @x int,
 @aSQL varchar(8000),
 @ss varchar(8000),
 @ss1 varchar(8000);

Set @NULLGUID = '00000000-0000-0000-0000-000000000000';
Set NoCount ON;
Set @Result=0;
Select @ActNam=RTrim(LTrim(UPPER(@ActNam)));

if @ActNam='CLASSFIELDS.DEL'
begin
Delete ClassFields where (@UNID=-1 or UNID=@UNID) and
             (@CLSID=-1 or CLSID=@CLSID) and
             (@FldTypCod=-1 or FldTypCod=@FldTypCod);
Select @Result=@UNID;
Goto Fin;
end;

if @ActNam='CLASSMETHODS.DEL'
begin
Delete ClassMethods
 where (@CLSMetCod=-1 or CLSMetCod=@CLSMetCod) and
    (@CLSID=-1 or CLSID=@CLSID);
Select @Result=@CLSMetCod;
Goto Fin;
end;

if @ActNam='CLASSSTATES.DEL'
begin
Delete ClassStates
 where (@UNID=-1 or UNID=@UNID) and
    (@CLSID=-1 or CLSID=@CLSID);
Select @Result=@CLSMetCod;
Goto Fin;
end;

if @ActNam='CLASSES.DEL'
begin
-- Сначала удалим ClassFields

exec S_RTTIProc @ActNam='ClassFields.Del', @CLSID=@CLSID;

-- Теперь удалим ClassMethods

exec S_RTTIProc @ActNam='ClassMethods.DEL', @CLSID=@CLSID;

 -- Удаляем ClassStates
exec S_RTTIProc @ActNam='ClassStates.DEL', @CLSID=@CLSID;

Delete Classes where CLSID=@CLSID;
Select @Result=@CLSID;
Goto Fin;
end;

fin:
set nocount off;
return(@result);
GO


Гаврила   (2005-08-19 11:39:00) [28]

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


kyn66   (2005-08-19 11:31:00) [29]

Ну, до этого я ешшо не дошел 8-(


Ega23   (2005-08-19 11:30:00) [30]

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


Ega23   (2005-08-19 11:29:00) [31]

Если ВСЕ записи, то
delete from Tab2
delete from Tab1

?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо