【问题标题】:insert into mysql database with pymysql failing to insert插入mysql数据库,pymysql无法插入
【发布时间】:2018-10-14 22:51:04
【问题描述】:

我正在尝试将虚拟数据插入 mysql 数据库。

数据库结构如下:

database name: messaround database table name: test

表结构:

id (Primary key, auto increment) path (varchar(254))

UPDATED 2 方法和错误。 我有一种方法可以尝试通过以下方式插入:

def insert_into_db(dbcursor, table, *cols, **vals):
    try:
        query = "INSERT INTO {} ({}) VALUES ('{}')".format(table, ",".join(cols),  "'),('".join(vals))  
        print(query)
        dbcursor.execute(query)
        dbcursor.commit()
        print("inserted!")
    except pymysql.Error as exc:
        print("error inserting...\n {}".format(exc))

connection=conn_db()        
insertstmt=insert_into_db(connection, table='test', cols=['path'], vals=['test.com/test2'])

但是,这是失败的说法:

INSERT INTO test () VALUES ('vals'),('cols')
error inserting...
 (1136, "Column count doesn't match value count at row 1")

你能帮忙吗?

谢谢。

【问题讨论】:

  • 我看到路径来自“vals”,它是字符而不是数字。你应该用 "path_val" 之类的引号括起来
  • @UdayS - 你能把这个放到答案中,这样我才能看得更清楚。

标签: python mysql pymysql


【解决方案1】:

如果您使用您的代码:

def insert_into_db(dbcursor, table, *cols, **vals):
    query = "INSERT INTO {} ({}) VALUES ({})".format(table,",".join(cols), ",".join(vals))
    print(query)

insert_into_db('cursor_here', 'table_here', 'name', 'city', name_person='diego', city_person='Sao Paulo')

Python 返回:

INSERT INTO table_here (name,city) VALUES (name_person,city_person)

现在和另一个:

def new_insert_into_db(dbcursor, table, *cols, **vals):
    vals2 = ''
    for first_part, second_part in vals.items():
        vals2 += '\'' + second_part + '\','
    vals2 = vals2[:-1]
    query = "INSERT INTO {} ({}) VALUES ({})".format(table,",".join(cols), vals2)
    print(query)

new_insert_into_db('cursor_here', 'table_here', 'name', 'city', name_person='diego', city_person='Sao Paulo')

Python 将返回正确的 SQL:

INSERT INTO table_here (name,city) VALUES ('diego','Sao Paulo')

【讨论】:

  • 欣赏答案。是否有可能使这不那么复杂?比如,有没有可能用更少的连接让它更容易阅读?
【解决方案2】:

通常在 Python 中,您将参数化查询传递给 DB 驱动程序。见this example in PyMySQL's documentation;它使用占位符构造 INSERT 查询,然后调用 cursor.execute() 传递查询和实际值的元组。

使用参数化查询也是recommended for security purposes,因为它可以击败许多常见的SQL注入攻击。

【讨论】:

    【解决方案3】:

    你应该打印你生成的 sql 语句,这样更容易看出哪里出了问题。

    但我猜你需要在 ",".join(vals) 的字符串值周围加上引号 '(以防有字符串值。
    所以你的代码正在生成

    insert into test (path,) values (test.com/test2,);
    

    但它应该产生

    insert into test (`path`) values ('test.com/test2');
    

    否则请尝试https://github.com/markuman/MariaSQL/,这使得使用 pymysql 将数据插入 MariaDB/MySQL 变得超级容易。

    【讨论】:

    • 你看到我的insertstmt了吗?它在末尾包含一个 path 作为字符串。
    • 不,因为vals = ['test.com/test2,']"values ({})".format(",".join(vals)) 之后只是'values (test.com/test2,)'。但它需要像"'" + ",".join(vals) + "'" 这样的东西。
    • 请查看更新的代码和输出。这仍然不起作用。
    • 我没有看到更新的 sn-p。此外,mysql错误消息正是这样说的:> ...在第1行的'test.com/test2,)VALUES()'附近“)你缺少引号。而且,至少当你在中使用特殊字符时列名,您需要使用反引号。
    • gist.github.com/markuman/d620fb3130d0966307ac71ef728f9381这是你的python字符串最终应该是什么样子,但它看起来像这样insert into test (path,) values (test.com/test2,);
    【解决方案4】:

    如下更改您的查询

    query = "INSERT INTO {} ({}) VALUES ('{}')".format(table, ",".join(cols),  "'),('".join(vals))
    

    当你使用连接时,变量应该是一个列表而不是一个字符串

    table = 'test'
    cols = ['path']
    vals = ['test.com/test2', 'another.com/anothertest']
    
    
    print(query)
    
    "INSERT INTO test (path) VALUES ('test.com/test2'),('another.com/anothertest')"
    

    更新:

    def insert_into_db(dbconnection=None, table='', cols=None, vals=None):
        mycursor = dbconnection.cursor()
        if not (dbconnection and table and cols and vals):
            print('Must need all values')
            quit()
        try:
            query = "INSERT INTO {} ({}) VALUES ('{}')".format(table, ",".join(cols),  "'),('".join(vals))
            mycursor.execute(query)
            dbconnection.commit()
            print("inserted!")
        except pymysql.Error as exc:
            print("error inserting...\n {}".format(exc))
    
    
    connection=conn_db()        
    
    insertstmt=insert_into_db(dbconnection=connection, table='test', cols=['path'], vals=['test.com/test2'])
    

    【讨论】:

    • 我非常感谢您的回答,但我如何通过变量insertstmt 执行此操作,如上所示?
    • 请查看更新后的代码 UPDATE2 上面的错误
    • 仍在努力制定这一点,请参阅上面的UPDATE2
    猜你喜欢
    • 2013-04-18
    • 2018-05-29
    • 2019-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 2019-01-04
    相关资源
    最近更新 更多