powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / xsd+2 родителя+identity+XMLBulkLoad
4 сообщений из 4, страница 1 из 1
xsd+2 родителя+identity+XMLBulkLoad
    #33647229
staya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Много уже говорилось о том, как описывать данные в xsd-схемах, связанные по принципу parent-child. При этом данные в xml хранятся в виде вложенной структуры, а внешние ключи для дочерней таблицы при закачке с помощью XMLBulkLoad создаются автоматически, и их значения будут соответствовать значению первичного ключа для родительского элемента в xml-данных. Причем, если в родительской таблице первичный ключ автоинкрементный, проблем не возникает, для дочерних таблиц он будет создаваться также автоматически и соответствовать родительскому.
Эта схема описывает работу с древовидной структурой данных, другими словами связь “one-to-many”. И всё было бы хорошо, но представим себе такую часто встречающуюся ситуацию. Нам необходимо создать справочник + некую таблицу, одно из полей которой будет ссылаться на этот справочник. Нетрудно заметить, что справочник при этом будет выступать в качестве «родителя», а таблица, на него ссылающаяся, станет дочерней. Рассмотрим на примере:

CREATE TABLE Category (
CategoryID int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
CategoryName varchar(255)
)

CREATE TABLE Books (
BookID int IDENTITY(1,1) NOT NULL PRIMARY KEY,
Title varchar(255),
CategoryID int NOT NULL
)


Справочником в данном случае будет таблица категорий «Category», в таблице книг «Books» каждая запись содержит ссылку на категорию. Используя описанный выше алгоритм, построим xsd-схему:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sql="urn:schemas-microsoft-com:mapping-schema"
>

<xsd:annotation>
<xsd:appinfo>
<sql:relationship name="BookCategory"
parent="Category"
parent-key="CategoryID"
child="Books"
child-key="CategoryID"/>
</xsd:appinfo>
</xsd:annotation>

<xsd:element name="root" sql:is-constant="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Categories" sql:is-constant="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>


<xsd:element name="Categories" sql:is-constant="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Category" sql:relation="Category" sql:key-fields="CategoryID" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="CategoryID" type="xsd:int" sql:identity="ignore"/>
<xsd:element name="CategoryName" type="xsd:string"/>
<xsd:element ref="Books" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:element name="Books"
sql:relation="Books"
sql:relationship="BookCategory">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Title" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>


Сопутствующий ей пример xml-данных можно привести такой:

<root>
<Categories>
<Category>
<CategoryID>1</CategoryID>
<CategoryName>Художественная литература</CategoryName>
<Books>
<Title>Первая труба к бою против чудовищного строя женщин</Title>
</Books>
<Books>
<Title>Меня не купишь</Title>
</Books>
</Category>
<Category>
<CategoryID>2</CategoryID>
<CategoryName>Компьютерная литература</CategoryName>
<Books>
<Title>Путь камикадзе. Как разработчику программного обеспечения выжить в безнадежном проекте</Title>
</Books>
</Category>
</Categories>
</root>

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

CREATE TABLE Authors(
AuthorID int IDENTITY(1,1) NOT NULL PRIMARY KEY,
AuthorName varchar(255) NOT NULL
)


В таблицу же книг добавляем еще одно поле:

CREATE TABLE Books (
BookID int IDENTITY(1,1) NOT NULL PRIMARY KEY,
Title varchar(255),
CategoryID int NOT NULL,
AuthorID int
)


По идее, авторов может быть много, но в данном случае это неважно.

Прошу прощение за столь длинное предисловие, но вопрос, собственно, заключается в том – что с этим делать дальше? Возможно ли столь же лихо, как с одним справочником, заполнить значения идентификатора второго для дочерней таблицы.
Решение без автоматического заполнения видится таким:
структура данных xsd

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sql="urn:schemas-microsoft-com:mapping-schema"
>
<xsd:element name="root" sql:is-constant="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Categories"/>
<xsd:element ref="Authors"/>
<xsd:element ref="Books"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>


<xsd:element name="Categories" sql:is-constant="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Category" sql:relation="Category" sql:key-fields="CategoryID" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="CategoryID" type="xsd:int"/>
<xsd:element name="CategoryName" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:element name="Authors" sql:is-constant="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Author" sql:relation="Authors" sql:key-fields="AuthorID" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="AuthorID" type="xsd:int"/>
<xsd:element name="AuthorName" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:element name="Books" sql:is-constant="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Book" sql:relation="Books"
maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Title" type="xsd:string"/>
<xsd:element name="CategoryID" type="xsd:int"/>
<xsd:element name="AuthorID" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>

данные xml

<root>
<Categories>
<Category>
<CategoryID>1</CategoryID>
<CategoryName>Художественная литература</CategoryName>
</Category>
<Category>
<CategoryID>2</CategoryID>
<CategoryName>Компьютерная литература</CategoryName>
</Category>
</Categories>

<Authors>
<Author>
<AuthorID>1</AuthorID>
<AuthorName>Эрик Маккормак</AuthorName>
</Author>
<Author>
<AuthorID>2</AuthorID>
<AuthorName>Мартин Касарьего</AuthorName>
</Author>
<Author>
<AuthorID>3</AuthorID>
<AuthorName>Эдвард Йордон</AuthorName>
</Author>
</Authors>

<Books>
<Book>
<Title>Первая труба к бою против чудовищного строя женщин</Title>
<CategoryID>1</CategoryID>
<AuthorID>1</AuthorID>
</Book>
<Book>
<Title>Меня не купишь</Title>
<CategoryID>1</CategoryID>
<AuthorID>2</AuthorID>
</Book>
<Book>
<Title>Путь камикадзе. Как разработчику программного обеспечения выжить в безнадежном проекте</Title>
<CategoryID>2</CategoryID>
<AuthorID>3</AuthorID>
</Book>
</Books>
</root>


В таком варианте все работает, если идентификаторы справочников заполнять значениями данных из xml, а не автоинкрементом.
Вопрос для обсуждения:
Возможно ли внутренние идентификаторы справочников использовать только для организации связей внутри самого xml? А при выкачивании справочников в базу присваивать им другие (автоинкрементные) идентификаторы, но в дочерних записях делать ссылки на эти другие идентификаторы?
...
Рейтинг: 0 / 0
xsd+2 родителя+identity+XMLBulkLoad
    #33648269
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
staya...Вопрос для обсуждения:
Возможно ли внутренние идентификаторы справочников использовать только для организации связей внутри самого xml? А при выкачивании справочников в базу присваивать им другие (автоинкрементные) идентификаторы, но в дочерних записях делать ссылки на эти другие идентификаторы?

Ответ в лучшем стиле здешнего форума: а зачем вам это надо?
Из "академического интереса" что-ли?
Если вы взяли на себя труд (или кто-то до вас, предоставив "готовые" данные) определить значения первичных/внешних ключей в исходном XML-файле, то - к чему "городить огород" с заменой этих "естественных" ключей на какой-то авто-инкремент или что-либо еще "потустороннее"?
Делайте структуру данных в БД соответствующую структуре своих справочников/каталогов вместе с их "родными" ключами и не парьтесь... .

З.Ы. Могу предположить, как вариант "фантазии на тему", что исходные XML-файлы для загрузки в БД приходят периодически с "несогласованными" ключами, т.е. уникальность внутренних ссылок по ключам "живет" только в пределах одного файла (бред, конечно, но очень уж хочется ваш вопрос "притянуть за уши" к реальной проблеме). Даже в этом случае есть простой выход - с помощью XSLT предварительно заменить ключи исходного XML-файла на ключи принимающей структуры БД (например GUID-ы) и грузить опять же - как есть, без всяких заморочек с авто-инкрементами...

З.З.Ы. к тому же - авто-инкременты в суррогатных ключах таблиц БД это "вчерашний день" для технологии РСУБД...
...
Рейтинг: 0 / 0
xsd+2 родителя+identity+XMLBulkLoad
    #33648521
staya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qu-qu
Ответ в лучшем стиле здешнего форума: а зачем вам это надо?
Из "академического интереса" что-ли?

Ну, и из него тоже :). А что, нынче такого уже и существовать не может? :)

qu-qu
Если вы взяли на себя труд (или кто-то до вас, предоставив "готовые" данные) определить значения первичных/внешних ключей в исходном XML-файле, то - к чему "городить огород" с заменой этих "естественных" ключей на какой-то авто-инкремент или что-либо еще "потустороннее"?
Делайте структуру данных в БД соответствующую структуре своих справочников/каталогов вместе с их "родными" ключами и не парьтесь... .

З.Ы. Могу предположить, как вариант "фантазии на тему", что исходные XML-файлы для загрузки в БД приходят периодически с "несогласованными" ключами, т.е. уникальность внутренних ссылок по ключам "живет" только в пределах одного файла (бред, конечно, но очень уж хочется ваш вопрос "притянуть за уши" к реальной проблеме). Даже в этом случае есть простой выход - с помощью XSLT предварительно заменить ключи исходного XML-файла на ключи принимающей структуры БД (например GUID-ы) и грузить опять же - как есть, без всяких заморочек с авто-инкрементами...

На самом деле, так и есть - файлы для загрузки приходят действительно с уникальными только для этого файла ключами. Т.е. по сути дела есть некая распределенная гетерогенная БД. Можно xslt использовать, можно еще массой способов воспользоваться, но хотелось обойтись только одним инструментом.
Кстати, кажется, я уже поняла, как эту задачу решить таким способом, хотя на практике я его применять и не буду.

qu-qu
З.З.Ы. к тому же - авто-инкременты в суррогатных ключах таблиц БД это "вчерашний день" для технологии РСУБД...
Это еще почему? :) И что значит суррогатные? Для Вас ключи обязательно должны иметь какой-то физический смысл? :)
...
Рейтинг: 0 / 0
xsd+2 родителя+identity+XMLBulkLoad
    #33648779
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
staya... И что значит суррогатные? ...

О-о-о-о, тема "суррогатных" и "естественных" ключей многократно тут обсуждалась на форумах типа "Сравнение БД" и пр. специализированных СУБД-шных... (поиск вам поможет узнать о них побольше).
"Суррогатные" и значит то, что на самом деле значит это слово в обычном русском языке - не настоящие...
А - придуманные программистом (архитектором системы) для гарантированной уникальной идентификации записей в таблице БД вне зависимости от физического (логического, предметного) смысла данных , содержащихся в этих записях .
В противовес "суррогатным" существуют т.н. "естественные" ключи, которые уже в чистом виде - термин из теории РСУБД ("отношения", "кортежи" и пр. лабуда). Эти-то как раз - целиком и полностью зависят от данных , хранящихся в записи, т.к. должны обеспечивать уникальную идентификацию записи на основе ее содержимого (из-за этого "естественные" ключи - сплошь и рядом "составные" из нескольких полей, и иногда термины "естественный" и "составной" путают в горячих спорах разные "финские парни").
Понятно, что строить отношения в системе типа parent-child на основе "составных" ключей - дело неблагодарное, поэтому все разработчики (архитекторы) рано или поздно переползают на ключи "суррогатные", и почему-то первым кандидатом на тип поля для них оказывается (не только у вас) - int (bigint) identity(1,1).
Уже 20 лет так "системы" проектируются, и уже 15 лет все подобного рода "разработки" натыкаются на ограничение типа identity(х,у) в распределенных базах (ну не знает "чужая" база о ваших seed-ах и increment-ах, и знать не обязана, по большому счету). И что-бы "разрулить" это противоречие - приходится вводить в структуру "суррогатного" ключа дополнительное поле для идентификации распределенного источника (типа: DBid, id), в итоге - от чего убегали (составные ключи) к тому и прибежали...
Поэтому и говорю - "вчерашний день"... GUID-ы во всех отношениях лучше, гибче, надежнее, бла-бла-бла... (ну, правда - места немного побольше занимают, да еще кое-какой "аккуратности" с обращением требуют).

staya...Кстати, кажется, я уже поняла, как эту задачу решить таким способом, хотя на практике я его применять и не буду...

Каким - "таким", может поделитесь с общественностью?
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / xsd+2 родителя+identity+XMLBulkLoad
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]