【发布时间】:2017-01-04 10:02:52
【问题描述】:
我正在努力提高 Web 应用程序的数据导入性能,其中一件显着提高了性能的事情是将数据库相关逻辑从服务器端代码移植到数据库中的存储过程和函数中。
此外,在处理大量类似查询时,将它们分批排队以便稍后在单个 SQL 事务中执行,可以显着减少导入过程的瓶颈。
不幸的是,我在此过程中遇到了一个问题,由于某种原因,我不能在单个 SQL 命令中多次调用存储过程。
在我连续两次调用LegacyUpdateProduct 的地方使用这个 SQL 来展示我的问题。
SQL
存储过程接受一些带数据的参数,不返回结果集,并且输出带有行 ID 的 @ID 变量,在这种情况下我们无论如何都不需要。
CALL LegacyUpdateProduct(92,'00010','ADAISD 345',18.81,'91020200','FSB92','GS8219','FSB92',TRUE,2,3,0,0,@ID);CALL LegacyUpdateProduct(277,'0002335600','TPASD 987',6.04,'0 002 335 ','UX79','','',TRUE,2,3,0,0,@ID);
PHP
在 PHP 中,任何人都希望通过两次调用 LegacyUpdateProduct 来简单地运行查询,一切都会好起来的。
$sql = "CALL LegacyUpdateProduct(92,'00010','ADAISD 345',18.81,'91020200','FSB92','GS8219','FSB92',TRUE,2,3,0,0,@ID);CALL LegacyUpdateProduct(277,'0002335600','TPASD 987',6.04,'0 002 335 ','UX79','','',TRUE,2,3,0,0,@ID);"
# With Code Igniter
$this->db->query($sql);
# Or with raw PHP
mysqli_query($this->db->conn_id, $sql);
遗憾的是,事实并非如此。使用 Code Igniter 或普通 PHP 运行此查询会引发 SQL 错误。
注意:我用细齿梳理了数据,并利用 Code Igniter DB 转义机制来产生更安全的查询。
错误号:1064 您的 SQL 语法有错误
最有趣的是,当我在 PHPMyAdmin 或 MySQL Workbench 中复制和粘贴据称错误的 SQL 时,它运行平稳,没有错误或警告。
实际上,在 PHPMyAdmin 和 MySQL Workbench 中,我能够在单个查询中运行多达 50 次对 LegacyUpdateProduct 的连续调用,而不会出现问题。
我已经通过 Google 和 SO 寻找可能在某种程度上相关或有帮助的问题,但没有发现太多可继续的问题,除了这可能是某种 Code Igniter 错误,但即使是普通的 PHP我发现了同样的问题。
在对另一个有点相关的 SO question 的回答中,它提到这可能是一个 Code Igniter 错误,但是它没有解释为什么使用普通的 PHP mysqli_query() 这个查询会失败。
在另一个 question 的 cmets 中,对于不同的错误,提示可能存在并发问题,如果不等待前一个完成,就无法对过程进行顺序调用。我对 MySQL 并发性的理解不够,无法提出索赔,但是,查询中的每个命令不应该在前一个命令之后执行。
帮助?
【问题讨论】:
-
如果你想一次运行2条语句,你必须使用multi_query。或者只是将您的查询拆分为两个查询。
query不知道如何使用第一个;之后的代码,这就是您收到语法错误的原因。 -
很有趣,用于在同一个 sql 语句中运行多个查询,从未考虑过
mysqli可能已经实现了该操作方法以防止恶意意图。我已经探索了这条途径,并且我能够在第一次调用multi_query时在同一语句中运行所有存储过程,但是以下对multi_query的调用以某种方式下降。但更重要的是我没有注意到性能提升,我会阅读文档并更好地了解这种方法,更重要的是找出在;之后执行查询的 MySQL 连接标志。 -
为了节省您的时间,在
;之后启用执行的唯一方法是使用_multi。而且您不会从中获得太多性能提升(只要您保持连接打开)。总是喜欢单个查询!原因很多!例如。安全,参数绑定,更容易(_multi要求您在继续之前阅读所有结果,这就是您的以下查询失败的原因),...对于一些技术见解(例如连接设置),请查看 @987654324 @ -
我玩弄了一些客户端标志,但没有成功。源数据来自可靠的来源(无需用户输入),无论如何,我仍然使用 Code Igniter 进行数据转义和参数绑定来构建每个查询,这为整个过程带来了一定程度的安全性。那么,抛开最佳实践不谈,对于
mysqli,您是否知道一种使用查询而不是multi_query来运行多个查询的方法? -
没有这种方法。也没有一个理由这样做。只需通过单独的 query() 调用运行您的查询,就像您已经被告知的那样
标签: php mysql stored-procedures mysqli codeigniter-3