每个数据库提供程序类型允许的最大参数数是多少?

Posted

技术标签:

【中文标题】每个数据库提供程序类型允许的最大参数数是多少?【英文标题】:What are the max number of allowable parameters per database provider type? 【发布时间】:2011-09-28 17:20:30 【问题描述】:

有 2,100 个参数的限制,可以通过 ADO.Net 传递给 Sql Server 查询,但是.Net 开发人员使用的其他常见数据库的记录限制是什么 - 特别是我感兴趣:

Oracle 10g/11g mysql PostgreSql Sqlite

有人知道吗?

【问题讨论】:

【参考方案1】:

甲骨文:64,000。 Source

MySQL:

默认情况下没有限制。 MySQL“文本协议”要求 .NET 客户端库在将命令文本发送到服务器之前替换所有参数;没有可以强制执行的服务器端限制,客户端也没有限制(可用内存除外)。 如果通过调用MySqlCommand.Prepare()(并在连接字符串中指定IgnorePrepare=false)使用“准备好的语句”,则有65,535 个参数的限制(因为num_params 必须适合two bytes)。李>

PostgreSql:编辑:根据 Magnus Hagander 的回答,查询为 34464,函数为 100(答案复制到此处以提供单点参考)

SqlLite:999(SQLITE_MAX_VARIABLE_NUMBER,默认为 999,但可以在运行时降低)- 对于函数,默认值为 100 个参数。 See section 9 Of Run-time limits documentation

【讨论】:

PostgreSQL 的答案是指大约 10 年前的 7.2。最新版本的 PostgreSQL 的正确答案是 100。但这指的是 函数调用 中的参数数量,而不是您可以在客户端界面中绑定的参数数量。不过,我不确定 pg 的 .net 驱动程序限制是什么,而且我周围没有 .net 环境,所以我无法对实际答案发表评论,不幸的是:( 谢谢马格努斯。我已将您的回复添加到答案中。我承认对 PostreSql 知之甚少! Fair enoguh - 我将其更改为 100 而不是 16,因为这就是我的答案。答案仍然对其他数据库的不同问题做出了回应,不过...... 关于sqlite,参数个数限制默认为999;这在sqlite.org/limits.html 中的单个 SQL 语句中的最大主机参数数中进行了说明 我已经使用official ADO.NET connector成功地将100,000个参数添加到MySqlCommand,因此限制大于65,536。请注意,MySqlCommand.Parameters.Add 方法使用 O(n) 算法(从 v6.5.4 开始),因此添加 100,000 个参数确实需要将近两分钟(添加 n 参数是 O(n^2)整体)。【参考方案2】:

当谈到查询的绑定参数时,PostgreSQL 的正确答案似乎是 34464。对于函数的参数数量,响应 100 仍然正确。

【讨论】:

使用 postgresql 9.6.3,我可以毫无问题地使用 65535 个参数进行单次插入。 65536+ 个参数失败。 这个答案太旧了。【参考方案3】:

PostgreSQL 有线协议使用 16 位整数来计算绑定消息 (https://www.postgresql.org/docs/current/protocol-message-formats.html) 中的参数。

因此,PostgreSQL 协议不允许单个语句的参数超过 65535 个。也就是说,发送一个带有两条语句的 ado.net 命令是可以的,每条语句有 65535 个参数。

【讨论】:

当前协议参数在这里:postgresql.org/docs/current/protocol-message-formats.html。相同的限制。【参考方案4】:

在 jOOQ 中,一旦我们达到每个供应商的相关数量,我们通过内联绑定值来解决这些限制。 The numbers are documented here。根据供应商文档,并非所有数字都一定是正确的,我们通过 JDBC 通过反复试验凭经验发现了它们。它们是(没有将它们绑定到特定版本):

入口:1024 微软访问:768 甲骨文:32767 PostgreSQL : 32767 SQLite:999 SQL Server:2100(取决于版本) Sybase ASE:2000

其他数据库似乎没有任何限制 - 至少我们还没有发现它们(虽然没有超过 100000 个)。

【讨论】:

你能详细说明一下内联吗?你到底是什么意思/它是如何工作的? @TimBüthe:通常,jOOQ 生成的 SQL 语句会产生绑定变量,例如SELECT * FROM t WHERE x IN (?, ?, ..., ?)。但是当达到限制时(或客户端代码明确请求),生成的 SQL 将包含“内联”值,例如SELECT * FROM t WHERE x IN (1, 2, ..., 53675) ORA-01795 限制为 1000 怎么样?这似乎与您在这里的号码相矛盾。 @MichaelPiefel:这是一个完全不同的限制,即IN 列表中的元素数量,jOOQ 也通过使用OR 谓词拆分IN 列表来处理。此限制与是否使用绑定变量无关。 对于 IBM DB2 v11,限制为 32767,如产品文档中所提供:ibm.com/docs/en/db2/11.5?topic=sql-xml-limits【参考方案5】:

在我看来,MySQL 问题实际上有两个答案。准备好的语句协议定义了一个带符号的 2 字节短来描述将从服务器检索的参数的数量。客户端首先调用COM_STMT_PREPARE,如果成功则收到COM_STMT_PREPARE response。

响应文档说明:

如果 num_params > 0 个数据包将跟随:

参数定义块

num_params * Protocol::ColumnDefinition

EOF_Packet

鉴于num_params 最多只能是 2^16(有符号短),因此这是参数的限制,并且由于我的公司有一个自定义 MySQL 驱动程序,我们在实现它时选择遵循此规则如果超出限制,则会引发异常。

但是,如果您发送的参数数量超过此数量,COM_STMT_PREPARE 实际上不会返回错误。 num_params 的值实际上只有 2^16,后面还会有更多的参数。我不确定这是否是一个错误,但协议文档没有描述这种行为。

只要您在客户端有办法知道参数的数量(client_num_params,如果您愿意的话),您就可以以期望看到client_num_params x @ 的方式实现您的 MySQL 客户端987654331@。您也可以查看EOF_Packet,但只有在未启用CLIENT_DEPRECATE_EOF 时才会实际发送。

注意到num_params 之后还有一个保留字节也很有趣,这表明协议设计者可能希望将其设为 24 位数字,允许大约 830 万个参数。这还需要一个额外的客户端功能标志。

总结一下:

客户端/服务器协议文档似乎表明参数的最大数量可以是 32768 服务器似乎并不关心您是否发送更多信息,但这似乎没有记录在案,并且在未来的版本中可能不受支持。我非常怀疑这是否会发生,因为这会破坏多个驱动程序,包括 Oracle 自己的 ADO.NET 连接器。

【讨论】:

以上是关于每个数据库提供程序类型允许的最大参数数是多少?的主要内容,如果未能解决你的问题,请参考以下文章

Python 函数中的最大参数数是多少?

使用模板元编程检测函数可以采用的最大参数数

MYSQL各字段的长度是多少

Mysql一个表中 最多能存多少文字? 一列中varchar最大值允许多少?

可以在C ++中使用动态分配的参数数创建函数吗?

Netezza 中可以传递 IN 子句的最大参数