python - 在 PostgreSQL 中使用 executemany() 在另一个表中插入外键

标签 python postgresql insert foreign-keys executemany

我试图将语句表中代码列的行值作为公司表中的外键插入。我采取了以下步骤:

创建表

cur.execute("CREATE TABLE IF NOT EXISTS companies (code INT NOT NULL PRIMARY KEY, short_name VARCHAR(255) NOT NULL, long_name VARCHAR(255) NOT NULL)")

cur.execute("CREATE TABLE IF NOT EXISTS statements (statement_id SERIAL NOT NULL PRIMARY KEY, statement_name VARCHAR(255) NOT NULL, code INT NOT NULL, FOREIGN KEY (code) REFERENCES companies_list (code))")

公司表中包含什么代码列(即)

 code |
-----------
  113
  221
  344

下一步是将需要的数据插入到语句表中,如下所示:

statement_name = ["balance_sheet", "income_statement", "cash_flow"]

code = "SELECT code FROM companies_list WHERE code IS NOT NULL"

statements = [tuple((t,)) for t in zip(statement_name, code)]

query = "INSERT INTO statements (statement_name, code) VALUES %s"
cur.executemany(query, statements)

我收到以下错误:

psycopg2.DataError: invalid input syntax for integer: "S"
LINE 1: ...ents (statement_name, code) VALUES ('balance_sheet', 'S')

我想要得到的最终结果如下:

statement_id |   statement_name    |   code
---------------------------------------------
     1           balance_sheet         113
     2           income_statement      113
     3           cash_flow             113
     4           balance_sheet         221
     5          income_statement       221
     6           cash_flow             221

最佳答案

错误来自这一行:

code = "SELECT code FROM companies_list WHERE code IS NOT NULL"

这不执行实际查询,它将 SQL 选择语句字符串分配给 code 变量。下一行然后用 code 压缩语句名称,因为 code 是一个字符串(可迭代),导致 code 的前 3 个字符> 使用 statement_name 中的项目进行压缩,结果为:

[(('balance_sheet', 'S'),), (('income_statement', 'E'),), (('cash_flow', 'L'),)]

这就是 'S' 的来源 - 它是 code 字符串中“SELECT”的第一个字符。 'S' 是一个字符串,而不是 statements 表的架构中定义的整数,因此会出现错误。

您可以看到使用 cursor.mogrify() 生成的查询:

>>> statement_name = ["balance_sheet", "income_statement", "cash_flow"]
>>> code = "SELECT code FROM companies_list WHERE code IS NOT NULL"
>>> statements = [tuple((t,)) for t in zip(statement_name, code)]
>>> query = "INSERT INTO statements (statement_name, code) VALUES %s"
>>> for args in statements:
...     print(cur.mogrify(query, args))
... 
INSERT INTO statements (statement_name, code) VALUES ('balance_sheet', 'S')
INSERT INTO statements (statement_name, code) VALUES ('income_statement', 'E')
INSERT INTO statements (statement_name, code) VALUES ('cash_flow', 'L')

解决此问题的一种方法是执行包含在 code 中的查询以获取公司代码列表,然后使用它来构造 INSERT 查询:

import itertools

cur.execute("SELECT code FROM companies_list WHERE code IS NOT NULL")
codes = [row[0] for row in cur.fetchall()]
query = 'INSERT INTO statements (statement_name, code) VALUES (%s, %s)'
args = itertools.product(statement_name, codes)
cur.executemany(query, args)

在这里itertools.product()用于形成报表名称和公司代码的笛卡尔积。这是在模仿数据库连接功能,因此如果语句类型在您的数据库中可用,最好用 SQL 而不是 Python 来完成。

关于python - 在 PostgreSQL 中使用 executemany() 在另一个表中插入外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34394022/

相关文章:

mysql - INSERT INTO with Increment 变量

Python 中带字典的 MySQL 动态查询语句

mysql - 结果在插入期间由多行组成

python - 带有 TFIDF 的 Spark MLLIB K-means 中的索引超出范围用于文本杂乱

python - 我可以在 Flask-SQLAlchemy 中使用数组枚举列吗?

python - 如何更改 pandas DataFrame 标题的样式?

python - 如何在matplotlib中设置轴乘数的值?

sql - 为什么这个 SQL 查询会陷入无限循环?

Postgresql pgstartup.log 文件问题

python - 合并 2 个以上子查询的有效查询