繁体   English   中英

如何使用Python将具有父/子(类别-子类别)层次结构的CSV数据导入MySQL

[英]How to import csv data with parent/child (category-subcategory) hierarchy to MySQL using Python

我正在使用Python的MySQLdb模块将包含父级/子级(类别-子类别)层次结构的csv文件导入MySQL。 这是一个示例csv文件:

vendor,category,subcategory,product_name,product_model,product_price
First vendor,category1,subcategory1,product1,model1,100
First vendor,category1,subcategory2,product2,model2,110
First vendor,category2,subcategory3,product3,model3,130
First vendor,category2,subcategory4,product5,model7,190

在MySQL中,我想使用具有层次结构的category表,如下所示:

CREATE TABLE IF NOT EXISTS `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`status` tinyint(1) NOT NULL,
PRIMARY KEY (`category_id`),
KEY `parent_id` (`parent_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

我的问题是:如何确定此表中的parent_id

这是我到目前为止拥有的Python脚本:

import MySQLdb
import csv
con = MySQLdb.connect('localhost', 'root', '', 'testdb', use_unicode=True, charset='utf8')
with con:
    cur = con.cursor()
    csv_data = csv.reader(file('test.csv'))
    csv_data.next()
    for row in csv_data:
        cur.execute("SELECT manufacturer_id FROM manufacturer WHERE name=%s", [row[0]],)
        res = cur.fetchall()
        if res:
            vendor_id = res[0][0]
        else:
            cur.execute("INSERT INTO manufacturer (name) VALUES (%s)", (row[0],))
            vendor_id = cur.lastrowid
        cur.execute("SELECT category_id FROM category_description WHERE name=%s", [row[2]])
        res = cur.fetchall()
        if res:
            category_id = res[0][0]
        else:

            # What parent_id should be inserted here?
            cur.execute("INSERT INTO category (`status`, `parent_id`) VALUES (%s,%s)", (1,))

            category_id = cur.lastrowid
            cur.execute("INSERT INTO category_description (category_id, name) VALUES (%s,%s)", (category_id,row[2],))
            cur.execute("INSERT INTO product (model, manufacturer_id, price,) VALUES (%s, %s, %s)", (row[4], `vendor_id`, row[8],))                           
            product_id = cur.lastrowid
            cur.execute("INSERT INTO product_to_category (product_id, category_id) VALUES (%s, %s)", (product_id, category_id,))
    cur.commit()

这是我的示例中使用的其他表的定义:

CREATE TABLE IF NOT EXISTS `manufacturer` (
`manufacturer_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
PRIMARY KEY (`manufacturer_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

CREATE TABLE IF NOT EXISTS `category_description` (
`category_id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`category_id`,`language_id`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

CREATE TABLE IF NOT EXISTS `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`model` varchar(64) NOT NULL,
`manufacturer_id` int(11) NOT NULL,
`price` decimal(15,4) NOT NULL DEFAULT '0.0000',
PRIMARY KEY (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

CREATE TABLE IF NOT EXISTS `product_to_category` (
`product_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`product_id`,`category_id`),
KEY `category_id` (`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

在层次结构表结构中,层次结构顶部的任何成员都没有父级。 我可能会使用NULL父ID来显示此信息,但是根据您定义category表的方式,您似乎想通过给父ID赋值为0来显示此信息。

由于您只有两个级别(类别和子类别)的固定深度层次结构,因此任务相对简单。 对于CSV数据的每一行,您需要:

  1. 检查父表( row[1] )是否在表中; 如果不是,请插入其父ID为0
  2. 从步骤1获取父项的category_id
  3. 检查子级( row[2] )是否在表中; 如果不是,请插入其父ID等于步骤2中的category_id

在示例代码中,您永远不会访问父级( row[1] ); 您需要将其插入表格中,以使其具有孩子可以引用的ID。 如果您已在此之前插入了父母,则可能仍应检查以确保其在其中。

您在这里还有其他问题:

  1. category_description表的PK是在您忘记在表中定义的列( language_id )上定义的。
  2. 您实际上应该在此物理模型中使用InnoDB,以便可以在category_descriptionproductproduct_to_category强制使用外键约束。
  3. 在您的示例中, cur.commit()将引发异常–这是MySQLdb中Connection对象的一种方法。 当然,无论如何都没有为MyISAM表实现COMMIT ,因此您也可以通过完全删除该行来避免异常。
  4. 根据您显示给我们的CSV数据,引用row[8]也会引发异常。 (这是为什么您应该测试MCVE以确保其正常工作的一个很好的例子!)
  5. 如果确实要切换到InnoDB,并且您可能应该这样做,则可以使用with con as cur:在退出with块时获取一个提交自己的游标。 这样可以节省几行代码,并且可以在不对连接对象进行微观管理的情况下管理事务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM