接受查询作为参数的存储过程

时间:2019-01-16 22:25:19

标签: mysql amazon-rds-aurora aws-aurora

我正在尝试编写一个MySQL存储过程,该存储过程接受SELECT查询并针对数据库列表执行该查询。 MySQL甚至有可能吗?

我们的应用程序中的每个客户在同一实例上都有自己的数据库。所有客户数据库的架构结构都相同。有时,我需要对所有客户数据库(例如SELECT COUNT(*) FROM users)执行一个简单的SELECT查询。

我已经为常见的重复“实例级”查询(例如用户计数)存储了存储过程,但是我不想为一次性查询创建更多的存储过程(例如,由于错误代码而查询损坏的记录,查询用于我们计划要弃用的列,等等。

我当前的解决方案是我有一个node脚本,该脚本在本地运行以为每个数据库生成SELECT查询,然后使用UNION将它们全部连接起来以生成一个庞大的查询,然后在该查询上执行数据库实例。

SELECT 'customerdb1' AS customer,
       COUNT(*) AS user_count
FROM customerdb1.users
UNION
SELECT 'customerdb2' AS customer,
       COUNT(*) AS user_count
FROM customerdb2.users
UNION
SELECT 'customerdb3' AS customer,
       COUNT(*) AS user_count
FROM customerdb3.users

1 个答案:

答案 0 :(得分:4)

您可以使用PREPARE and EXECUTE在存储过程中完成此操作,但是以这种方式运行任意SQL被认为是一个安全漏洞。您说过,该程序只能由特殊帐户使用,但是仅允许该程序存在是一种风险。如果修改了特权并允许任何人运行该程序怎么办?

在许多模式下运行该查询也将非常慢,因为MySQL每个查询只运行一个线程。它必须串行运行查询,并将结果收集到临时表中。

此外,您对任何单个SQL查询的长度都有一个限制,即max_allowed_packet。这应该很大,但是如果您有足够的UNION术语,您仍然可以超过长度。

我在一个您所描述的网站上工作,那里有很多模式,每个客户一个,带有相同的表。当我们想在所有架构上运行查询时,我将在多个并行线程中运行一个简单查询(无UNION),并将结果收集到应用程序代码中。


有关可以允许输入任意SQL的存储过程的有趣故事,请参见https://thedailywtf.com/articles/For-the-Ease-of-Maintenance