为什么我的插值SQL查询有这些额外的引号



我设置了如下查询。我想用变量替换bucket_namefile_name

此查询由psycopg2执行

query = '''copy table.test
from 's3://%(bucket_name)s/%(file_name)s.txt'
iam_role 'arn:aws:iam::123453215125:role/test'
timeformat as 'auto'
ACCEPTINVCHARS 
delimiter 't';'''

我得到桶名和文件名

bucket_name = get_bucket_name(event)
file_name = get_file_name(event)

之后,我执行了查询,但它返回错误

cur.execute(query, {'bucket_name':bucket_name,'file_name':file_name})
[ERROR] SyntaxError: syntax error at or near "expired" LINE 2: from 's3://'expired-test-bucket... ^ Traceback (most recent cal

似乎用单引号'expired-test-bucket'代替了bucket_name

我想要的结果是expired-test-bucket

我该怎么解决这个问题?

参数化查询中的参数的工作方式与字符串插值不同,即使您使用的pyformat绑定样式恰好看起来像老式的基于%的字符串插值。之所以有引号,是因为数据库引擎希望您使用占位符来表示整个参数,并通过设计将引号(以及可能的各种形式的转义(放入最终查询文本,特别是为了防止由于将用户数据直接插入查询而导致的安全漏洞。

如果您需要使用用户数据来构建查询中使用的值,那么只需按单独的步骤执行即可:首先,使用Python字符串格式来创建原始基础值,然后使用SQL引擎的功能来确保将该值安全地放入查询中。

所以,类似于:

bucket_name = get_bucket_name(event)
file_name = get_file_name(event)
url = f's3://{bucket_name}/{file_name}.txt'
query = '''copy table.test
from %s
iam_role 'arn:aws:iam::123453215125:role/test'
timeformat as 'auto'
ACCEPTINVCHARS 
delimiter 't';'''
cur.execute(query, (url,))

最新更新