为什么 pymysql 不将记录插入 table?

Why pymysql not insert record into table?

我在 python 开发方面还很陌生。我有一个很长的 python 脚本,用于“克隆”数据库并添加额外的存储函数和过程。克隆意味着仅复制 DB.These 个步骤的模式工作正常。

我的问题是关于 pymysql 插入执行: 我必须将一些 table 内容复制到新数据库中。我没有收到任何 sql 错误。如果我调试或打印创建的 INSERT INTO 命令是正确的(我已经在 sql editor/handler 中对其进行了测试)。插入执行是正确的,因为结果包含确切的行号...但是目标 table 在 dest.DB 中缺少所有行... (当然已经定义了DB_*变量!)

import pymysql

liveDbConn = pymysql.connect(DB_HOST, DB_USER, DB_PWD, LIVE_DB_NAME)
testDbConn = pymysql.connect(DB_HOST, DB_USER, DB_PWD, TEST_DB_NAME)

tablesForCopy = ['role', 'permission']
for table in tablesForCopy:
    with liveDbConn.cursor() as liveCursor:
        # Get name of columns
        liveCursor.execute("DESCRIBE `%s`;" % (table))
        columns = '';
        for column in liveCursor.fetchall():
            columns += '`' + column[0] + '`,'
        columns = columns.strip(',')
        
        # Get and convert values
        values = ''
        liveCursor.execute("SELECT * FROM `%s`;" % (table))
        for result in liveCursor.fetchall():
            data = []
            for item in result:
                if type(item)==type(None):
                    data.append('NULL')
                elif type(item)==type('str'):
                    data.append("'"+item+"'")
                elif type(item)==type(datetime.datetime.now()):
                    data.append("'"+str(item)+"'")
                else:  # for numeric values
                    data.append(str(item))
            v = '(' + ', '.join(data) + ')'
            values += v + ', '
    values = values.strip(', ')
    
    print("### table: %s" % (table))
    testDbCursor = testDbConn.cursor()
    testDbCursor.execute("INSERT INTO `" + TEST_DB_NAME + "`.`" + table + "` (" + columns + ") VALUES " + values + ";")
    print("Result: {}".format(testDbCursor._result.message))
    

liveDbConn.close()
testDbConn.close()

结果是:

### table: role 
Result: b"'Records: 16  Duplicates: 0  Warnings: 0"
### table: permission 
Result: b'(Records: 222  Duplicates: 0  Warnings: 0'

我做错了什么?谢谢!

这里有 2 个主要问题:

  1. 您不使用 conn.commit()(此处为 liveDbConn.commit()testDbConn.commit())。如果不提交这些更改,将不会反映对数据库的更改。请注意,所有 更改 都需要提交,但 SELECT 则不需要。
  2. 您的查询对 SQL 注入开放。这是一个严重的问题。

Table 名称无法参数化,因此我们对此无能为力,但您需要参数化您的值。我对与类型检查和参数化相关的代码进行了多次更正。

for table in tablesForCopy:
    with liveDbConn.cursor() as liveCursor:        
        liveCursor.execute("SELECT * FROM `%s`;" % (table))
        name_of_columns = [item[0] for item in liveCursor.description]
        insert_list = []
        for result in liveCursor.fetchall():
            data = []
            for item in result:
                if item is None: # test identity against the None singleton
                    data.append('NULL')
                elif isinstance(item, str): # Use isinstance to check type
                    data.append(item)
                elif isinstance(item, datetime.datetime):
                    data.append(item.strftime('%Y-%m-%d %H:%M:%S'))
                else:  # for numeric values
                    data.append(str(item))
            insert_list.append(data)

    testDbCursor = testDbConn.cursor()
    placeholders = ', '.join(['`%s`' for item in insert_list[0]])
    testDbCursor.executemany("INSERT INTO `{}.{}` ({}) VALUES ({})".format(
                                                                TEST_DB_NAME, 
                                                                table, 
                                                                name_of_columns, 
                                                                placeholders),
                             insert_list)
    testDbConn.commit()

来自this github thread, I notice that executemany does not work as expected in psycopg2; it instead sends each entry as a single query. You'll need to use execute_batch

from psycopg2.extras import execute_batch

execute_batch(testDbCursor,
              "INSERT INTO `{}.{}` ({}) VALUES ({})".format(TEST_DB_NAME, 
                                                            table, 
                                                            name_of_columns, 
                                                            placeholders),
              insert_list)
testDbConn.commit()

如何使用 python pymsql 将数据插入 table 在下面找到我的解决方案

import pymysql
import datetime

# Create a connection object
dbServerName    = "127.0.0.1"
port = 8889
dbUser          = "root"
dbPassword      = ""
dbName          = "blog_flask"
# charSet         = "utf8mb4"

conn   = pymysql.connect(host=dbServerName, user=dbUser, password=dbPassword,db=dbName, port= port)
try:
    # Create a cursor object
    cursor           = conn.cursor()

    # Insert rows into the MySQL Table 
    now = datetime.datetime.utcnow()
    my_datetime = now.strftime('%Y-%m-%d %H:%M:%S')
    cursor.execute('INSERT INTO posts (post_id, post_title, post_content, \
    filename,post_time) VALUES (%s,%s,%s,%s,%s)',(5,'title2','description2','filename2',my_datetime))
    conn.commit()

except Exception as e:
    print("Exeception occured:{}".format(e))

finally:
    conn.close()