每种数据库提供程序允许的最大参数数量是多少?

31

针对通过ADO.Net传递给Sql Server查询的参数,有一个2100个参数的限制。但其他常用的数据库(特别是我感兴趣的Oracle 10g/11g、MySQL、PostgreSQL和SQLite)的文档限制是什么呢?

  • Oracle 10g/11g
  • MySql
  • PostgreSql
  • Sqlite

有人知道吗?

5个回答

30

Oracle: 64,000. 来源

MySQL:

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

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

SqlLite:999(SQLITE_MAX_VARIABLE_NUMBER,默认为999,但可以在运行时降低)- 对于函数,默认参数为100。 请参阅运行时限制文档的第9部分


PostgreSQL的答案指的是7.2版本,这个版本大约是10年前的。最近版本的PostgreSQL的正确答案是100。但是这个数字指的是函数调用中的参数数量,而不是你可以在客户端接口中绑定的数量。我不确定pg的.net驱动程序限制是多少,因为我周围没有.net环境,所以无法对实际答案进行评论,很抱歉:( - Magnus Hagander
关于SQLite,参数数量的限制默认为999个;这在http://www.sqlite.org/limits.html的“单个SQL语句中主机参数的最大数量”下有说明。 - Dan D.
2
我已经成功地使用官方ADO.NET连接器MySqlCommand添加了100,000个参数,因此限制大于65,536。请注意,MySqlCommand.Parameters.Add方法使用O(n)算法(截至v6.5.4),因此添加100,000个参数确实需要近两分钟(添加_n_个参数总体上是O(n^2))。 - Bradley Grainger
值得注意的是,您的数据库客户端/驱动程序也可能会影响此限制。例如,似乎PostgreSql的JDBC驱动程序将最大参数数量限制为32,767(2 ** 15 - 1):https://blog.makk.es/postgresql-parameter-limitation.html - tdg5
使用PostgreSQL 9.6.3,我可以无问题地进行具有65535个参数的单个插入。而65536个或以上的参数则会失败。 - phiresky
显示剩余2条评论

17
在jOOQ中,我们通过在达到每个供应商的相关数字时内联绑定值来解决这些限制。这些数字在此处有记录。并非所有数字都是根据供应商文档正确的数字,我们通过JDBC的试错法经验主义地发现了它们。它们是(不将它们与特定版本绑定):
  • Ingres:1024
  • Microsoft Access:768
  • Oracle:32767
  • PostgreSQL:32767
  • SQLite:999
  • SQL Server:2100(取决于版本)
  • Sybase ASE:2000

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


1
@TimBüthe:通常,jOOQ生成的SQL语句会产生绑定变量,例如 SELECT * FROM t WHERE x IN (?, ?, ..., ?)。但是当达到限制(或客户端代码明确请求)时,生成的SQL将包含“内联”值,例如 SELECT * FROM t WHERE x IN (1, 2, ..., 53675) - Lukas Eder
ORA-01795限制到1000怎么样?这似乎与您在此处提供的数字相矛盾。 - Michael Piefel
3
这是完全不同的限制,即IN列表中元素数量的限制。jOOQ通过使用“OR”谓词来分割IN列表来处理此限制。这个限制与是否使用绑定变量无关。 - Lukas Eder
针对IBM DB2 v11,限制为32767,详细信息可参见产品文档:https://www.ibm.com/docs/en/db2/11.5?topic=sql-xml-limits。 - Axinet
@Axinet:它确切地在哪里说了? - Lukas Eder
显示剩余2条评论

7

1
当前协议参数在此处:https://www.postgresql.org/docs/current/protocol-message-formats.html。同样的限制。 - kavadias

6

对于关于查询的边界参数,PostgreSQL 的正确答案似乎是 34464。而对于函数的参数数量,响应为 100 仍然是正确的。


7
使用PostgreSQL 9.6.3,我可以轻松地进行包含65535个参数的单个插入操作。当参数超过65536时,则会失败。 - phiresky
这个答案太旧了。 - kavadias

0
在我看来,MySQL的问题实际上有两个答案。预处理语句协议定义了一个有符号的2字节短整型,用于描述将从服务器检索到的参数数量。客户端首先调用COM_STMT_PREPARE,如果成功,则接收到一个COM_STMT_PREPARE响应
关于这个响应的文档如下所示:
如果 num_params > 0,则会跟随更多数据包: 参数定义块 - num_params * Protocol::ColumnDefinition - EOF_Packet
鉴于num_params最大只能是2^16(有符号短整型),因此这就是参数的限制。由于我们公司使用自定义的MySQL驱动程序,在实现时选择遵循这个规则,如果超过了限制,就会抛出异常。

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

只要您在客户端有一种方法知道参数的数量(如果您愿意,可以使用client_num_params),您可以以这样的方式实现MySQL客户端,即它希望看到client_num_params x Protocol::ColumnDefinition。您还可以观察EOF_Packet,但只有在未启用CLIENT_DEPRECATE_EOF时才会实际发送该数据包。

值得注意的是,在num_params之后还有一个保留字节,表明协议设计者可能希望将其作为一个24位数字的选项,从而允许约830万个参数。这也需要额外的客户端能力标志。

总结:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接