在您的情况下,我处理问题的方法是:
在数据库中分别创建一组相应的表,通过从给定的 XML 中提取建模,这些表依次代表公司的产品模型。
创建并使用计划的每日同步作业,该作业可能会执行少量 SQL 命令,以便通过解析产品 XML 到创建的表中来刷新数据或引入新命令。
为了更加实用:
(此图表基于从您的 XML 生成的 XSD 创建的)
所有其余部分都可以视为Products 表中的常规列,因为它们仅构成1-1 关系。
接下来,在您的数据库中创建所需的表(您可以使用 XSD2DB Schema 转换器工具来创建 DDL 脚本,我是手动完成的):
companydb.products
CREATE TABLE companydb.products (
Id INT(11) NOT NULL,
Version INT(11) DEFAULT NULL,
InsertDate DATETIME DEFAULT NULL,
Warrenty TINYINT(1) DEFAULT NULL,
Price DECIMAL(19, 2) DEFAULT NULL,
ModelCode INT(11) DEFAULT NULL,
ModelColor VARCHAR(10) DEFAULT NULL,
Model VARCHAR(255) DEFAULT NULL,
ModelSize VARCHAR(10) DEFAULT NULL,
InternalColor VARCHAR(10) DEFAULT NULL,
InternalSize VARCHAR(10) DEFAULT NULL,
PRIMARY KEY (Id)
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci
COMMENT = 'Company''s Products';
companydb.productsimages
CREATE TABLE companydb.productimages (
Id INT(11) NOT NULL AUTO_INCREMENT,
ProductId INT(11) DEFAULT NULL,
Size VARCHAR(10) DEFAULT NULL,
FileName VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (Id),
CONSTRAINT FK_productsimages_products_Id FOREIGN KEY (ProductId)
REFERENCES companydb.products(Id) ON DELETE RESTRICT ON UPDATE RESTRICT
)
ENGINE = INNODB
AUTO_INCREMENT = 1
CHARACTER SET utf8
COLLATE utf8_general_ci
COMMENT = 'Products'' Images';
companydb.productsoptions
CREATE TABLE companydb.productoptions (
Id INT(11) NOT NULL AUTO_INCREMENT,
ProductId INT(11) DEFAULT NULL,
Type VARCHAR(255) DEFAULT NULL,
`Option` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (Id),
CONSTRAINT FK_producstsoptions_products_Id FOREIGN KEY (ProductId)
REFERENCES companydb.products(Id) ON DELETE RESTRICT ON UPDATE RESTRICT
)
ENGINE = INNODB
AUTO_INCREMENT = 1
CHARACTER SET utf8
COLLATE utf8_general_ci;
- 至于要发生的同步作业过程,您可以轻松地创建一个MySql event 并使用Event Scheduler 来控制它,我创建了所需的
event,它正在调用您将在下面找到的存储过程 (SyncProductsDataFromXML),请看:
CREATE DEFINER = 'root'@'localhost' 事件
companydb.ProductsDataSyncEvent 按计划每“1”天开始
'2014-06-13 01:27:38' COMMENT '同步产品表
产品 XML 的 DO BEGIN SET @productsXml =
LOAD_FILE('C:/MySqlXmlSync/products.xml');称呼
SyncProductsDataFromXML(@productsXml);结尾;
ALTER EVENT companydb.ProductsDataSyncEvent 启用
现在有趣的部分正在发生,这里是同步存储过程(注意上面的event 是如何调用它的):
CREATE DEFINER = 'root'@'localhost'
PROCEDURE companydb.SyncProductsDataFromXML(IN productsXml MEDIUMTEXT)
BEGIN
DECLARE totalProducts INT;
DECLARE productIndex INT;
SET totalProducts = ExtractValue(productsXml, 'count(//export_management/product)');
SET productIndex = 1;
WHILE productIndex <= totalProducts DO
SET @productId = CAST(ExtractValue(productsXml, 'export_management/product[$productIndex]/@id') AS UNSIGNED);
INSERT INTO products(`Id`, `Version`, InsertDate, Warrenty, Price, ModelCode, Model, ModelColor, ModelSize, InternalColor, InternalSize)
VALUES(
@productId,
ExtractValue(productsXml, 'export_management/product[$productIndex]/version'),
ExtractValue(productsXml, 'export_management/product[$productIndex]/insert_date'),
CASE WHEN (ExtractValue(productsXml, 'export_management/product[$productIndex]/warrenty')) <> 'false' THEN 1 ELSE 0 END,
CAST(ExtractValue(productsXml, 'export_management/product[$productIndex]/price') as DECIMAL),
ExtractValue(productsXml, 'export_management/product[$productIndex]/model/code'),
ExtractValue(productsXml, 'export_management/product[$productIndex]/model/model'),
ExtractValue(productsXml, 'export_management/product[$productIndex]/model/color'),
ExtractValue(productsXml, 'export_management/product[$productIndex]/model/size'),
ExtractValue(productsXml, 'export_management/product[$productIndex]/internal/color'),
ExtractValue(productsXml, 'export_management/product[$productIndex]/internal/size')
);
SET @totalImages = ExtractValue(productsXml, 'count(//export_management/product[$productIndex]/images/image)');
SET @imageIndex = 1;
WHILE (@imageIndex <= @totalImages) DO
INSERT INTO productimages(ProductId, Size, FileName) VALUES(@productId, 'small', EXTRACTVALUE(productsXml, 'export_management/product[$productIndex]/images/image[$@imageIndex]/small'));
SET @imageIndex = @imageIndex + 1;
END WHILE;
SET @totalStandardOptions = ExtractValue(productsXml, 'count(//export_management/product[$productIndex]/options/s_option)');
SET @standardOptionIndex = 1;
WHILE (@standardOptionIndex <= @totalStandardOptions) DO
INSERT INTO productoptions(ProductId, `Type`, `Option`) VALUES(@productId, 'Standard Option', EXTRACTVALUE(productsXml, 'export_management/product[$productIndex]/options/s_option[$@standardOptionIndex]'));
SET @standardOptionIndex = @standardOptionIndex + 1;
END WHILE;
SET @totalExtraOptions = ExtractValue(productsXml, 'count(//export_management/product[$productIndex]/options/extra_option)');
SET @extraOptionIndex = 1;
WHILE (@extraOptionIndex <= @totalExtraOptions) DO
INSERT INTO productoptions(ProductId, `Type`, `Option`) VALUES(@productId, 'Extra Option', EXTRACTVALUE(productsXml, 'export_management/product[$productIndex]/options/extra_option[$@extraOptionIndex]'));
SET @extraOptionIndex = @extraOptionIndex + 1;
END WHILE;
SET productIndex = productIndex + 1;
END WHILE;
END
大功告成,这是此过程的最终预期结果:
注意:我已将整个代码提交到我的 GitHub 存储库之一:XmlSyncToMySql
更新:
因为您的 XML 数据可能大于 TEXT 字段允许的最大值,所以我已将 productsXml 参数更改为 MEDIUMTEXT。查看此答案,其中概述了各种文本数据类型的最大允许大小:
Maximum length for MYSQL type text