在Redshift查询中转义引号

5 投票
2 回答
12972 浏览
提问于 2025-04-30 05:59


我正在尝试把我的代码改成PEP8标准,以提高可读性,但在处理SQL查询中的引号时遇到了困难。
我有两个查询。第一个是简单的SQL查询,第二个是Redshift的UNLOAD命令。

query = '''SELECT * FROM redshift_table
           LEFT JOIN
           (SELECT DISTINCT * FROM redshift_view) v
           ON redshift_table.account_number = v.card_no
           WHERE timestamp < date_trunc('day', CURRENT_DATE)
           AND timestamp >=  (CURRENT_DATE - INTERVAL '1 days')'''

unload = '''UNLOAD ('%s') to '%s'
            credentials 'aws_access_key_id=%s;aws_secret_access_key=%s'
            delimiter as '%s'parallel off ALLOWOVERWRITE''' % (query, s3_path, access_key, aws_secret, file_delimiter)

因为SQL查询嵌套在UNLOAD命令里面,所以我只能通过在引号前加三个反斜杠来让它工作:'day'变成///'day///'。
这样并不是最理想的,我在想有没有其他解决办法。

非常感谢任何帮助。谢谢。

暂无标签

2 个回答

2

Masashi的回答并不总是有效,比如当查询中已经有转义字符串时(比如在正则表达式中)。

为了找到一个更可靠的解决办法,你可以利用美元引号。Redshift的文档提到在“美元引号字符串常量”这一部分可以找到相关信息。你可以用美元符号来引号你的查询,这样就不需要手动转义引号了:

unload = """UNLOAD ($$ %s $$) ...as""" % (query, ...)

不过,如果你在查询中使用了$$,这个方法也会失效。如果你想更安全一点,可以在美元符号里面使用一个随机的标签:

import uuid

# Leading underscore is necessary since this needs to be a valid
# identifier, i.e. can only start with a letter or underscore.
quote_tag = '_' + uuid.uuid4().hex

unload = 'UNLOAD ($%s$ %s $%s$) ...'.format(quote_tag, query, quote_tag, ...)
0

因为你只需要在卸载命令里面的引号前面加反斜杠,所以使用一个转义函数就可以了。下面是一个例子。

def escape_quote(value):
  return value.replace("'", "\\'")

query = '''SELECT * FROM redshift_table
           LEFT JOIN
           (SELECT DISTINCT * FROM redshift_view) v
           ON redshift_table.account_number = v.card_no
           WHERE timestamp < date_trunc('day', CURRENT_DATE)
           AND timestamp >=  (CURRENT_DATE - INTERVAL '1 days')'''

unload = '''UNLOAD ('%s') to '%s'
            credentials 'aws_access_key_id=%s;aws_secret_access_key=%s'
            delimiter as '%s'parallel off ALLOWOVERWRITE''' % (escape_quote(query), s3_path, access_key, aws_secret, file_delimiter)

撰写回答