【问题标题】:SQL error when using format() function with pyodbc in Django在 Django 中将 format() 函数与 pyodbc 一起使用时出现 SQL 错误
【发布时间】:2021-05-28 13:50:23
【问题描述】:

我想在我的 Django 应用程序中使用 pyodbc 执行命令。当我对一列进行简单更新时,效果很好:

cursor.execute("UPDATE dbo.Table SET attr = 1 WHERE id = {}".format(id))

但是,当我尝试将字符串用作列值时,它会引发错误:

cursor.execute("UPDATE dbo.Table SET attr = 1, user = '{}' WHERE id = {}".format(id, str(request.user.username)))

这里是错误信息:

('42S22', "[42S22] [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'Admin'. (207) (SQLExecDirectW)")

令人惊讶的是,这种方法有效:

cursor.execute("UPDATE dbo.Table SET attr = 1, user = 'Admin' WHERE id = {}".format(id))

似乎是什么问题?为什么 sql 将列值误认为其名称?

【问题讨论】:

  • 非常不鼓励您在 django 应用程序中使用像这样的原始 SQL,您很容易受到 sql 注入的影响,不良行为者可能会截断并删除您的整个数据库,或者更糟的是在您不知情的情况下访问您的系统。至少你应该清理你的输入。你为什么不使用 ORM ?
  • @Umar.H 我正在使用 ORM。我使用的原始 SQL 是必要的,因为属于不同系统的数据库为我的一个表提供更新。每次使用按钮时我都需要检查一些东西并更新这个远程数据库。另外-没有人弄乱我的数据的危险,这个网站只能在我的网络内运行,我会在本地托管。

标签: sql django pyodbc


【解决方案1】:

如上所述,您的参数倒置,但如果您要使用cursor.execute(),更重要的是使用位置参数 (%s)。这会将 SQL 和值分别传递给数据库后端,并保护您免受 SQL 注入:

from django.db import connection

cursor = connection.cursor()

cursor.execute("""
    UPDATE dbo.Table
    SET attr = 1,
        user = %s
    WHERE id = %s
""", [
    request.user.username,
    id,
])

【讨论】:

  • 不应该 %s 占位符是 ? ...?
  • @GordThompson 当使用pyodbc 光标时,这是真的。但是,通过 Django 使用它时,占位符是 %s 在使用 Django 游标时。然后每个数据库引擎将%s 替换为底层驱动程序的占位符:github.com/michiya/django-pyodbc-azure/blob/…
【解决方案2】:

你的格式参数倒过来了。您将 id 传递给用户,并将用户名传递给 id WHERE 子句。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-02
    • 2021-06-15
    • 1970-01-01
    • 2022-06-17
    • 2015-05-21
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    相关资源
    最近更新 更多