每个数据库提供程序类型允许的最大参数数是多少?
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 连接器。【讨论】:
以上是关于每个数据库提供程序类型允许的最大参数数是多少?的主要内容,如果未能解决你的问题,请参考以下文章