在 PostgreSQL 中使用 executemany() 在另一个 table 中插入外键
INSERT FOREIGN KEY in another table with executemany() in PostgreSQL
我试图在语句 table 中插入代码列的行值作为公司 Table 的外键。我采取了以下步骤:
正在创建 Tables
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))")
公司table(即)
中包含什么代码栏
code |
-----------
113
221
344
下一步是将需要的数据插入语句 table,如下所示:
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 select 语句字符串分配给 code
变量。下一行然后用 code
压缩语句名称,因为 code
是一个字符串(可迭代),导致 code
的前 3 个字符与 statement_name
,结果为:
[(('balance_sheet', 'S'),), (('income_statement', 'E'),), (('cash_flow', 'L'),)]
这就是 'S'
的来源 - 它是 code
字符串中 "SELECT" 的第一个字符。 'S'
是一个字符串,而不是 statements
table 架构中定义的整数,因此出现错误。
您可以看到使用 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.
中执行
我试图在语句 table 中插入代码列的行值作为公司 Table 的外键。我采取了以下步骤:
正在创建 Tables
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))")
公司table(即)
中包含什么代码栏 code |
-----------
113
221
344
下一步是将需要的数据插入语句 table,如下所示:
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 select 语句字符串分配给 code
变量。下一行然后用 code
压缩语句名称,因为 code
是一个字符串(可迭代),导致 code
的前 3 个字符与 statement_name
,结果为:
[(('balance_sheet', 'S'),), (('income_statement', 'E'),), (('cash_flow', 'L'),)]
这就是 'S'
的来源 - 它是 code
字符串中 "SELECT" 的第一个字符。 'S'
是一个字符串,而不是 statements
table 架构中定义的整数,因此出现错误。
您可以看到使用 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.