简体   繁体   English

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

[英]INSERT FOREIGN KEY in another table with executemany() in PostgreSQL

I tried to insert row values for code column in statements table as a foreign key from companies Table. 我试图将语句表中代码列的行值作为来自公司表的外键插入。 i took the following steps: 我采取了以下步骤:

Creating 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))")

What code column contains in companies table ( ie ) 公司表(即)中包含哪些代码列

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

The next step is inserting wanted data to statements table as below : 下一步是将所需数据插入到语句表中,如下所示:

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)

i got the following error : 我收到以下错误:

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

The Final result i want to get is like below : 我想要得到的最终结果如下所示:

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

The error arises from this line: 错误是由此行引起的:

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

This does not perform an actual query, it assigns the SQL select statement string to the code variable. 这不会执行实际查询,而是将SQL select语句字符串分配给code变量。 The next line then zips the statement names with code which, because code is a string (an iterable), results in the first 3 characters of code being zipped with the items from statement_name , the result being: 然后,下一行用code压缩语句名称,由于code是字符串(可迭代),导致code的前3个字符与statement_name的项目一起压缩,结果为:

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

So that's where the 'S' is coming from - it's the first character of "SELECT" in the code string. 这就是'S'的来源-它是code字符串中“ SELECT”的第一个字符。 'S' is a string, not an integer as defined in the schema for the statements table, hence the error. 'S'是一个字符串,而不是在statements表的架构中定义的整数,因此是错误。

You can see the queries generated with cursor.mogrify() : 您可以看到使用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')

One way of fixing this is to execute the query contained in code to get a list of company codes, then use that to construct the INSERT query: 解决此问题的一种方法是执行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)

Here itertools.product() is used to form the Cartesian product of the statement names and the company codes. 在这里, itertools.product()用于形成语句名称和公司代码的笛卡尔乘积。 This is mimicking database join functionality, so if the statement types are available in your database, it might be better to do it in SQL rather than Python. 这是在模仿数据库联接功能,因此,如果数据库中有语句类型可用,则最好使用SQL而不是Python。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM