Форум: "Базы";
Текущий архив: 2004.05.23;
Скачать: [xml.tar.bz2];
ВнизУдаление записей из одной таблицы по ключам другой таблицы Найти похожие ветки
← →
Курдль © (2004-04-28 23:58) [0]1. База построена криво, - не сыпьте соль на ...
2. Перепланировать ее нельзя никоим образом - ни процедур ни даже временных таблиц.
Описание:
Есть таблица СПРАВКИ ПК: СПР_ИД
Есть таблица ПЛАТЕЖИ, ссылающаяся на справки "одна-к-одной" по внешнему ключу ВК_СПР_ИД.
Теперь внимание! Вопрос: надо удалить те, и только те СПРАВКИ, на которые ссылается группа ПЛАТЕЖЕЙ.
Если кто не понял, проблема в том, что сначала надо обнулить значение внешних ключей из ПЛАТЕЖЕЙ, а потом удалить соответствующие обнуленным ключам справки.
Не предлагать:
1. Сделать селект и в цикле обнулять по одному сначала ключи (запоминая их значение), а потом удалять СПРАВКУ со СПР_ИД равной этому значению.
2. Предлагать все остальное :) Хотелось бы какой-нить шайтан скрипт :)
← →
ЮЮ © (2004-04-29 02:48) [1]>ссылающаяся на справки "одна-к-одной" по внешнему ключу ВК_СПР_ИД
Может всё-таки "один-ко-многим". Иначе ВК_СПР_ИД - PrimaryKey field, которое не может быть NULL
> а потом удалить соответствующие обнуленным ключам справки.
после обнуления не будет соответствия, поэтому можно удалить все записи из СПРАВКИ, на которые нет ссылок из ПЛАТЕЖЕЙ, при условии, конечно, что не должно быть таких справок, а они существуют лишь благодаря "кривизне" структуры БД
← →
Курдль © (2004-04-29 09:09) [2]
> Может всё-таки "один-ко-многим". Иначе ВК_СПР_ИД - PrimaryKey
> field, которое не может быть NULL
1. C какого это перепугу? :) У Вас, например, легально может быть только один паспорт. И может быть один, или ни одного загранпаспорта. Предположим, что Вам интересно иметь ссылку именно с паспорта на загранпаспорт - вот она и будет "внешний ключ один-к-одному", причем не обязательный!
> можно удалить все записи из СПРАВКИ, на которые нет ссылок
> из ПЛАТЕЖЕЙ
2. Так тоже нельзя, т.к. СПРАВКИ живут своей полной приключений жизнью, могут создаваться на рабочих местах другого типа и закономерно не иметь никаких отношений с ПЛАТЕЖАМИ. Однако, это не повод, чтобы их удалять.
3. Есть маленькая надежда добиться права альтернуть внешний ключ со свойством check on commit, но весьма призрачная.
4. Создать View или Temporary Table не дают привелегии пользователя.
← →
Johnmen © (2004-04-29 09:19) [3]>Вопрос: надо удалить те, и только те СПРАВКИ, на которые
>ссылается группа ПЛАТЕЖЕЙ.
Что есть "группа" ПЛАТЕЖЕЙ ? И какой однозначный критерий "ссылается" ?
← →
Sandman25+1 (2004-04-29 09:48) [4]1. Если в Sybase есть способ временно отключить Foreign Key, то можно так и сделать, а потом в лоб - сначала удалить нужные справки, потом очистить платежи, которые ссылаются на только что удаленные (и потому несуществующие уже) справки.
2. Если способ 1 невозможен, то можно закачать номера нужных справок в новую временную таблицу, а затем двумя командами очистить платежи и удалить справки, используя эту новую временную таблицу в подселекте в обеих командах. Если временная табличка будет большая, то можно еще и индекс по ней создать для ускорения.
← →
Курдль © (2004-04-29 10:10) [5]Для Johnmen
> Что есть "группа" ПЛАТЕЖЕЙ ? И какой однозначный критерий
> "ссылается" ?
"Группа" - один, или несколько платежей, например, порожденных одним и тем же отчетом.
Критерий "ссылается" - имеет внешний ключ по СПР_ИД, как описано в [0]
Для Sandman25+1
1, 2: Нет никаких прав для вмешательства в структуру БД, как описано в [2] п.4.
← →
Johnmen © (2004-04-29 10:34) [6]>Курдль © (29.04.04 10:10) [5]
Тогда это уже не один-к-одному, а один-ко-многим. В общем случае...
ПопробуйDELETE FROM СПРАВКИ
WHERE EXISTS (SELECT 0 FROM ПЛАТЕЖИ
WHERE ПЛАТЕЖИ.ВК_СПР_ИД=СПРАВКИ.СПР_ИД)
← →
DenK_vrtz © (2004-04-29 10:35) [7]>Курдль ©
Если я правильно понял на одну справку имеется несколько платежей. Так? Если вы пытаетесь удалить справку, а у платежа занудить ссылку на справку, о каком внешнем ключе, в таком случае, может идти речь?
Исходя из Курдль © (29.04.04 10:10) [5]
>Нет никаких прав для вмешательства в структуру БД
задача может быть решена путем создания каких-нить, скажем, временных локальных таблиц, в которые будет закачена, а потом восстановлена нужная информация. Но вопрос о сохранении внешнего ключа остается открытым.
← →
Sandman25+1 (2004-04-29 10:37) [8][5] Курдль © (29.04.04 10:10)
Никакого вмешательства в БД нет.
В первом случае foreign key отключается только для текущей транзакции, в момент подтверждения/отката транзакции происходит автоматическе восстановление constraint и если он "violated", то commit не проходит.
Во втором случае создается temp table, которая существует только в текущем сеансе подключения и удаляется автоматически при его завершении.
← →
stud © (2004-04-29 10:37) [9]так а запросом типа
delete from spravki where spravki.spr_id in (select plategi.id from plategi inner join on (plategi.id=spravki.spr_id)
или что-то в этом роде?
← →
Johnmen © (2004-04-29 10:40) [10]>Курдль ©
Я кажись понял, в чем проблема....
Отсюда вопрос - можешь ли изменить описание внешнего ключа ?
← →
Курдль © (2004-04-29 10:55) [11]Для всех: все именно так, как я описал один-к-одному.
> Отсюда вопрос - можешь ли изменить описание внешнего ключа
> ?
Это крайняя мера, к которой прибегну в последний моментcheck on commit
← →
Johnmen © (2004-04-29 11:24) [12]>Курдль © (29.04.04 10:55) [11]
Почему крайняя ? Переопредели FK.... ON DELETE SET NULL
← →
Курдль © (2004-04-29 12:46) [13]
> Sandman25+1 (29.04.04 09:48) [4]
> 1. Если в Sybase есть способ временно отключить Foreign Key
Приведи пример такой возможности из любой другой базы - я попробую порыть в доке Сайбэйса (мож не заметил чего).
> Johnmen © (29.04.04 11:24) [12]
> Почему крайняя ? Переопредели FK.
> ... ON DELETE SET NULL
У меня нет права просто так взять и вмешаться в структуру БД, которая оттачивалась месяцами и на которой ныне работают несколько крупных фирм. Для этого должны быть веские основания. Когда я говорил о кривизне базы - имел в виду, что это громоздкое, но рабочее сооружение с огромным количеством компромиссов.
← →
Johnmen © (2004-04-29 12:57) [14]>Курдль © (29.04.04 12:46) [13]
Тогда твоя проблема, в данной постановке, неразрешима (за искл.см.ниже).
Основание :
Надо сделать модификацию данных одной тбл, потом модификацию данных другой тбл, причем критерий для 2тбл берется на основании критерия для 1тбл. Значит параметры второй модификации зависят от первой, т.е. должен быть "мостик" данных.
Т.о. единственное решение видится в применении временной таблицы.
← →
Danilka © (2004-04-29 13:10) [15]а в Sybase можно скрипты на исполнение посылать?
не процедуру, не запрос, а скрипт.
который будет делать, например, курсор на одну таблицу, в цикле этого курсора два запроса: на удаление из второй таблицы и апдейт текущей записи, записать в ее поле null.
в орокле такое можно, посылаешь блок begin ... end; в ms-sql тоже можно, а в сабейсе разве нельзя?
← →
Курдль © (2004-04-29 13:13) [16]
> Т.о. единственное решение видится в применении временной
> таблицы.
А вот вопросец... Каким образом незаметненько создать временную таблицу? Если в лоб пишешьselect temporary table ...
- нарываешься на нарушение прав. Роль юзера, который должен работать с этими таблицами распространяется только на добавление/изменение/удаление записей.
← →
Курдль © (2004-04-29 13:16) [17]
> в орокле такое можно, посылаешь блок begin ... end; в ms-sql
> тоже можно, а в сабейсе разве нельзя?
В Sybase чёрта лысого сделать можно - хоть запросы на Java писать, поэтому в его доке запутаться - как 2 факса отослать! Но позволят ли компоненты (SQL Direct)?.. Однако надо сначала попробовать в "Interactive SQL".
← →
Johnmen © (2004-04-29 13:17) [18]Я не знаю, как организована поддержка временных таблиц в сибейсе.
Может достаточно просто создавать пользовательскую тбл, а потом убивать... Я не знаю, как организована поддержка прав в сибейсе.
← →
Курдль © (2004-04-29 13:23) [19]
> Я не знаю, как организована поддержка временных таблиц в
> сибейсе.
> Может достаточно просто создавать пользовательскую тбл,
> а потом убивать... Я не знаю, как организована поддержка
> прав в сибейсе.
Как во всякой взрослой базе. Естественно, когда нами конкретная база проектировалась, никто и представить не мог такой крамолы, чтобы дать юзерам возможность создавать таблицы. Плохо, что нет времени и сил углубляться в частности типа чемcreate global temporary table...
отличается отcreate local temporary table...
. Естественно, что все эти варианты я попробовал и они либо выдали ошибки, либо не подошли, прежде чем я потревожил мастеров. :(
← →
Danilka © (2004-04-29 13:30) [20]Все-таки, в орокле, вероятно, я-бы сделал примерно так:
begin
for i in (select ... from ПЛАТЕЖИ where ...) loop
-- удаляем справки
-- апдейтим поле
end loop;
end;
Скорее всего, в сибейсе подобное тоже возможно. и никаких темповых таблиц.
← →
roottim (2004-04-29 13:44) [21]2Danilka © (29.04.04 13:30) [20]
>Скорее всего, в сибейсе подобное тоже возможно. и никаких темповых таблиц.
Наврядли. Оракл версионник... и данные по вышему курсору будут браться из сегмента отката.
СиБэйз подобен мсскл (или наоборот) блокировочники.. и выходом из ситуации для них служат созданные временные таблицы. (по этой-же причине в Оракл временные таблицы ранее не использовалиь вообще. Да и сейчас необходимы для частных(редких) удобств)
2 Курдль
а сибэйз не может как мсскл (вроде одного поля ягоды) типа:select * штещ #temp from mytable
← →
Sandman25+1 (2004-04-29 13:53) [22][13] Курдль © (29.04.04 12:46)
СУБД Informix:
BEGIN WORK;
SET CONSTRAINT my_foreign_key DEFERRED;
-- работа с БД
-- ...
COMMIT WORK
Еще можно SET CONSTRAINTS ALL DEFERRED - отключает вообще все constraints
← →
Курдль © (2004-04-29 14:11) [23]
> DEFERRED
Нет даже такого зарезервированного слова. И в работе с констрэйнтами ничего про рилтайм (тока создал/удалил).
Да и вряд ли установленные нами же правила дали бы менять констрэйнты рядовому юзеру.
To Danilka © - попробую родить скрипт. Тестовый скрипт отработал с компонентом TSDQuery и TSDScript - зачет!
Окончательные результаты доложу.
> СиБэйз подобен мсскл (или наоборот) блокировочники..
MS SQL делался по образу и подобию. Не знаю, насколько удачно.
← →
Курдль © (2004-04-29 15:30) [24]Доклад: зачётно отработал скрипт
begin
for LP as CR cursor for select INQ_ID as CUR_INQ from SC.SC_AGENT_PAYMENTS where AGR_ID = :AGR_ID do
update SC.SC_AGENT_PAYMENTS set INQ_ID = Null where INQ_ID = CUR_INQ;
delete SC.SC_INQUIRYES where INQ_ID = CUR_INQ;
end for;
end;
Спасибо всем-всем-всем, а особенно Danilka © за хорошую наводку!
ЗЫ: Люблю Sybase!
← →
Sandman25+1 (2004-04-29 17:02) [25][23] Курдль © (29.04.04 14:11)
Constraint не меняется. Ни рядовым юзером, ни DBA. Он всего навсего временно отключается, чтобы можно было работать с таблицами в любом порядке (а не в том, который требуют констрейнты).
Не предлагать:
1. Сделать селект и в цикле обнулять по одному сначала ключи (запоминая их значение), а потом удалять СПРАВКУ со СПР_ИД равной этому значению.
Так бы сразу и сказал :))))
← →
Курдль © (2004-04-29 17:07) [26]
> Так бы сразу и сказал :))))
Чё за грязные инсиннуации? :))) Это про мой скрипт, который так именно и делает? :)))
Я просто переделываю модуль, созданный одним юным дарованием, так у него на клиенте был сделан цикл по выборке из ПЛАТЕЖЕЙ, в каждом проходе которого на сервер посылалось немеряное кол-во запросов.
← →
Sandman25+1 (2004-04-29 17:20) [27][26] Курдль © (29.04.04 17:07)
Само собой, никто бы не советовал написать хранимую процедуру, все обожают такое делать через TTable... :)
← →
Курдль © (2004-04-29 17:24) [28]
> Само собой, никто бы не советовал написать хранимую процедуру
И правильно не советовали, особенно те, кто внимательно читал условие - нельзя вмешиваться в структуру базы!
Вот в конце концов был рожден (не помню, как он обзывается) типа анонимный (или автономный) скрипт.
← →
Sandman25+1 (2004-04-29 17:28) [29][28] Курдль © (29.04.04 17:24)
Виноват, невнимательно посмотрел. Точнее, посчитал, что нельзя изменять процедуры (понятно, почему) и добавлять таблицы (чтобы не увеличивать требования к памяти). Жаль, что ХП выполняется быстрее, чем автономный скрипт.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2004.05.23;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.033 c