为什么查询中的 Snowflake 变量绑定会抛出表名错误而不是整数错误?

Ezr*_*ron 3 sql-injection string-interpolation snowflake-cloud-data-platform

我正在遵循Snowflake Python Connector文档进行变量绑定以避免 SQL 注入。我成功地使用以下凭据字典建立了数据库连接:

import snowflake.connector

CONN = snowflake.connector.connect(
    user=snowflake_creds['user'],
    password=snowflake_creds['password'],
    account=snowflake_creds['account'],
    warehouse=snowflake_creds["warehouse"],
    database=snowflake_creds['database'],
    schema=snowflake_creds['schema'],
)
cur = CONN.cursor(snowflake.connector.DictCursor)
Run Code Online (Sandbox Code Playgroud)

以下块工作正常,我返回查询结果,对表名称进行硬编码并使用标准format绑定:

command = ("SELECT * FROM TEST_INPUT_TABLE WHERE batch_id = %s")
bind_params = (2)
results = cur.execute(command % bind_params).fetchall()
Run Code Online (Sandbox Code Playgroud)

类似地,使用绑定,该块可以正常工作pyformat

command = ("SELECT * FROM TEST_INPUT_TABLE WHERE batch_id = %(id)s")
bind_params = {"id": 2}
results = cur.execute(command, bind_params).fetchall()
Run Code Online (Sandbox Code Playgroud)

但以下两个块都会产生 a ProgrammingError(粘贴在第二个块下面):

command = ("SELECT * FROM %s WHERE batch_id = %s")
bind_params = ("TEST_INPUT_TABLE", 2)
results = cur.execute(command, bind_params).fetchall()


command = ("SELECT * FROM %(tablename)s WHERE batch_id = %(id)s")
bind_params = {
    "tablename": "TEST_INPUT_TABLE",
    "id": 2
    }
results = cur.execute(command, bind_params).fetchall()


    ProgrammingError: 001011 (42601): SQL compilation error:
    invalid URL prefix found in: 'TEST_INPUT_TABLE'
Run Code Online (Sandbox Code Playgroud)

字符串和整数的插值方式有什么区别吗?我不认为这会有所作为,但这就是我能想到的。我在这里缺少一些简单的东西吗?我不想在硬编码表名和让系统面临 SQL 注入风险之间做出选择。感谢您的任何指导。

Mik*_*ton 5

当绑定变量引用对象时,您应该用INDENTIFER()函数包装它们,而不是字符串文字。例如:

command = ("SELECT * FROM IDENTIFIER(%(tablename)s) WHERE batch_id = %(id)s")
Run Code Online (Sandbox Code Playgroud)

https://docs.snowflake.com/en/sql-reference/identifier-literal.html

尝试一下。