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

Why does my interpolated SQL query have these extra quotation marks?

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

替换 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

好像把bucket_name换成了单引号'expired-test-bucket'

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

我该如何解决这个问题?

参数化查询中的参数不会像字符串插值一样工作,即使您use pyformat binding style that happens to look like old-school %-based string interpolation也是如此。引号在那里是因为数据库引擎希望您使用占位符来表示整个参数,并将引号(以及可能的各种转义形式)放入最终查询文本 设计专门用于防止将用户数据直接插入到查询中而导致的安全漏洞。

如果您需要使用用户数据来构建查询中使用的值,那么请按照单独的步骤执行此操作:首先,使用 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,))