为什么pymsql不将记录插入表中?

时间:2019-11-03 07:11:16

标签: python python-3.x pymsql

我在python开发中是相当新的。我有一个很长的python脚本,可以“克隆”数据库并添加其他存储的函数和过程。克隆意味着仅复制数据库架构。这些步骤可以正常工作。

我的问题是关于 pymsql 插入执行: 我必须将一些表内容复制到新的数据库中。我没有任何SQL错误。如果我调试或打印创建的 INSERT INTO 命令是正确的(我已经在sql编辑器/处理程序中对其进行了测试)。插入执行正确,因为结果包含确切的行号...但是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 个答案:

答案 0 :(得分:2)

您在这里有2个主要问题:

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

表名无法参数化,因此我们对此无能为力,但您需要参数化值。我已经对代码进行了多次更正,涉及类型检查和参数化。

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中,我注意到executemanypsycopg2中无法正常工作;而是将每个条目作为单个查询发送。您需要使用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()

答案 1 :(得分:1)

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

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()