【问题标题】:Escaping quotes in Redshift query在 Redshift 查询中转义引号
【发布时间】:2014-12-24 09:42:17
【问题描述】:


我正在尝试将我的代码重构为 PEP8 标准以提高可读性,但我正在努力在我的 SQL 查询中转义引号。 我有 2 个查询。第一个是简单的 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 命令中,所以我只能通过在引号前面加上 3 个反斜杠来转义引号来使其工作:'day' 变为 ///'day///'。
这并不理想,我想知道是否有办法解决它。

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

【问题讨论】:

    标签: python mysql amazon-redshift


    【解决方案1】:

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

    要获得更强大的解决方案,您可以利用美元报价。 Redshift 文档在“美元引用的字符串常量”部分中指向this page。您可以使用美元符号来引用您的查询,而不是手动转义引号:

    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, ...)
    

    【讨论】:

    • 你知道如果查询中有反斜杠会发生什么吗?也需要逃避它们?
    • 如果你使用美元报价,我不知道。
    【解决方案2】:

    由于您只需要在 unload 命令中的引号前插入反斜杠,因此使用转义函数可以工作。这是一个例子。

    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)
    

    【讨论】:

    • 这绝对是一个优雅的解决方案。但是我想知道是否有一种方法可以利用 psycopg2 的功能,它已经执行了 sql 查询的转义,以避免添加额外的代码。
    • 这不考虑已经转义的引号。此代码将通过转义反斜杠有效地取消转义。阅读 Friedl 的 Mastering Regular Expressions 了解标准正则表达式以匹配和转义引用的字符串,同时考虑嵌入的转义字符。
    猜你喜欢
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 2017-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多