2

会社のテーブルからの外部キーとしてステートメントテーブルのコード列の行の値を挿入しようとしました。私は次の手順を実行しました:

テーブルの作成

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
4

1 に答える 1

0

エラーは次の行から発生します。

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

これは実際のクエリを実行するのではなく、SQL 選択ステートメント文字列をcode変数に割り当てます。次の行はステートメント名を zip します。 は文字列 (反復可能) でcodeあるためcode、最初の 3 文字がcodeからのアイテムで圧縮さstatement_nameれます。結果は次のようになります。

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

これが の'S'由来です。文字列の「SELECT」の最初のcode文字です。テーブル'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')

これを修正する 1 つの方法は、に含まれるクエリを実行して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()は、ステートメント名と会社コードのデカルト積を形成するために使用されます。これはデータベースの結合機能を模倣しているため、ステートメントの種類がデータベースで使用できる場合は、Python ではなく SQL で実行する方がよい場合があります。

于 2015-12-21T11:26:05.917 に答える