正确使用 Psycopg2 SQL 模块
Proper use of Psycopg2 SQL module
由于 Maurice Meyer 让我知道的语法错误编辑了问题
我需要保护应用程序免受 SQL 注入,因此使用来自 Psycopg2 的 sql 模块。这会生成一个工作查询:
conn = get_db()
cur = conn.cursor()
with open(fp, 'r') as f:
query = sql.SQL("COPY parts ({fields}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)").format(
fields = sql.SQL(',').join(sql.Identifier(col) for col in cols))
cur.copy_expert(query, f)
但是我想知道这是否是正确的解决方案。由于生成的查询是:
print(query.as_string(conn))
>>> COPY parts ("asin","name","t_id","supp_pid","acq_price","deposit","ean","m_pid") FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)
但根据 Postgresql docs 标识符应不带引号。
为什么它仍然有效?
你打错了:
sql.SQL("xxx".format(...))
而不是:
sql.SQL("xxx").format(...)
^ this (
所以:
query = sql.SQL("COPY parts ({fields}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)").format(
fields = sql.SQL(',').join(sql.Identifier(col) for col in cols))
括号没有正确闭合。您在字符串上使用 format
而不是 SQL 对象:
with open(fp, 'r') as f:
_sql = "COPY parts ({}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)"
query = sql.SQL(_sql).format(
sql.SQL(',').join(sql.Identifier(col) for col in cols)
)
print(query.as_string(conn))
cur.copy_expert(query, f)
输出:
COPY parts ("firstname","lastname") FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)
Traceback (most recent call last):
File "pg2.py", line 14, in <module>
cur.copy_expert(query, f)
psycopg2.errors.UndefinedTable: relation "parts" does not exist
注意,关于引用的标识符:
假设你有一个包含空格的列名,然后你需要引用它们才能使用它们。所以允许使用 double 引号,同样的行为适用于 postgres 控制台。
>>> cur.execute("""select firstname, "desc ription" from users2 where lastname = 'bar'""")
>>> print(cur.fetchone())
RealDictRow([('firstname', 'fo'), ('desc ription', 'baz')])
由于 Maurice Meyer 让我知道的语法错误编辑了问题
我需要保护应用程序免受 SQL 注入,因此使用来自 Psycopg2 的 sql 模块。这会生成一个工作查询:
conn = get_db()
cur = conn.cursor()
with open(fp, 'r') as f:
query = sql.SQL("COPY parts ({fields}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)").format(
fields = sql.SQL(',').join(sql.Identifier(col) for col in cols))
cur.copy_expert(query, f)
但是我想知道这是否是正确的解决方案。由于生成的查询是:
print(query.as_string(conn))
>>> COPY parts ("asin","name","t_id","supp_pid","acq_price","deposit","ean","m_pid") FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)
但根据 Postgresql docs 标识符应不带引号。 为什么它仍然有效?
你打错了:
sql.SQL("xxx".format(...))
而不是:
sql.SQL("xxx").format(...)
^ this (
所以:
query = sql.SQL("COPY parts ({fields}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)").format(
fields = sql.SQL(',').join(sql.Identifier(col) for col in cols))
括号没有正确闭合。您在字符串上使用 format
而不是 SQL 对象:
with open(fp, 'r') as f:
_sql = "COPY parts ({}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)"
query = sql.SQL(_sql).format(
sql.SQL(',').join(sql.Identifier(col) for col in cols)
)
print(query.as_string(conn))
cur.copy_expert(query, f)
输出:
COPY parts ("firstname","lastname") FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)
Traceback (most recent call last):
File "pg2.py", line 14, in <module>
cur.copy_expert(query, f)
psycopg2.errors.UndefinedTable: relation "parts" does not exist
注意,关于引用的标识符:
假设你有一个包含空格的列名,然后你需要引用它们才能使用它们。所以允许使用 double 引号,同样的行为适用于 postgres 控制台。
>>> cur.execute("""select firstname, "desc ription" from users2 where lastname = 'bar'""")
>>> print(cur.fetchone())
RealDictRow([('firstname', 'fo'), ('desc ription', 'baz')])