You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+ODBC Driver 17 for SQL Server原生查询无法处理列表参数求助

代码

我封装了一个处理Django原生SQL查询标准流程的函数:

def run_mssql_query(query, connection="prod", args=None):
    
    """Method will run query on MSSQL database

    Args:
            query (str): MSSQL Query
            connection (str): Which connection to use. Defaults to "prod".

    Returns:
            dict: Results of query
    """
    if connection == "omron":
        results = {}

        conn = get_oracle_connection()

        with conn.cursor() as cursor:
            try:
                if args == None:
                    args = dict()
                    
                cursor.execute(query, args)
                cursor.rowfactory = lambda *args: dict(zip([d[0] for d in cursor.description], args))
                results = cursor.fetchall()
            except:
                results = {}

        return results

    with connections[connection].cursor() as cursor:
        if args == None:
            args = list()
        
        cursor.execute(query, args)  # Replace with your actual query

        try:
            columns = [col[0] for col in cursor.description]
            results = [dict(zip(columns, row)) for row in cursor.fetchall()]
        except:
            results = {}

    return results

执行示例:

data = run_mssql_query(f"""SELECT *
                           FROM EVENTS.dbo.MES_BARCODES
                           WHERE BARCODE = %s""", args=["123"])
问题

单个参数(字符串、整数等)传入时函数运行正常,但尝试传入列表作为IN条件参数时出错:

barcodes = ["123", "321"]
data = run_mssql_query(f"""SELECT *
                           FROM EVENTS.dbo.MES_BARCODES
                           WHERE BARCODE IN %s""", args=[list(barcodes)])

错误信息:

('42000', '[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Column, parameter, or variable #1: Cannot find data type 321.123. (2715) (SQLExecDirectW)')

错误栈信息:

File "C:\python-projects\fas-mes\fasmes\APP__LogsDashboard\decorators.py", line 32, in wrapper
    response = func(*args, **kwargs)
  File "C:\python-projects\fas-mes\fasmes\APP__Constructors\views.py", line 74, in get_duplicated_barcodes
    data = run_mssql_query(f"""SELECT *
  File "C:\python-projects\fas-mes\fasmes\API__Database\views_functions.py", line 90, in run_mssql_query
    cursor.execute(query, args)  # Replace with your actual query
  File "C:\python-projects\fas-mes\venv\lib\site-packages\django\db\backends\utils.py", line 102, in execute
    return super().execute(sql, params)
  File "C:\python-projects\fas-mes\venv\lib\site-packages\django\db\backends\utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "C:\python-projects\fas-mes\venv\lib\site-packages\django\db\backends\utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\python-projects\fas-mes\venv\lib\site-packages\django\db\backends\utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "C:\python-projects\fas-mes\venv\lib\site-packages\django\db\utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\python-projects\fas-mes\venv\lib\site-packages\django\db\backends\utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "C:\python-projects\fas-mes\venv\lib\site-packages\mssql\base.py", line 677, in execute
    return self.cursor.execute(sql, params)
项目依赖(pip freeze)
asgiref==3.8.1
backports.zoneinfo==0.2.1
certifi==2024.7.4
cffi==1.17.1
charset-normalizer==3.3.2
cryptography==43.0.1
cx-Oracle==8.3.0
Django==4.2.15
django-appconf==1.0.6
django-compressor==4.5.1
django-cors-headers==4.4.0
django-extensions==3.2.3
django-mssql==1.8
django-mssql-backend==2.8.1
django-sass-processor==1.4.1
django-xff==1.4.0
djangorestframework==3.15.2
idna==3.7
libsass==0.23.0
MarkupSafe==2.1.5
mssql-django==1.5
oracledb==2.4.1
packaging==24.1
pillow==10.4.0
pycparser==2.22
pyodbc==5.1.0
pyOpenSSL==24.2.1
python-ipware==3.0.0
pytz==2024.1
rcssmin==1.1.2
requests==2.32.3
rjsmin==1.2.2
sqlparse==0.5.1
typing-extensions==4.12.2
tzdata==2024.1
urllib3==2.2.2
werkzeug==3.0.4
已尝试的解决方法
  • 在查询中添加ANY():
data = run_mssql_query(f"""SELECT *
                           FROM EVENTS.dbo.MES_BARCODES
                           WHERE BARCODE IN ANY(%s)""", args=[list(barcodes)])

无效果。

  • 查看Django实际执行的SQL并手动执行:
    查看SQL的代码:
print("Executed queries:" )
for i, query in enumerate(connections[connection].queries):
    print(f'----------------- {i} -------------------')
    print(query["sql"])
    print(f'-----------------------------------------')

输出结果:

Executed queries:
----------------- 0 -------------------
SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)
-----------------------------------------
----------------- 1 -------------------
SELECT SYSDATETIME()
-----------------------------------------
----------------- 2 -------------------
SELECT *
FROM EVENTS.dbo.MES_BARCODES
WHERE BARCODE IN ['123', '321']
-----------------------------------------

生成的SQL看起来完全正常,但推测底层存在额外的查询转换。

现状

查阅大量StackOverflow文章和官方文档后,仍无法实现包含列表/元组参数的查询正常运行。
注:为避免SQL注入风险,不能使用f-string或string.format拼接SQL。


内容的提问来源于stack exchange,提问作者yma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:24:56