使用MySQL-Python将JSON数据插入MySQL时的TypeError

时间:2014-06-25 12:49:17

标签: python mysql mysql-python sql-insert

我尝试使用MySQLdb将数据从JSON字符串插入MySQL。列总数是固定的。来自JSON字符串的每行数据并不总是具有每列的值。

以下是我的示例代码:

vacant_building = 'http://data.cityofchicago.org/resource/7nii-7srd.json?%24where=date_service_request_was_received=%272014-06-02T00:00:00%27'
obj = urllib2.urlopen(vacant_building)
data = json.load(obj)

def insert_mysql(columns, placeholders, data):
    sql = "INSERT INTO vacant_buildings (%s) VALUES (%s)" % (columns, placeholders)
    db = MySQLdb.connect(host="localhost", user="xxxx", passwd="xxxx", db="chicago_data")
    cur = db.cursor()
    cur.execute(sql, data)

for row in data:
    placeholders = ', '.join(['%s'] * len(row))
    columns = ', '.join(c[:64] for c in row.keys())
    row_data = ', '.join(str(value) for value in row.values())
    insert_mysql(columns, placeholders, row_data)

我收到以下错误:

    query = query % tuple([db.literal(item) for item in args])
TypeError: not all arguments converted during string formatting

我很确定错误与我插入值的方式有关。我试图将其更改为:

sql = "INSERT INTO vacant_buildings (%s) VALUES (%s) (%s)" % (columns, placeholders, data) 

但是我收到1064错误。这是因为这些值没有用引号括起来(')。

修复的想法?

1 个答案:

答案 0 :(得分:1)

为了使用MySQLdb的cursor.execute方法参数化您的查询,execute的第二个参数必须是一系列值;在for循环中,您将这些值一起加入一个字符串,其中包含以下行:

row_data = ', '.join(str(value) for value in row.values())

由于您为等值len(row)的值生成了多个占位符,因此需要向cursor.execute提供多个值。如果你只给它一个字符串,它会将整个字符串放入第一个占位符,而其他字符串不带任何参数。这将抛出一个TypeError - 这种情况下的消息会读取,"没有足够的格式字符串参数,"但我会假设你只是在复制/粘贴时混淆了,因为相反的情况(提供太多参数/占位符太少)会在您指示时读取,"并非在字符串格式化期间转换所有参数。&# 34;


为了通过MySQLdb使用一组可变列运行INSERT语句,您可以像对列和占位符一样完成,但我更喜欢使用扩展的映射类型MySQLdb支持的格式化语法(例如,%(name)s而不是%s),以确保我正确构造了我的查询,而不是将值放入任何错误的顺序。我也喜欢在我自己的代码中使用advanced string formatting

您可以像这样准备输入:

max_key_length = 64
columns = ','.join(k[:max_key_length] for k in row.keys())
placeholders = ','.join('%({})s'.format(k[:max_key_length]) for k in row.keys())
row_data = [str(v) for v in row.values()]

注意到dict理解的顺序是guaranteed,只要你不同时改变字典。

一般来说,这应该适用于insert_mysql函数中的代码。但是,查看您实际从该URL中提取的JSON数据,您应该知道您可能会遇到嵌套问题;例如:

>>> pprint.pprint(data[0])
{u'address_street_direction': u'W',
 u'address_street_name': u'61ST',
 u'address_street_number': u'424',
 u'address_street_suffix': u'ST',
 u'any_people_using_property_homeless_childen_gangs_': True,
 u'community_area': u'68',
 u'date_service_request_was_received': u'2014-06-02T00:00:00',
 u'if_the_building_is_open_where_is_the_entry_point_': u'FRONT',
 u'is_building_open_or_boarded_': u'Open',
 u'is_the_building_currently_vacant_or_occupied_': u'Vacant',
 u'is_the_building_vacant_due_to_fire_': False,
 u'latitude': u'41.78353874626324',
 u'location': {u'latitude': u'41.78353874626324',
               u'longitude': u'-87.63573355602661',
               u'needs_recoding': False},
 u'location_of_building_on_the_lot_if_garage_change_type_code_to_bgd_': u'Front',
 u'longitude': u'-87.63573355602661',
 u'police_district': u'7',
 u'service_request_number': u'14-00827306',
 u'service_request_type': u'Vacant/Abandoned Building',
 u'ward': u'20',
 u'x_coordinate': u'1174508.30988836',
 u'y_coordinate': u'1864483.93566661',
 u'zip_code': u'60621'}

u'location'列的字符串表示形式为:

"{u'latitude': u'41.78353874626324', u'needs_recoding': False, u'longitude': u'-87.63573355602661'}"

您可能不希望将其放入数据库字段中,尤其是考虑到JSON对象中已存在原子lat / lon字段。