【问题标题】:TypeError when inserting JSON data into MySQL using MySQL-Python使用 MySQL-Python 将 JSON 数据插入 MySQL 时出现 TypeError
【发布时间】:2014-08-16 01:03:27
【问题描述】:

我正在尝试使用 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 错误。这是因为这些值没有用引号括起来 (')。

想解决的问题?

【问题讨论】:

    标签: python mysql mysql-python sql-insert


    【解决方案1】:

    为了使用 MySQLdb 的 cursor.execute 方法参数化您的查询,execute 的第二个参数必须是一个值序列;在您的for 循环中,您将使用以下行将这些值连接到一个字符串中:

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

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


    为了通过 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,只要您同时不更改 dict。

    一般来说,这应该适用于 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 对象中已经存在原子纬度/经度字段。

    【讨论】:

      猜你喜欢
      • 2018-03-02
      • 2011-05-14
      • 2018-01-04
      • 1970-01-01
      • 2020-10-06
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      相关资源
      最近更新 更多