【问题标题】:psycopg2 inserting rows as columnspsycopg2 将行作为列插入
【发布时间】:2021-02-03 17:30:38
【问题描述】:

我不确定我是否正确地表达了这一点,但是当从一个数据库查询数据并使用psycopg2 将其插入另一个数据库时,脚本有时会分解数据,并将行作为列插入(即每行每列打印一个字符)如下:

     name     | id_2       | id_1        | blank        | data
--------------+------------+-------------+--------------+--------------
 A            | 1          | a           |              | {json: data}
 B            | a          | 1           |              | {json: data}
 C            | 2          | b           |              | {json: data}
 D            | b          | 2           |              | {json: data}
 E            | 3          | c           |              | {json: data}
 F            | c          | 3           |              | {json: data}

我希望表格如下所示:

     name     | id_2       | id_1        | blank        | data
--------------+------------+-------------+--------------+--------------
 ABCDEF       | 1a2b3c     | a1b2c3      |              | {json: data}

我必须生成的代码是:

import psycopg2, uuid

id_1 = str(uuid.uuid4())

conn1 = psycopg2.connect(
    host='host',
    database=db1,
    user='user',
    password='password')

conn2 = psycopg2.connect(
    host='host',
    database=db2
    user='user',
    password='password')

def generate_data(id_1, name, id_2):

    data = {
        "tag": name,
        "id_2": id_2,
        "id_1": id_1,
        "rand_int": random.randint(0, 86400),
        "rand_uni_1": str(round(random.uniform(0.0, 8.0), 2)),
        "rand_uni_2": str(round(random.uniform(0.0, 16.0), 2)),
        "digi": "",
        "point_type": random.randint(0, 1),
        "garbage_data": "garbage_data"
    }
    data_str = str(json.dumps(data).replace("'", "''"))
    add_data(name, id_2, id_1, data_str)

def add_data(name_rec, id_2_rec, id_1_rec, data_rec):
    insert_data = "INSERT into table(name, id_2, id_1, data) VALUES (%s, %s, %s, %s::jsonb) ON CONFLICT DO NOTHING;"
    try:
        cur = conn2.cursor()
        cur.executemany(insert_data, zip(name_rec, id_2_rec, id_1_rec, data_rec))
        conn2.commit()
        cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn2 is not None:
            conn2.close()

def query_data():
    try:
        create_data_table()
        cur = conn1.cursor()
        cur.execute("SELECT name, table_name FROM existing_table;")
        data_returned = cur.fetchall()
        name = [i[0] for i in data_returned]
        old_table = [i[1] for i in data_returned]
        for x in data_returned:
            name = x[0]
            new_id_2 = x[1][5:].replace("_","-")
            generate_data(id_1_rec, name, new_id_2)
        cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)

def create_data_table():
    with conn2.cursor() as cursor:
        cursor.execute(
            "CREATE TABLE IF NOT EXISTS table "
            "("
            "name VARCHAR(100), "
            "id_2 VARCHAR(50), "
            "id_1 VARCHAR(50), "
            "data JSONB"
            ");"
        )
        conn2.commit()
    cursor.close()

create_data_table()
query_data()

我正在使用 print 语句来验证数据是否显示为应该插入到表中。我在隔离我遇到的有关jsonb 的代码的另一个问题时发现了这一点,我将在接下来发布该问题。我对来自 QA 的 SQL 和 Python(以及 psycopg2)相对较新,因此非常感谢任何帮助!

【问题讨论】:

  • 如果 generate_data 中没有定义 id_1_rec(而且它似乎不是全局的),generate_data 如何使用 id_1_rec 调用 add_data?
  • @Jeremy - 这是一个错字...我替换了很多变量以增加安全措施。 add_data() 应该用id_1 调用,而不是id_1_rec 所以我在上面修复了它。这就是对细节的关注!
  • 我仍然掌握编写函数和将变量作为参数传递的窍门。因此所有print 语句。 :)
  • 为什么不从existing_table 中选择数据,让它看起来像你想要的那样,而不是“重新插入”到新表中?和/或这两张桌子有什么区别?可能,我根本没有真正得到“问题”:)
  • 这是一团糟,所以我并没有真正关注正在发生的事情。我怀疑问题出在这里:cur.executemany(insert_data, zip(name_rec, id_2_rec, id_1_rec))

标签: python python-3.x postgresql psycopg2 psql


【解决方案1】:

今天早上站起来后我抓住了我们的一些开发人员,并解决了这个问题,如果不清楚,就是如上所述将数据输入数据库的方式。

这里的问题在于cur.executemany(insert_data, zip(name_rec, id_2_rec, id_1_rec, data_rec)) 行——更具体地说是executemany 方法和zip() 函数。由于zip() 函数返回一个 zip 对象,它是元组的迭代器,其中每个传递的迭代器中的第一项(以及所有后续项)配对在一起,而executemany 方法准备一个数据库操作(查询或命令)并针对在序列 seq_of_params 中找到的所有参数序列或映射执行它,这导致数据逐个字符地输入到新表中。这已通过将行更改为 cur.execute(insert_data, (name_rec, id_2_rec, id_1_rec, data_rec)) 来解决,现在我的数据按原样显示,即

     name     | id_2       | id_1        | blank        | data
--------------+------------+-------------+--------------+--------------
 ABCDEF       | 1a2b3c     | a1b2c3      |              | {json:data}

我为 混乱 代码道歉,如果我最初没有正确地表达这个问题 - 我在大约 2.5 年前上学音乐并进入这个领域,作为一名 QA,之前没有任何经验,所以这对我来说还是比较新的。

【讨论】:

    猜你喜欢
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 1970-01-01
    相关资源
    最近更新 更多