Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

проблема с исправлением dbf в Fox

68K
09 марта 2011 года
Shadow-Star
2 / / 09.03.2011
Ребята столкнулся с такой задачей: есть база которая взаимодействует с SQL, но писалась под Fox. в которой некоторое количество столбцов а именно интересуют два должна выглядеть так:
 
Код:
Ta_ Tb_
40001 1
40001 2
40001 3
40001 сколько необходимо
40002 1
40002 2
40002 3
40002 сколько необходимо

А в данный момент выглядит так:
Код:
Ta_ Tb_
40001 1
40001 2
40001 3
40001 сколько необходимо
40001 1
40001 2
40001 3
40001 сколько необходимо
40002 1
40002 2
40002 3
40002 сколько необходимо
40002 1
40002 2
40002 3
40002 сколько необходимо

Вообщем суть проблемы: Задвоились все строки и как написать запрос на их удаление ни как не могу придумать, т.к. данные ничем не различаются.
Помогите пожалуйста.
385
10 марта 2011 года
SomewherSomehow
477 / / 25.07.2004
Если б речь шла о sql server, я бы написал вам конкретный кусок кода. Но т.к. с фоксом не работал, то придется ограничиться общим описание идеи. Итак, какие есть варианты на мой взгляд:
1. Есть ли в фоксе ранжирующие оконные функции? что-то типа row_number() которая нумерует строки в результирующей выборке, если есть - использовать ее, пронумеровать строки и удалить все строки с номером 1 или номером 2.
2. Если нет, то как вариант, добавить колонку в таблицу, в эту колонку проставить последовательно номера (либо сразу добавить колонку identity, ежели так можно в фоксе). После этого сделать обычный запрос с группировкой и удалить те строки, в которых значение этого поля будет максимальным или минимальным в группе. после этого удалить колонку.
3. Создать временную таблицу, перелить туда обычным запросом сгруппированные данные из таблицы с дубликатами. Удалить все данные из таблицы дубликатов, залить в нее данные из временной. Удалить временную. Этот способ может быть неудобен если в таблице есть первичный ключ, на который ссылаются другие таблицы.
как-то так, что приходит в голову на первый взгляд. удачи.
68K
10 марта 2011 года
Shadow-Star
2 / / 09.03.2011
Цитата: SomewherSomehow
Если б речь шла о sql server, я бы написал вам конкретный кусок кода. Но т.к. с фоксом не работал, то придется ограничиться общим описание идеи. Итак, какие есть варианты на мой взгляд:
1. Есть ли в фоксе ранжирующие оконные функции? что-то типа row_number() которая нумерует строки в результирующей выборке, если есть - использовать ее, пронумеровать строки и удалить все строки с номером 1 или номером 2.
2. Если нет, то как вариант, добавить колонку в таблицу, в эту колонку проставить последовательно номера (либо сразу добавить колонку identity, ежели так можно в фоксе). После этого сделать обычный запрос с группировкой и удалить те строки, в которых значение этого поля будет максимальным или минимальным в группе. после этого удалить колонку.
3. Создать временную таблицу, перелить туда обычным запросом сгруппированные данные из таблицы с дубликатами. Удалить все данные из таблицы дубликатов, залить в нее данные из временной. Удалить временную. Этот способ может быть неудобен если в таблице есть первичный ключ, на который ссылаются другие таблицы.
как-то так, что приходит в голову на первый взгляд. удачи.



Спасибо за предложение, но:
1. такой функции насколько мне известно нет.
2. неподходящий вариант, т.к. при добавлении колонки может сбиться структура т.к. таблица постоянно взаимодействует с другими таблицами и изменение ее может привести к окончательной крышке для общей базы.
3. тот же случай что и с пунктом 2...
Но все равно громадное спасибо за попытку помочь.

Мне знакомые советовали в принципе вариант как можно решить эту проблему, но они тоже работают только с sql server потому не знают как реализовать функционально это решение. Суть заключается в том, что нужно создать цикл который брал за основу вначале первую строку первого столбца и если данные равны второй строке, то сравнивал первую строку второго столбца и т.д. и если находил совпадение, то удалял его... Но как это реализовать даже приблизительно не представляю...

385
10 марта 2011 года
SomewherSomehow
477 / / 25.07.2004
Цитата: Shadow-Star
Спасибо за предложение, но:
1. такой функции насколько мне известно нет.
2. неподходящий вариант, т.к. при добавлении колонки может сбиться структура т.к. таблица постоянно взаимодействует с другими таблицами и изменение ее может привести к окончательной крышке для общей базы.
3. тот же случай что и с пунктом 2...
Но все равно громадное спасибо за попытку помочь.


1. очень жаль..
2. вот почему не надо запросы писать через select *, если бы все запросы были написаны изначально нормально, то проблем бы не было.
3. если с таблицей идет активная работа, то может создать таблицу дубликат полностю идентичную, но с другим именем, залить туда все данные, а потом одномоментно в одной транзакции с высоким уровнем изоляции "переключить" таблицы, поменяв имя одно на другое. если в фоксе блокировки реализованы нормально, ничего страшного не произойдет, другие транзакции просто чуток "подождут" и все. но лучше конечно сделать тестовый слепок бд и проверить сначала на нем. потом либо руками "дозалить" данные которые успели попасть в старую таблицу до переключения, либо операцию по заполнению временной таблицы и само переключение делать вообще в одной транзакции, тогда возможно другим запросам придется подождать подольше =)

Цитата: Shadow-Star

Мне знакомые советовали в принципе вариант как можно решить эту проблему, но они тоже работают только с sql server потому не знают как реализовать функционально это решение. Суть заключается в том, что нужно создать цикл который брал за основу вначале первую строку первого столбца и если данные равны второй строке, то сравнивал первую строку второго столбца и т.д. и если находил совпадение, то удалял его... Но как это реализовать даже приблизительно не представляю...


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

upd:
пока писал, пришла еще одна мысль. как насчет курсоров, в фоксе есть такое? при помощи операции fetch курсора теоретически можно было бы брать именно по одной строке и сравнивать ее с предыдущей, при этом правда надо обеспечить правильный порядок строк в самом курсоре иначе в таком сравнении будет мало толку. и вот тут как раз курсор можно перебирать в том самом цикле, м.б. это вам советовали? только сразу учтите что это будет гораздо дольше чем со множествами или одним запросом. И не знаю как в фоксе, но в сиквеле пришлось бы создавать динамический курсор для обновления, а раз динамический то данные в нем могли бы изменятся, тогда вероятность получить несогласованные данные увеличивается, либо пришлось бы класть хорошую такую блокировку на таблицу, и т.к. курсор и цикл - операция затратная (заведомо медленнее чем один два-запроса), то блокировка бы заняла много времени, чем потенциально создала бы проблемы если с таблицей идет активная работа. Но как там у вас в фоксе - почитайте обязательно, это я описал потенциальные грабли в сиквеле, просто чтоб вы имели ввиду что такие проблемы могут быть.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог