使用 sqlite3 在 django 中出现“太多 SQL 变量”错误

Posted

技术标签:

【中文标题】使用 sqlite3 在 django 中出现“太多 SQL 变量”错误【英文标题】:"Too many SQL variables" error in django with sqlite3 【发布时间】:2011-10-29 16:18:09 【问题描述】:

我在 django 中使用 sqlite3 时遇到此错误:

异常值:SQL 变量太多

我认为答案是这样的,from here:

许多 SQL 程序员都熟悉使用问号(“?”)作为宿主 范围。 SQLite 还支持以“:”、“$”或 “@”和“?123”形式的编号主机参数。

为了防止过多的内存分配,主机参数的最大值 number 是 SQLITE_MAX_VARIABLE_NUMBER,默认为 999。”

但是,还有一个我不明白的奇怪之处,那就是 相同的查询在 django shell 会话中运行良好(使用 python manage.py shell 启动),但在我的 views.py 发出调用时却不行。

这些是导致错误的代码行:

vals = Company.objects.filter(id__in=comp_ids).values('id', 'name').order_by('name')
names_map = SortedDict(vals)

其中comp_ids 是一个包含 1038 个整数元素的集合。

完全相同的查询,但编号更大。 comp_ids (3800+) 在 django shell(使用python manage.py shell 启动) - 字典得到 创建,我可以遍历它。

我尝试将 comp_ids 分解为多个集合,例如[:996](这似乎是 在它吐出之前限制)即filter(id__in=comp_ids[:996]),然后是其余的 下一次迭代,这将与“主机参数数量”一致 解释。

但为什么它可以在 django shell 中工作,但不能在 views.py 中工作?

编辑:更多信息: 将查询输入到 sqlite shell (manage.py dbshel​​l) 会返回完整的 一组没有错误的结果,与 django shell (manage.py shell) 中的相同。

以下是参数(1039 个元素)和查询的确切列表,如果您愿意的话 想了解详情:

参数

(2, 3, 4, 2053, 6, 7, 2732, 10, 3737, 13, 2063, 2064, 17, 18, 21, 2393, 2052, 29, 30, 32, 2456, 35, 36, 38, 40 , 2396, 42, 2731, 45, 46, 2095, 3343, 49, 2098, 2252, 53, 54, 58, 59, 2058, 62, 63, 64, 66, 67, 72, 2123, 3426, 3344, 79 , 80, 81, 85, 2134, 87, 91, 92, 95, 98, 2747, 2149, 102, 104, 106, 2155, 109, 110, 3773, 2455, 2165, 118, 122, 2171, 2172, 17 , 134, 135, 137, 138, 2187, 2413, 145, 148, 2414, 2198, 2199, 152, 153, 154, 2204, 157, 2210, 163, 2417, 169, 170, 13,219, 7923, , 2077, 179, 180, 181, 2230, 2231, 184, 186, 187, 2237, 190, 191, 2240, 2241, 3787, 2245, 2246, 2247, 2248, 2249, 25,251, 204, 204, 20 , 209, 210, 213, 214, 2263, 2265, 3450, 222, 2273, 2274, 2275, 228, 2277, 2811, 231, 234, 2283, 2284, 238, 240, 243, 248, 2050, , 254, 2303, 2305, 258, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 267, 269, 2318, 271, 2320, 2321, 2322, 2323, 2325, 28, 28, 232 , 285, 286, 287, 290, 2342, 295, 298, 2347, 2348, 2349, 2350, 2351, 304, 2353, 307, 309, 312, 318, 320, 321, 323, 326, 327, 328, 332, 333, 334, 2385, 338, 2387, 2388, 2389, 2390, 2391, 2392, 345, 2394, 347, 348, 350, 32, 355, 356, 357, 359, 360, 2410, 364, 365, 366, 2415, 2416, 369, 2451, 373, 2422, 375, 377, 2426, 2428, 2429, 2430, 24732, 24,32, 24,32, 391, 2441, 2443, 398, 399, 400, 401, 2553, 403, 404, 405, 406, 407, 408, 409, 410, 411, 413, 2462, 3628, 418, 2459, 4020, 2469, 2472, 425, 427, 2476, 2461, 2483, 2485, 440, 441, 2490, 443, 444, 445, 446, 2496, 2497, 2499, 2501, 2502, 455, 2504, 4605, 46, 46, 45, 2510、463、465、466、467、469、470、2519、2520、2468、474、2529、2531、484、486、487、488、490、491、493、2542、2543、2544、49 499、500、2549、502、2551、504、505、2554、2555、2556、509、2558、511、2560、2562、2475、2564、517、2566、2567、2568、2569、2568、2569、2568、2569、257 527, 529, 536, 538, 539, 2588, 2589, 2590, 2596, 550, 552, 556, 2605, 2607, 2608, 2612, 565, 566, 567, 568, 580, 2634, 588, 26 2639、2270、595、598、2489、605、606、609、610、 2407, 615, 618, 619, 620, 2669, 2670, 2493, 2672, 2152, 628, 629, 630, 2680, 2682, 2684, 640, 641, 642, 2691, 645, 69,7, 60,0,2 2701、2702、2703、2705、659、2708、661、2712、667、2718、2719、2720、2721、2723、2724、2725、2728、681、2730、2614、26、935、2733、 2739, 2741, 2746, 699, 701, 706, 707, 2757, 2759, 2760, 2508, 2763, 2766, 721, 2771, 725, 730, 2511, 732, 2170, 734, 2343, 734, 2343, 98, 74, 2799, 752, 753, 2515, 756, 2078, 2807, 2808, 2412, 763, 2813, 766, 769, 2818, 2821, 2822, 779, 2861, 2833, 2834, 28,7, 280,36, 28,7,7, 2 2852, 2854, 2856, 2550, 810, 2860, 813, 2862, 2863, 817, 2869, 2870, 2871, 824, 826, 2876, 829, 830, 2882, 836, 28785, 2886, 28785, 2886, 2986, 3 2893, 847, 2896, 2872, 2899, 2902, 2546, 2909, 2256, 2912, 2913, 870, 2920, 2921, 2922, 876, 2930, 887, 2937, 3903, 892, 85,93, 892, 85,93, 86 897, 898, 899, 900, 901, 903, 904, 905, 906, 907, 908, 909, 910, 911, 2884, 2970, 927, 2977, 2978, 2979, 2980, 2981, 2545, 942, 2205、948、949、950、9 51, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 3014, 967, 968, 969, 970, 971, 3234, 2552, 980, 981, 982, 983, 985, 2895, 3038, 995, 996, 998, 2897, 2538, 2761, 3051, 1012, 1013, 3062, 3063, 3066, 2559, 3073, 1027, 103,028, 14229, 3 1036,1038,1039,1040,1041,3092,3246,3853,111112,1067,3109,3112,1067,1068,1073,1074,1075,1076,1078,1081,2076,1086,1081,2091,1086,2229,1088, 1089,1090,1091,1092,1093,1095,1099,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,3161,1119, 3170,2235,3174,3176,3177,1132,1133,1134,1135,1136,3186,1141,3192,3193,3194,3195,3197,3198,2425,1152,1155,1156,3205,2924,3214, 1168,1169,1171,1172,1176,1174,1175,1176,3225,1178,3230,1186,1189,1193,1194,1195,1196,3245,1198,1199,1200,1202,2541,3273,1210, 3259、1213、1225、1226、1228、1230、2253、3280、3281、1234、1235、1238、1243、1244、1248、1249、3298、3299、1253、3302、2257、 4, 3305, 3306, 3308, 1262, 2838, 3315, 3317, 3381, 1277, 1278, 3327, 3331, 3332, 1285, 2945, 1288, 1289, 1292, 1295, 348, 1296, 3348, 3496, 3349 1302,3351,3352,3353,1306,1307,3356,1312,3364,1320,3370,3371,3372,3374,3375,1328,3377,3378,3380,1333,1334,3388,3390,3296,3394, 3395,2227,1350,2615,1357,1361,1362,3111,31,3413,1368,2276,1371,1372,3105,1378,2228,31105,1378,2228,3428,3030,3233,1400,1402,1404,3453,3455, 3808,1409,3458,3459,1412,1414,1416,1417,1470,1419,1486,1437,3437,3486,1439,2571,3491,3492,3493,1446,2435,1454,1463,3663, 3523,1477,1478,1479,1480,1481,1482,3489,1490,3488,1489,1490,3540,1494,1495,1496,3546,3547,2298,1510,1512,3666,1520,1523,2302, 1526,1527,3584,1539,1540,1549,3193,1548,1549,3393,1554,1555,1560,1561,3079,1565,2507,3616,3617,1570,3616,3617,1570,3619,3620,3621,3622,1575, 3624、2817、3629、3630、1583、1590、1591、1592、2996、3643、3645、2997、3649、2781、3653、3655、1608、3 657,2317,1618,3667,1620,3669,1625,2319,3002,2782,1633,1634,3199,3691,3346,3179,3650,1656,3007,3709,3008,1666,2616,3009,2668, 2306,3723,3010,2238,1681,1682,1683,1687,3012,3738,2671,1693,3013,1697,1698,2548,3749,3755,3757,3758,333,1714,1718,3770,3018, 1729,3778,3783,1739,1744,3793,1746,1752,1753,1755,3741,3707,1771,1774,2514,1779,2494,3831,1788,2346,3831,1788,2346,3029,3840,3182,2689,1802, 1803,2690,1811,1815,1817,3011,2352,1827,2467,1832,3881,1839,1840,2107,1848,1855,1857,1853,1855,1857,1864,1855,1857,1864,1867,1872,1873,3923, 1878年,1882年,1889,3889,1903,1903,1904,904,2366,1915,1920,1921,1927,1928,1930,1931,3133,1943,1947,1957,1958,1947,1957,1958,1959,1964,1967,1969,1964,1967,1968,1964,1967,1968,1976,2809, 3612, 1987, 1988, 1989, 3745, 1994, 2000, 2003, 2382, 2008, 3613, 2021, 2022, 3410, 3464, 2033, 2034, 2037, 2038, 2729, 2044)

查询

'SELECT "screen_company"."id", "screen_company"."name" FROM "screen_company" WHERE "screen_company"."id" IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ORDER BY "screen_company"."name" ASC'

(顺便说一句,你不需要为此使用 pdb - django 非常有帮助 发生错误时在浏览器中显示回溯(在 render_to_response()? 中),并带有 每一步的局部变量的完整列表,所以你可以看到完整的查询 在那里。)

然而,我之前曾尝试使用 pdb 进入 django 代码,并且 发现错误实际上来自python的 pysqlite2.dbapi2 (或 sqlite3.dbapi2) 模块,在 django/db/backends/sqlite3/base.py 的第 200 行:

return Database.Cursor.execute(self, query, params)

(这也在错误页面中显示的有用回溯中),其中 数据库是 pysqlite2.dbapi2 或 sqlite3.dbapi2 的别名,具体取决于 在你的 python 版本上。

但我认为调用堆栈太远了,无法继续调试(目前), 所以决定停下来,开始考虑解决方法并在谷歌上搜索 而是回答。 :)

【问题讨论】:

Django shell 是否足够聪明,可以知道限制并自动为您分解查询? 分解查询会产生竞争条件。最好创建一个包含一列的临时表并填充它。然后查询是 SELECT ... WHERE column in (SELECT * FROM temptable)。 发生这种情况的另一个原因是在大型查询集上执行 prefetch_related。 @dbw 你能告诉我如何解决这个问题。因为我用的是sqlite。但我想执行只读操作。 【参考方案1】:

实际上这些限制在这里给出: https://www.sqlite.org/c3ref/c_limit_attached.html#sqlitelimitvariablenumber

附上解释:

单个 SQL 语句中的最大主机参数个数

主机参数是填充的 SQL 语句中的占位符 在使用 sqlite3_bind_XXXX() 接口之一。许多 SQL 程序员熟悉使用问号(“?”)作为主机 范围。 SQLite 还支持以“:”开头的命名主机参数, “$”或“@”以及“?123”形式的编号主机参数。

SQLite 语句中的每个主机参数都分配有一个编号。这 数字通常以 1 开头,每个新数字加一 范围。但是,当使用“?123”形式时,主机参数 number 是问号后面的数字。

SQLite 分配空间来保存 1 到 使用的最大主机参数号。因此,一条 SQL 语句 包含像 ?1000000000 这样的主机参数需要千兆字节 贮存。这很容易使主机的资源不堪重负 机器。为了防止过多的内存分配,最大值 主机参数编号为 SQLITE_MAX_VARIABLE_NUMBER,默认为 到 999。

最大主机参数数可以在运行时使用 sqlite3_limit(db,SQLITE_LIMIT_VARIABLE_NUMBER,size) 接口。

https://www.sqlite.org/limits.html

【讨论】:

你的意思是如果你有1000000000个参数?那将是一个高得离谱的数字。但是,达到 10000 之类的值可能并不过分。 在执行查询之前它不会“内联”它们而不是将它们作为 1k+ 参数传递,是否有原因?我不明白为什么上面的查询不是简单的... IN (1, 2, 3, 42, ...) 而不是... IN (?, ?, ? ...) @DanM。数字没问题,但如果你有字符串,你想参数化它们以防止注入。【参考方案2】:

谷歌搜索这条错误消息把我带到这里,所以添加我的解决方案。

在我的情况下,这个错误是由以下行引起的:

Event.objects.all().delete()

可能 Django 试图“删除其中的 id (?,?,?,...”并且 id 列表太长了。

性能对我来说不是问题,所以我通过以下方式解决了这个问题:

while Event.objects.count():
    ids = Event.objects.values_list('pk', flat=True)[:100]
    Event.objects.filter(pk__in = ids).delete()

【讨论】:

太棒了!为了获得更好的性能,您不必一次将自己限制为 100 个项目;我将它设置为 500,但你很可能。可以将其增加到接近 999 左右(上面引用的 SQLITE_MAX_VARIABLE_NUMBER 默认为 999)。【参考方案3】:

没有办法绕过这个,这是一个 SQLITE 限制。但是,您的查询将在 mysql 上运行良好。但是如果你必须做这种查询,你很可能做错了。您的 mysql 架构应该重做。如果不能,那么您可能希望将此查询分解为 100 个小查询。

【讨论】:

【参考方案4】:

我在运行该行时发现了同样的错误:

    Entry.objects.all().delete()

我解决了这个问题

    while Entry.objects.count():
          Entry.objects.all()[0].delete()

我认为这是一个比其他人更好的主意。

【讨论】:

这不如@fsw 的答案高效,后者按查询组分类。【参考方案5】:

注意:我不是 Django 专家

问题是在您的查询中

vals = Company.objects.filter(id__in=comp_ids)... 

您传递了一组臃肿的值,而底层引擎无法执行查询。 幸运的是,您在该行中执行的 sqlalchemy 是 lazy。您可以执行 SELECT,然后“手动”过滤条目,而不会造成很大的性能损失。

它看起来更像这样:

# here you should do a proper session.query(CompanyTable)
vals_all = Company.objects

vals_filtered = (item for item in vals_all if item.id in comp_ids)
vals_ordered = sorted(vals_filtered, key=attrgetter('name'))
vals_final = [(v.id, v.name) for v in vals_ordered]

【讨论】:

【参考方案6】:

我遇到了类似的问题,但是在删除另一个表中包含大量相关行的单行时。 Django 调用了导致问题的级联删除,但由于我的代码仅调用单个对象删除,因此无法应用其他答案中描述的解决方案(除非我修改了 Django 库代码,我不想这样做) .

我的解决方案是首先通过原始 sql 查询删除相关对象,然后在父对象上使用普通的 Django delete(),全部包装在事务中。

之前:

object.delete() # Django tries to delete a large number of related object and fails

之后:

from django.db import connection

Class MyObject:
    def delete_related(self):
        cur = connection.cursor()
        sql = 'delete from my_table where ...'
        cur.execute(sql, params)

...

with transaction.atomic():
    object.delete_related() # so that Django won't try (and fail) on its own
    object.delete()

【讨论】:

以上是关于使用 sqlite3 在 django 中出现“太多 SQL 变量”错误的主要内容,如果未能解决你的问题,请参考以下文章

3. 在Django 2.2中启动开发服务器时处理SQLite3错误

Django shift to PostgreSQL 无法导入fixture,说明数据太长

django:sqlite3.OperationalError:没有这样的表

在 Django 1.9.2 数据库 sqlite3 中插入​​列表

Django / sqlite3“OperationalError:没有这样的表”关于线程操作

Django:使用 sqlite3 作为数据库在 Heroku 上部署应用程序