Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности

Новые сообщения [новые:0]
Дайджест
Горячие темы
Избранное [новые:0]
Форумы
Пользователи
Статистика
Статистика нагрузки
Мод. лог
Поиск
|
|
28.03.2005, 21:50
|
|||
|---|---|---|---|
|
|||
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
Не посоветует ли многоуважаемая аудитория как можно быстро и безболезненно синхронизировать данные между 2мя базами? Задача: На входе: 2 базы с идентичной структурой. Известны имена таблиц, которые надо "синхронизировать". Синхронизировать надо ТОЛЬКО ДАННЫЕ. Примочки с синхронизацией структур не нужны. На выходе: SQL скрипт, который все это сделает, если его запустить. Чтобы не сбивать народ с толку, опишу зачем это нужно более подробно на случай если исходная задача может быть решена другими средствами. Исходная задача банальна до невозможности: контроль версий базы. То есть, есть одна девелоперская база, и есть с пару сотен клиентских баз, которые после выпуска версии надо проапгрейдить. Со структурами CASE (PowerDesigner PhysicalArchitect) справляется превосходно. На базу вешается номер версии, и есть скрипт, который апгрейдит базу от версии 1 к версии 2, потом 3, и т.д. т.е. известно что в какую версию пошло и какое изменение есть у кого из клиентов. Однако есть некие "системные" (в смысле приложений) таблицы, данные в которых тоже могут меняться со временем. Имена таблиц, "системных" для приложения известны. T.e. необходимо иметь некий скрипт, который также апгрейдит и данные в этих системных таблицах. Было бы неплохо выбрать какое изменение "идет" в новую версию, а какое пока нет. ПОнятно, что могут быть вставки, изменения, и удаления. Подключив Unload/Load и написав пару хранимых процедур все пишется и тестируется за неделю своими руками, но проблема моя в том, что нету у меня этой недели. Т.к. задача до невозможности типичная, решил обратить свой взгляд на рынок программных примочек, которые могут эту задачу решать. Пробежался первым делом поиском, сам нарыл несколько ссылок, но ничего не подошло. Вот список испробованного с описанием причин отказа: 1. CDB Databases Comparator 3.1 Все круто, хоть и дороговат. Но вот одну фичу они упустили: SQL генерировать можно только для одной записи. Когда выбираешь несколько (или все), говорит извинитя, нету SQL, могу только напрямую перегнать. Напрямую - это здорово, только не совсем то, что мне нужно. 2. SQL Merger . Кажется что нужно, но только на первый взгляд. Очень сыра на ощупь, все вводится текстом от руки, включая имя таблицы и имя первичного ключа, и SQL запроса для обеих частей. Если мне надо будет 20 таблиц этой прогой сделать, я скорее умру. Демо-версия имеет еще пару дебильных ограничений что толком и не посмотришь как оно раьботает, также есть подозрение что вместо INSERT она лепит UPDATE для новых записей. 3. DBDiff Все круто, интерфейс что надо, только вот одна мелочь - на выходе мне выдается "отчет" типа что отличается. Как из нее вытрясти SQL, понятия не имею. Похоже что никак. А жаль. 4. Database Bridge ТОже сыро, хотя №2 гораздо сырее. Может и подошла бы, да только она опять "напрямую" мне все предлагает сделать. Скрипта нема. И опять, же все по одной таблице за раз. 5. DBExplorer Очень приятная программка, только опят же предлагает все сделать "напрямую". Есть еще раза в 2 больше примочек, которые попробовал бы, но они работают только с MSSQL :(. Прослеживается следующая тенденция: 1. больше половины программ предлагают сравнивать структуры (таблицы, представления, и т.п.). У нас над этой частью уже все равно CASE трудится. 2. 90% увиденного предлагает все "напрямую" закачать, и своего скрипта я увидеть так и не смог. Неужели ни у кого не возникает такой задачи? Как ее решают? Заранее спасибо ЗЫ. Можно вслепую чистить и тут же перезагружать все подряд из текстовых файлов, предварительно отбрасывая внешние ключи, а в конце скрипта их опять воссоздавать, но только муторно, плюс это меняет структуры таблиц/ключей что подрывает процесс версии структур таблиц. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
28.03.2005, 21:51
|
|||
|---|---|---|---|
|
|||
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
Сервер ASA 9.0.2, но подойдет любой ODBC-совместимый софт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
28.03.2005, 22:47
|
|||
|---|---|---|---|
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
Задачу "обновления таблицы справочника" можно решить очень просто. С самого начала обрати внимание, что эти таблицы надо отправлять клиентам "как есть". То есть собственно сравнивать данные не нужно совершенно. Надо всего лишь привести таблицу получатель в точно такое же состояние как и исходная таблица. А значит все программы сравнивающие две таблицы нам не нужны.... Что нам в итоге нужно? Нам нужен скрипт вида: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. Слегка сложнее сгенерировать скрипт на удаление устаревших записей. Для этого можно держать либо две разных таблицы (чтобы было с чем сравнивать). Либо в исходной таблице сделать дополнительное date поле "убить эту запись после такой-то даты". Либо (самый предпочтительный вариант!) вообще не убивать ничего из таблицы справочника. Может клиент уже насоздавал кучу платежек в группу "на пьянки" :) А ты взял и убил эту строку из справочника. У клиента все платежи по этой группе убились по внешнему ключу и весь отчет годовой поехал. Код: plaintext 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
28.03.2005, 23:42
|
|||
|---|---|---|---|
|
|||
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
Хорошее решение. У него, есть одна особенность - каждый раз надо посылать все таблицы справочника. Некоторые таблицы у нас содержат "примерчики отчетов" с формами и отчетами в мемо-полях, поэтому я хотел отправлять только изменения. Еще хотелось бы знать что именно поменялось с версии такой-то по такую-то, потому что 1. Может вообще ничего не поменялось в это раз, и клиенту с данной версией базы этот скрипт не нужен? 2. (самое важное) Наши разработчики "наделали" в девелоперской базе тестовых записей, или поредактировали старые, шутки ради. Контроль качества нужен. Боязно вот так все сразу перезагружать. Так или иначе, Ваше решени намного лучше того, что я использовал до этого (перезагрузка с отбросом внешних ключей - очень плохо :) ), поэтому внедрю его пока на первое время, а сам буду продолжать поиски. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
29.03.2005, 02:27
|
|||
|---|---|---|---|
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
Dmitriy PopovХорошее решение. Плохих не держим :) Dmitriy PopovУ него, есть одна особенность - каждый раз надо посылать все таблицы справочника. Некоторые таблицы у нас содержат "примерчики отчетов" с формами и отчетами в мемо-полях, поэтому я хотел отправлять только изменения. Да, конечно, но таблицы справочники редко бывают большими по объему. Обычно то от десятка до сотни записей всего. Редко когда справочник превышает тысячу записей.... У меня в с системе таких всего два. Но большие справочники обычно представляют из себя деревья, а не простые списки. Так что можно при обновлении делать только частичное обновление какой-либо ветки, сильно выигрывая на объеме скрипта. К тому же, кого в наше время удивишь объемами? :) Dmitriy PopovЕще хотелось бы знать что именно поменялось с версии такой-то по такую-то, потому что Не согласен. Во первых, клиенту такая информация нафиг не нужна. В документации появление нового "типа платежа" упомянуто и хватит. А у тебя как у разработчика лежит подборка whatsnew :) С другой стороны, у словарной статьи может быть какой-то переиод жизни. Например старые платежи создавались под графой "на пьянку", а с новой версии программы такие платежи создавать больше нельзя, но при этом и старые не должны исчезнуть? Тогда я ввожу в словарь два поля StartDate/EndDate и клиент показывает пользователю как доступные словарные варианты только те, которые уже вошли в действие и у которых еще не кончился период. Таким образом мы получаем возможность для всех филиалов разом "изменить" справочники. Пример из жизни: сейчас конец марта, мы рассылаем по своим филиалам очередной апдейт. В нем упомянута радиостанция на которой мы крутим свою рекламу. Чтобы клиент (в смысле человек-клиент) приходя к нам, мог сказать что услышал про нашу фирму там-то, а менеджер решил куда давать рекламу лучше. Но фокус в том, что на данной радиостанции наши ролики будут крутить только в мае. Поэтому и клерк вплоть до мая не увидит этой радиостанции в справочнике рекламных источников. И она "магически исчезнет" из справочника через год после окончания рекламы на этой радиостанции. Во всех филиалах разом! И мне, как администратору базы данных, для этого не потребуется шевелиться совсем. Dmitriy Popov1. Может вообще ничего не поменялось в это раз, и клиенту с данной версией базы этот скрипт не нужен? Опять не согласен. Справочник на удаленой базе должен быть всегда свежайшим, это во первых. А во вторых, мы всегда можем обернуть любой скрипт в блок: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Код: plaintext 1. 2. 3. 4. Dmitriy Popov2. (самое важное) Наши разработчики "наделали" в девелоперской базе тестовых записей, или поредактировали старые, шутки ради. Контроль качества нужен. Боязно вот так все сразу перезагружать. Ну это уже решается административными мерами :) Да и к тому же всегда надо держать несколько копий базы. Одна для игр разработчиков, одна для контроля. Собственно говоря задачу со справочниками я решаю несколько более жестким методом. У меня на LAN висят несколько серверов. И одна из баз данных целиком посвящена справочникам. Только справочники! Плюс специальный клиент который ходит к этой базе. Несколько офисных клерков, которые занимаются правкой справочников, пользуются именно этой программой. Когда они говорят "все готово", я запускаю отдельную утилитку которая собственно и делает выгрузку нужного справочника из этой специальной базы. Формирует скрипт по принципам которые я уже показывал. Мне остается только положить этот скрипт в каталог для InstallShield и... все :) Кстати, редактирование справочников через специальную базу дало еще один плюс - структура справочника на табличном уровне может отличаться (и иногда существенно) от табличной структуры справочника в рабочей базе. Чтобы было проще писать редактор справочника :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
29.03.2005, 17:26
|
|||
|---|---|---|---|
|
|||
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
Я делал примерно следующее: на входе процедуры имена таблиц для сравнения, за тем я создавал временку, где были поля идентифицирующие номер записи и флаг, принцип флага 0 -значение не изменилось, -1 запись отсутсвует, 1 значение изменилось, ну а дальше все просто, из системных таблиц извлекалось имя столбцов таблицы, т.е. открывался курсор который бегал по именам столбцов, на их основе делался запрос на сравнение значений ABS(Compare()) и вливание результата во времянку, затем во времянке убивались все записи где флаг = 0, ну а оставшиеся записи показывали что надо изменять. Вот что получилось... create PROCEDURE "DBA"."procUpgradeTable"(in Table_ varchar(256),in Table1 varchar(256)) begin declare inIdTable integer; declare column_id_tmp integer; declare column_name_tmp varchar(256); declare recId_tmp varchar(256); declare s varchar(2048); declare UTable_ varchar(256); declare UTable1 varchar(256); declare Err_not_Found exception for sqlstate value '02000'; declare NewColumns dynamic scroll cursor for select column_id,column_name from SYS.SYSCOLUMN where table_id = inIdTable order by column_id asc; declare NewStrings dynamic scroll cursor for select distinct keyOrg from tblOrlovTMP where (name_Table = Table1 or name_Table = Table_) and flagDb < 0; declare local temporary table tblOrlovTMP( idRec integer not null default autoincrement, KeyOrg integer null, Flagdb integer null, Name_table varchar(256) null, primary key( idRec) , ) on commit delete rows; set UTable1=Ucase(Table1); set UTable_=Ucase(Table_); delete from OrlovTemp where name_Table = Table1; delete from OrlovTemp where name_Table = Table_; select table_id into inIdTable from SYS.SYStable where table_name = table1; /* Сравнение столбцов таблиц новой Table1 и старой Table_ */ open NewColumns; For_NewColumns_loop1: loop fetch next NewColumns into column_id_tmp,column_name_tmp; if sqlstate = Err_not_Found then leave For_NewColumns_loop1 end if; if column_id_tmp = 1 then /* счетчик, если flafDb -1 то новая строка */ set recId_tmp=column_Name_tmp; set s=string('insert into tblOrlovTMP( keyOrg,FlagDb,Name_table) ( select "',recid_tmp,'",'); set s=string(s,' -1 ,',"char"(39),Utable1,"char"(39)); set s=string(s,' from ',table1,' where not ( "',recid_tmp,'" in ('); set s=string(s,' select "',recid_tmp,'" from ',table_,' )))'); execute immediate s else /* остальные поля, если flafDb 0 или null то нет изменений */ set s=string(' insert into tblOrlovTMP( keyOrg,FlagDb,Name_table) ( select a."',recid_tmp,'",'); set s=string(s,'abs(Compare(a."',column_Name_tmp,'",b."',column_Name_tmp,'")),',"char"(39),Utable1,"char"(39)); set s=string(s,' from ',table1,' as a, ',table_,' as b where a."',recid_tmp,'"= b."',recid_tmp,'" )'); execute immediate s end if end loop For_NewColumns_loop1; close NewColumns; /* Сравнение столбцов таблиц старой Table_ и новой Table1 */ select table_id into inIdTable from SYS.SYStable where table_name = table_; open NewColumns; For_NewColumns_loop2: loop fetch next NewColumns into column_id_tmp,column_name_tmp; if sqlstate = Err_not_Found then leave For_NewColumns_loop2 end if; if column_id_tmp = 1 then /* счетчик, если flafDb -2 то строка в старой таблице отсуствует в новой */ set recId_tmp=column_Name_tmp; set s=string('insert into tblOrlovTMP( keyOrg,FlagDb,Name_table) ( select "',recid_tmp,'",'); set s=string(s,' -2 ,',"char"(39),Utable_,"char"(39)); set s=string(s,' from ',table_,' where not ( "',recid_tmp,'" in ('); set s=string(s,' select "',recid_tmp,'" from ',table1,' )))'); execute immediate s else /* остальные поля, если flafDb 0 или null то нет изменений */ set s=string(' insert into tblOrlovTMP( keyOrg,FlagDb,Name_table) ( select a."',recid_tmp,'",'); set s=string(s,'abs(Compare(a."',column_Name_tmp,'",b."',column_Name_tmp,'")),',"char"(39),Utable_,"char"(39)); set s=string(s,' from ',table_,' as a, ',table1,' as b where a."',recid_tmp,'"= b."',recid_tmp,'" )'); execute immediate s end if end loop For_NewColumns_loop2; close NewColumns; /* очистка о данных которые не изменились */ delete from tblOrlovTMP where keyOrg = 0; delete from tblOrlovTMP where(FlagDb = 0 or FlagDb is null); /* сканирование если надо всталять или удалять всю строку */ open NewStrings; For_NewStrings_loop: loop fetch next NewStrings into column_id_tmp; if sqlstate = Err_not_Found then leave For_NewStrings_loop end if; delete from tblOrlovTMP where(name_Table = Table1 or name_Table = Table_) and flagDb > 0 and keyorg = column_id_tmp end loop For_NewStrings_loop; close NewStrings; /* Вставка данных в таблицу OrlovTemp */ insert into OrlovTemp( keyOrg,Flagdb,Name_table) ( select distinct keyorg,1,Name_table from tblOrlovTMP where(name_Table = UTable1 or name_Table = UTable_) and FlagDb > 0); insert into OrlovTemp( keyOrg,Flagdb,Name_table) ( select distinct keyorg,-2,UTable_ from tblOrlovTMP where(name_Table = UTable1 or name_Table = UTable_) and FlagDb = -2); insert into OrlovTemp( keyOrg,Flagdb,Name_table) ( select distinct keyorg,-1,UTable_ from tblOrlovTMP where(name_Table = UTable1 or name_Table = UTable_) and FlagDb = -1); select column_name into column_name_tmp from SYS.SYSCOLUMN where column_id = 1 and table_id = (select table_id from SYS.SYStable where table_name = table_); set s=string('delete from "',TABLE_,'" where "',column_name_tmp,'" in ('); set s=string(s,' select keyOrg from OrlovTemp where Name_table=',"char"(39),UTable_,"char"(39),')'); execute immediate s; set s=string('insert into "',TABLE_,'"('); set s=string(s,' select * from "',Table1,'" where "',column_name_tmp,'" in '); set s=string(s,' ( select distinct keyOrg from OrlovTemp where Name_table=',"char"(39),Utable_,"char"(39),'))'); execute immediate s; drop table tblOrlovTMP; commit work end ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
29.03.2005, 17:35
|
|||
|---|---|---|---|
|
|||
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
Да, забыл сказать именно в таблице OrlovTemp получается информация какие записи надо менять там idrec autoincrement keyOrg integer - номер записи FlagDb integer - удалять/изменять/вставлять Name_table varchar(255) - в какой таблице ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
31.03.2005, 12:25
|
|||
|---|---|---|---|
|
|||
Сравнить данные в таблице(ах) в 2х базах |
|||
|
#18+
С RepServerom поставляеться утилита Subcmp (NT) или Rs_subcmp (Unix). Утилита позволяет посмотреть и если надо то синхронизировать таблицы по принципу Prymary Replicate. На ASe работает довольно быстро(если сегмента данных Tempdb хватает) Пробовал синхронизацию 1.5 гб на одном сервере в двух базах. Прошла за 30 минут. Не знаю работает ли это для ASA. По смыслу должно, так как репсервер против ASA ничего не имеет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|

start [/forum/topic.php?fid=55&tablet=1&tid=2013754]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
52ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
45ms |
get tp. blocked users: |
1ms |
| others: | 225ms |
| total: | 361ms |

| 0 / 0 |
