将表名作为参数传递给psycopg2

9 浏览
0 Comments

将表名作为参数传递给psycopg2

我有以下的代码,使用pscyopg2库:

sql = 'select %s from %s where utctime > %s and utctime < %s order by utctime asc;'
data = (dataItems, voyage, dateRangeLower, dateRangeUpper)
rows = cur.mogrify(sql, data)

这个输出结果是:

select 'waterTemp, airTemp, utctime' from 'ss2012_t02' where utctime > '2012-05-03T17:01:35+00:00'::timestamptz and utctime < '2012-05-01T17:01:35+00:00'::timestamptz order by utctime asc;

当我执行这个代码时,它会出错 - 这是可以理解的,因为表名周围的引号是非法的。

有没有办法合法地将表名作为参数传递,或者我需要进行(明确警告的)字符串连接,比如:

voyage = 'ss2012_t02'
sql = 'select %s from ' + voyage + ' where utctime > %s and utctime < %s order by utctime asc;'

感谢任何见解。

0
0 Comments

问题的出现的原因是在使用psycopg2进行动态生成SQL查询时,需要动态选择表名。之前的解决方法是使用AsIs(一个用于表示字符串的对象)来表示表名,但是AsIs不应该被用来表示表名或字段名。

解决方法是使用psycopg2中的新模块sql来动态生成SQL查询。新的解决方法如下:

from psycopg2 import sql
cur.execute(
    sql.SQL("insert into {table} values (%s, %s)")
        .format(table=sql.Identifier('my_table')),
    [10, 20])

这里的sql.Identifier('my_table')表示表名,通过.format()方法将表名动态地插入到SQL查询中。

psycopg2文档还提到,绝对不能使用Python字符串的拼接或者插值的方式将变量传递给SQL查询字符串,这是非常不安全的。

确保.format()方法调用在sql.SQL对象上而不是内部字符串上。例如,SQL('select * from {}'.format(...))是不起作用的,而SQL('select * from {}').format(...)是正确的用法。

0
0 Comments

问题的出现原因是因为在psycopg2中无法将表名作为参数传递,但其他所有内容都可以。因此,表名应该在应用程序中硬编码(不要从程序外部输入或使用任何内容作为表名)。你的代码应该可以解决这个问题。

如果你有一个合理的理由来获取外部的表名,确保不允许用户直接输入。可以通过传递索引来选择表,或者通过其他方式查找表名。然而,你对此持谨慎态度是正确的。这种方法是可行的,因为表名的数量相对较少。找到一种验证表名的方法,你应该就没问题了。

可以像下面这样做,来检查表名是否存在。这是一个带参数的版本。只需确保在运行SQL代码之前执行此操作并验证输出。这个方法的部分想法来自于这个答案

SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' and table_name=%s LIMIT 1

是的,表名确实需要从外部传入,没有什么办法可以避免这个问题。不过,我有一个'有效'(即安全)表的列表,因此可以对传入的参数进行检查,以确保其可接受,以防止注入。

实际上,考虑一下,这将是一个相当简单的SQL查询。我已经发布了这样一个查询,你可以根据需要将其转换为适合你的适配器的形式。

"The table name cannot be passed as a parameter" - 这是不正确的。你可以使用.format将其作为字符串传入。

关键是使用.format容易受到SQL注入攻击,而使用mogrify的真正参数则不会。

stackoverflow.com/a/42947632/1888503 下面的答案是正确的。

是的,当然,我同意。然而,它仍然是可能的。更好的说法应该是:“虽然可以将表名作为参数传入,但由于可能存在SQL注入的可能性,不建议这样做”。

0
0 Comments

使用psycopg2将表名作为参数传递的原因是为了避免SQL注入攻击。通过将表名作为参数传递给execute()函数,可以确保表名不会被当作SQL语句的一部分进行解析,从而防止恶意用户利用输入的表名执行任意的SQL代码。

上述代码中,使用AsIs类将表名作为参数传递给execute()函数。AsIs类将参数原样传递给SQL语句,而不对其进行任何解析或转义。这样可以确保表名不会被当作SQL语句的一部分进行解析。

然而,使用AsIs类会破坏参数化查询的目的。参数化查询的目的是将用户输入作为参数传递给SQL语句,以防止SQL注入攻击。因此,在处理用户输入的表名时,不应该使用AsIs类。

总结起来,要在psycopg2中将表名作为参数传递,应该使用参数化查询的方式,并避免使用AsIs类。这样可以确保安全地执行SQL语句,并防止SQL注入攻击。

文章的中文输出如下:

根据这个回答,你可以这样做:

import psycopg2
from psycopg2.extensions import AsIs
#创建连接和游标...
cursor.execute("SELECT * FROM %(table)s", {"table": AsIs("my_awesome_table")})

应该是cursor.execute("SELECT * FROM %(table)s", {"table": AsIs("my_awesome_table")}),但无法编辑,因为只有2个字符 🙂

不幸的是,AsIs破坏了参数化查询的目的。不要将用户数据与之一起使用。

AsIs不应该用于这个目的:stackoverflow.com/a/42980069/5285608

0