将SQL语句保存在表中以供以后执行是一个坏主意吗?


21

将SQL语句保存在MySQL表中以供以后执行是否是一个坏主意?SQL语句将准备好执行,例如,将没有参数可交换或任何其他内容DELETE FROM users WHERE id=1

我想我很懒,但是我想到了这个主意,因为我正在从事一个需要大量cron作业并定期执行SQL语句的项目。


您应该弄清楚是否打算一次运行这些SQL语句,或者是否要重复运行同一组语句。
GrandmasterB 2014年

10
整个问题似乎是基本方法错误的情况之一。但是很难确切说明原因,因为我们对问题空间了解得很少。
艾里克·罗伯逊

Answers:


46

很安全,如果您要这样。只要您像对待数据安全性一样谨慎对待安全性。

但是不要浪费时间,存储过程是存储在表中的SQL位。他们支持(不鼓励)参数化。

还要注意,通过使用MySql Event Scheduler而不是cron ,可以简化安全性并减少故障点的数量并减少网络通信。

出于充分的理由,其他数据库也具有与之等效的数据库。您并不是第一个需要此功能的人。


1
使用调度程序时+1。将调度程序的访问权限限制为仅对procs优于表访问。
JeffO 2014年

但是,如果您需要从UI中动态创建这些查询,该怎么办?例如,如果您允许管理员用户根据复杂的查询动态设置Web内容的访问规则。您不希望UI在数据库中创建新的proc。我认为在某些情况下,存储查询要比proc更好。
弟子

32

如果要将SQL语句保存在数据库中以供以后执行,则有比将它们放在表中更好的选择:使用为此特定目的提供的内置功能。将它们放在存储过程中。


2
那么cron作业在哪里存储要运行的存储过程列表?
JeffO 2014年

1
这可能是有用的stackoverflow.com/questions/6560639/…尽管它没有使用cron
MetaFight 2014年

不知道我在想什么 一系列proc都可以从一个proc中执行,因此cron作业只需要执行一个即可。
JeffO 2014年

11

不,我会说这不是一个好主意。

这意味着每个“真实”查询/更新都需要在数据库上命中2次-一次获取“真实”查询/更新,然后执行一次。

在小型系统中,这可能不是什么大问题,但是系统获得的用户/交易越多,扩展规模就越小。

我猜想这是由于在您的代码中寻找替代方法来嵌入SQL?

正如Mason Wheeler所建议的那样,将SQL封装在存储过程中将是比这种想法好得多的一种方法。


+1,这是@Mason Wheeler的解决方案正确的主要原因-他只是想强调这一点。尽管恕我直言,这不是性能问题,但我在这里看到的是最重要的-无需通过从数据库中提取SQL语句然后将其发回执行来使事情复杂化。
布朗

为什么sql语句列表必须存储在同一数据库/服务器等中?
JeffO 2014年

1
OP是建议对数据库进行2次点击的操作。我说他不应该这样做。然后,您问为什么它必须是相同的数据库/服务器。请问是谁说的?然后,您问如何在数据库上获得2次匹配。您为什么不陈述自己的实际问题,而不是在做什么?
ozz 2014年

1
@JeffO即使它是一个不同的数据库,它仍然是2个数据库查询,应该是1个查询,这是不必要的减速
Izkata 2014年

1
@Ozz:您过多地权衡了答案的性能方面-在大多数实际情况下,性能很可能被忽略。但是需要两个动作(第一个动作获取“真实的”查询/更新,第二个动作执行),使事情变得比必要的更为复杂。
布朗

4

抱歉,我认为这不是一个好主意。

考虑问题表更改的情况。假设您的id列重命名为new_id

除了更改本身之外,还有一个代码版本是为数据库的旧版本编写的,该版本可能不再运行。当然,您可能知道要检入代码表,但是对于其他人来说并不是立即显而易见的。

对于如上所述的更改,我通常会查看独立的SQL文件,存储过程,触发器,客户端代码(VB,C#,C ++等)中的内联SQL,但我想看看的最后一个地方在数据库表中。虽然也许我现在会!:)


2

有充分的理由将SQL存储在表中。我正在使用的软件现在包括一个用于生成文档的系统,并且该文档需要使用数据库中的数据进行相当复杂的计算。这些文档经常更新,在所需数据和需要执行的计算方面经常有很大不同。基本上,SQL被用作执行这些计算的脚本语言,并且SQL存储在表中,这些表还存储了这些文档的其他信息。维护这些文档的人员不是程序员或DBA,但他们熟悉数据库架构,并且精通SQL。对于他们而言,以存储过程的形式维护该SQL代码将是巨大的开销。

对于您所说的-“ ...一个需要大量cron作业的项目,这些项目将定期执行SQL语句”-其他答案可能是正确的,建议您使用存储过程或等效的DBMS。重新使用。

决定将SQL存储在表中还是将SQL存储在存储过程中的明智标准是确定谁将维护该SQL。如果用户维护该SQL,即在需要时编写并更改它,那么将SQL存储在表中可能是完全可以的,而且实际上是最好的。如果开发人员将维护该SQL,则应以可以通过您的(希望自动化的)构建和部署过程更新的形式存储该SQL,例如,将其存储为对象,例如存储过程本身在数据库中。


1
谢谢你的回答。我最终使用MySQL事件安排了查询的运行时间。当我只需要在特定用户操作之后15分钟后运行一些SQL语句时,很多人就会认为“基本方法是错误的” :)。
Amged Rustom 2014年

2
@AmgadSuliman –对每个人,特别是在SE网站上的每个人,慈善都是重要的。拥有强烈的意见固然很好,但对于我们喜欢权衡的模式而言,过度匹配容易了。但是,在这些网站上对他人慈善的部分原因是提供了足够的背景信息。太多的内容可以掩盖真正的问题,但通常可以通过后续编辑轻松解决。
肯尼·埃维特

1

最简单的方法是拥有一个.ini或其他配置样式文件来保留查询。通过这种方式,您可以将它们放在一个位置,无需访问数据库即可进行任何更改,而不必多次访问数据库并且在某些时候您可能希望/需要使用参数或向查询中添加条件(针对代码中的特定情况,使用更复杂的内容为它们添加代码)。

当然,您可以将它们保留在数据库级别(在表中,或者更好的是,作为存储过程),但是,如果您像我一样懒惰;-)但也要关注性能,.ini文件和PHP钟爱的parse_ini方法来读取它是必经之路(如果您要使用另一种编程语言,则需要自己寻找类似的方法)!通常,我会在应用程序的引导加载程序中读取此文件,并将其保存在静态对象中(也许在其顶部有一个缓存层),以在我们谈论大量不同的查询时真正加快速度。


1

例如,如果您只需要一次SQL语句,例如,要排队在下班时间执行一系列操作,那么可以,将它们放入表中就可以了。

如果您需要以指定的时间间隔执行同一条SQL语句,那么其他人提到的存储过程路由可能对您来说是一个更好的选择。

就是说,您要问的是非常不寻常的,并且可能表明存在其他问题。例如,如果您正在等待从数据库中删除用户,则最好调用调度的脚本来通过应用程序代码执行操作,而不是记录实际的SQL语句。这样,SQL和代码就不会永不同步。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.