Python3 中的 PostgreSQL - 使用外键创建 table 语句中的语法错误
PostgreSQL in Python3 - SyntaxError in a create table statement with foreign key
我正在尝试创建一个 table (basic_totals),其中包含指向另一个 table(玩家)的主键的外键。我将语句保存在一个字符串中,如下所示:
player_table_name = "players"
basic_table_name = "basic_totals"
basic_table_statement = '''
CREATE TABLE IF NOT EXISTS public.{0} (
id SERIAL PRIMARY KEY,
player_id SERIAL REFERENCES {1}(id),
GP SMALLINT,
3PTA SMALLINT,
3PTM SMALLINT,
FGA SMALLINT,
FGM SMALLINT,
FTA SMALLINT,
FTM SMALLINT,
PTS SMALLINT,
FTM SMALLINT,
PTS SMALLINT,
REB SMALLINT,
AST SMALLINT,
STL SMALLINT,
BLK SMALLINT,
TO SMALLINT
);'''.format(basic_table_name, player_table_name)
当尝试使用连接的游标 (cursor.execute(basic_table_statement)) 执行此语句时,会引发 SyntaxError。
由于其他table(玩家)的创建语句以相同的方式完成(减去外键部分),我假设错误在这部分附近。
我的语法有什么问题,我该如何进一步调试它?
TO
是一个 reserved keyword. If you really insist on using it, you need to use double quotes 来逃避它,例如"to"
。
但是一旦你这样做了,名字就会变成 sensitive,所以 TO
和 "TO"
是不同的名字(因为 TO
是折叠成小写)。
但是,使用带引号的标识符是 strongly discouraged 并且我 高度 建议您找到一个不需要引号的不同列名称。
另一个问题是列名 3PTA
和 3PTM
。标识符不能以数字开头,因此您还需要为它们找到一个不同的名称(除非您想使用那些可怕的双引号)。
内联 REFERENCES 子句不需要重复目标 table 的主键列。您还两次定义了列 FTM
和 PTS
。
不是错误的原因,而是另一个错误的选择是 player_id 的类型 serial
。 serial
不是数据类型。它是 integer
列的缩写,它从序列中获取默认值。永远不要将外键列定义为序列,因为它们引用已经生成的值。所以应该是player_id integer REFERENCES {1}(id),
将所有这些放在一起,SQL 应该如下所示:
CREATE TABLE IF NOT EXISTS some_table (
id serial primary key,
player_id integer references other_table,
gp smallint,
pta3 smallint, --<< here
ptm3 smallint, --<< here
fga smallint,
fgm smallint,
fta smallint,
ftm smallint, --<< only once!
pts smallint, --<< only once!
reb smallint,
ast smallint,
stl smallint,
blk smallint,
to_x smallint --<< change here
);
我正在尝试创建一个 table (basic_totals),其中包含指向另一个 table(玩家)的主键的外键。我将语句保存在一个字符串中,如下所示:
player_table_name = "players"
basic_table_name = "basic_totals"
basic_table_statement = '''
CREATE TABLE IF NOT EXISTS public.{0} (
id SERIAL PRIMARY KEY,
player_id SERIAL REFERENCES {1}(id),
GP SMALLINT,
3PTA SMALLINT,
3PTM SMALLINT,
FGA SMALLINT,
FGM SMALLINT,
FTA SMALLINT,
FTM SMALLINT,
PTS SMALLINT,
FTM SMALLINT,
PTS SMALLINT,
REB SMALLINT,
AST SMALLINT,
STL SMALLINT,
BLK SMALLINT,
TO SMALLINT
);'''.format(basic_table_name, player_table_name)
当尝试使用连接的游标 (cursor.execute(basic_table_statement)) 执行此语句时,会引发 SyntaxError。 由于其他table(玩家)的创建语句以相同的方式完成(减去外键部分),我假设错误在这部分附近。
我的语法有什么问题,我该如何进一步调试它?
TO
是一个 reserved keyword. If you really insist on using it, you need to use double quotes 来逃避它,例如"to"
。
但是一旦你这样做了,名字就会变成 sensitive,所以 TO
和 "TO"
是不同的名字(因为 TO
是折叠成小写)。
但是,使用带引号的标识符是 strongly discouraged 并且我 高度 建议您找到一个不需要引号的不同列名称。
另一个问题是列名 3PTA
和 3PTM
。标识符不能以数字开头,因此您还需要为它们找到一个不同的名称(除非您想使用那些可怕的双引号)。
内联 REFERENCES 子句不需要重复目标 table 的主键列。您还两次定义了列 FTM
和 PTS
。
不是错误的原因,而是另一个错误的选择是 player_id 的类型 serial
。 serial
不是数据类型。它是 integer
列的缩写,它从序列中获取默认值。永远不要将外键列定义为序列,因为它们引用已经生成的值。所以应该是player_id integer REFERENCES {1}(id),
将所有这些放在一起,SQL 应该如下所示:
CREATE TABLE IF NOT EXISTS some_table (
id serial primary key,
player_id integer references other_table,
gp smallint,
pta3 smallint, --<< here
ptm3 smallint, --<< here
fga smallint,
fgm smallint,
fta smallint,
ftm smallint, --<< only once!
pts smallint, --<< only once!
reb smallint,
ast smallint,
stl smallint,
blk smallint,
to_x smallint --<< change here
);