Другой хороший вариант проверка lxml , который я нахожу довольно приятными использовать.
А простой пример, взятый от lxml сайта:
from StringIO import StringIO
from lxml import etree
dtd = etree.DTD(StringIO(""""""))
root = etree.XML(" ")
print(dtd.validate(root))
# True
root = etree.XML("bar ")
print(dtd.validate(root))
# False
print(dtd.error_log.filter_from_errors())
# :1:0:ERROR:VALID:DTD_NOT_EMPTY: Element foo was declared EMPTY this one has content
У меня нет личного опыта с этим, но мне кажется, что вы должны иметь возможность однозначно сопоставить PK -> Новый PK для каждого сервера. Например, сгенерируйте новые PK, так что данные с сервера LA имеют PK% 3 == 2, SF имеет PK% 3 == 1, а NY имеет PK% 3 == 0. И поскольку, как я все равно понял ваш вопрос, каждый сервер хранит только отношения FK со своими собственными данными, вы можете обновлять FK таким же образом.
NewLA = OldLA*3-1
NewSF = OldLA*3-2
NewNY = OldLA*3
Затем вы можете объединить их и не иметь дубликатов PK. По сути, как вы уже сказали, это просто создание новых PK, но такое структурирование позволяет вам тривиально обновлять ваши FK (при условии, что, как и я, данные на каждом сервере изолированы). Удачи.
BEST: add a column for RegionCode, and include it on your PKs, but you don't want to do all the leg work.
HACK: if your IDs are INTs, a quick fix would be to add a fixed value based on region to each key on import. INTs can be as large as: 2,147,483,647
local server data:
LA IDs: 1,2,3,4,5,6
SF IDs: 1,2,3,4,5
NY IDs: 1,2,3,4,5,6,7,9
add 100000000 to LA's IDs
add 200000000 to SF's IDs
add 300000000 to NY's IDs
combined server data:
LA IDs: 100000001,100000002,100000003,100000004,100000005,100000006
SF IDs: 200000001,200000002,200000003,200000004,200000005
NY IDs: 300000001,300000002,300000003,300000004,300000005,300000006,300000007,300000009
Я сделал это и говорю, измените ваши ключи (выберите метод) вместо того, чтобы изменять ваш код. Вы неизменно либо пропустите хранимую процедуру, либо внесете ошибку. При изменении данных довольно легко писать тесты для поиска потерянных записей или проверки правильности сопоставления. При изменении кода, особенно кода, который работает правильно, слишком легко что-то упустить.
One thing you could do is set up the tables with regional data to use GUID's. That way, the primary keys in each region are unique, and you can mix and match data (import data from one region to another). For the tables which have shared data (like type tables), you can keep the primary keys the way they are (since they should be the same everywhere).
Here is some information about GUID's: http://www.sqlteam.com/article/uniqueidentifier-vs-identity
Maybe SQL Server Management Studio lets you convert columns to use GUID's easily. I hope so!
Best of luck.
what i have done in a situation like this is this:
Как сказал Джон, я бы использовал GUID для решения задачи слияния. И я вижу два разных решения, для которых требуются идентификаторы GUID:
Это хорошее решение в целом, но если у вас их много кода, отличного от SQL, который каким-то образом связан с тем, как работают ваши идентификаторы, может потребоваться несколько изменений кода. Возможно, поскольку вы объединяете базы данных, вам в любом случае может потребоваться обновить приложение, чтобы оно работало только с данными одного региона в зависимости от того, какой пользователь вошел в систему и т. Д.
Это немного сложнее, но как только вы напишете этот сценарий миграции, вы можете (повторно) запустить его несколько раз, чтобы снова объединить базы данных, если вы испортите его в первый раз. Вот пример:
Table: PERSON (ID INT PRIMARY KEY, Name VARCHAR(100) NOT NULL)
Table: ADDRESS (ID INT PRIMARY KEY, City VARCHAR(100) NOT NULL, PERSON_ID INT)
Ваши сценарии изменения (обратите внимание, что для всех PK мы автоматически генерируем GUID):
ALTER TABLE PERSON ADD UID UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID())
ALTER TABLE ADDRESS ADD UID UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID())
ALTER TABLE ADDRESS ADD PERSON_UID UNIQUEIDENTIFIER NULL
Затем вы обновляете FK, чтобы они соответствовали INTEGER:
--// set ADDRESS.PERSON_UID
UPDATE ADDRESS
SET ADDRESS.PERSON_UID = PERSON.UID
FROM ADDRESS
INNER JOIN PERSON
ON ADDRESS.PERSON_ID = PERSON.ID
Вы делаете это для всех PK ( автоматически генерировать GUID) и FK (обновите, как показано выше).
Теперь вы создаете свою целевую базу данных. В этой целевой базе данных вы также добавляете столбцы UID для всех PK и FK. Также отключите все ограничения FK.
Теперь вы вставляете данные из каждой исходной базы данных в целевую (примечание: мы не вставляем PK и целочисленные FK):
INSERT INTO TARGET_DB.dbo.PERSON (UID, NAME)
SELECT UID, NAME FROM SOURCE_DB1.dbo.PERSON
INSERT INTO TARGET_DB.dbo.ADDRESS (UID, CITY, PERSON_UID)
SELECT UID, CITY, PERSON_UID FROM SOURCE_DB1.dbo.ADDRESS
После того, как вы вставили данные из всех баз данных, вы запускаете код, противоположный исходному, для согласования целочисленных FK с идентификаторами GUID в целевой базе данных:
--// set ADDRESS.PERSON_ID
UPDATE ADDRESS
SET ADDRESS.PERSON_ID = PERSON.ID
FROM ADDRESS
INNER JOIN PERSON
ON ADDRESS.PERSON_UID = PERSON.UID
Теперь вы можете отбросить все столбцы UID: ALTER TABLE PERSON DROP COLUMN UID ИЗМЕНИТЬ ИДЕНТИФИКАЦИОННЫЙ ИДЕНТИФИКАТОР ДОПОЛНИТЕЛЬНОЙ СТОЛБЦА ALTER TABLE ADDRESS DROP COLUMN PERSON_UID
Итак, в конце вы должны получить довольно длинный сценарий миграции, который должен сделать всю работу за вас. Дело в том, что - ЭТО ВЫПОЛНЕНО
ПРИМЕЧАНИЕ: все написанное здесь не проверено.