我尝试使用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错误。这是因为这些值没有用引号括起来('
)。
修复的想法?
答案 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字段。