有没有比使用存储过程更好的方法?

时间:2014-08-26 22:07:58

标签: mysql stored-procedures coldfusion coldfusion-9 sendgrid

请考虑使用以下代码来获取Sendgrid发布的数据。

<cftry>              
 <cfset incomingData = toString(getHttpRequestData().content) />
 <cfset djs = DeserializeJSON(incomingData)/>

<cfset a = "0">
<cfset b = "">
<cfset c = "0">
<cfset d = "0">
<cfset e = "">
<cfset f = "">
<cfset g = "">
<cfset h = "">
<cfset i = "">
<cfset k = "#NOW()#">
<cfset l = "">
<cfset m = "">
<cfset n = "">

<cfoutput>
<cfloop from="1" to="#arraylen(djs)#" index="i">

    <cfset a = "0">
    <cfset b = "">
    <cfset c = "0">
    <cfset d = "0">
    <cfset e = "">
    <cfset f = "">
    <cfset g = "">
    <cfset h = "">
    <cfset i = "">
    <cfset k = "#NOW()#">
    <cfset l = "">
    <cfset m = "">
    <cfset n = "">

    <cfif StructKeyExists(djs[i],'p')>
        <cfset a       = djs[i].p />
    </cfif>

    <cfif StructKeyExists(djs[i],'q')>
        <cfset b           = djs[i].q />
    </cfif>
    <cfif StructKeyExists(djs[i],'r')>
        <cfset c       = djs[i].r />
    </cfif>
    <cfif StructKeyExists(djs[i],'s')>
        <cfset d       = djs[i].s />
    </cfif>     
    <cfif StructKeyExists(djs[i],'t')>
        <cfset e       = djs[i].t />
    </cfif>
   <cfif StructKeyExists(djs[i],'u')>
        <cfset f           = djs[i].u />
    </cfif>
    <cfif StructKeyExists(djs[i],'v')>
        <cfset g       = djs[i].v />
    </cfif>

    <cfif StructKeyExists(djs[i],'w')>
        {                                                                         
        <cfset i  = djs[i].w />
        <cfset k  = dateAdd("s", i, createDateTime(1970, 1, 1, 0, 0, 0))/>
        }
    </cfif>
    <cfif StructKeyExists(djs[i],'x')>
        <cfset l         = djs[i].x />
    </cfif>
    <cfif StructKeyExists(djs[i],'y')>
        <cfset m       = djs[i].y />
    </cfif>
    <cfif StructKeyExists(djs[i],'z')>
        <cfset n       = djs[i].z /> 
    </cfif>

    <cfstoredproc procedure="sp1" datasource="db1">
        <cfprocparam cfsqltype="cf_sql_bigint" value="#a#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(b,199)#">
        <cfprocparam cfsqltype="cf_sql_integer" value="#c#">
        <cfprocparam cfsqltype="cf_sql_integer" value="#d#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(e,199)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(f,199)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(g,499)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(h,199)#">
        <cfprocparam cfsqltype="cf_sql_timestamp" value="#k#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(l,199)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#LEFT(m,499)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(n,99)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="XX.XX.X.XX">
    </cfstoredproc>


    <cfstoredproc procedure="sp2" datasource="db2">
        <cfprocparam cfsqltype="cf_sql_bigint" value="#a#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(b,199)#">
        <cfprocparam cfsqltype="cf_sql_integer" value="#c#">
        <cfprocparam cfsqltype="cf_sql_integer" value="#d#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(e,199)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(f,199)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(g,499)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(h,199)#">
        <cfprocparam cfsqltype="cf_sql_timestamp" value="#k#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(l,199)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#LEFT(m,499)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="#left(n,99)#">
        <cfprocparam cfsqltype="cf_sql_varchar" value="XX.XX.X.XX">
    </cfstoredproc>   

</cfloop>

</cfoutput>

</cftry>

从上面可以清楚地看出,我的代码依赖于MySQL数据库上的存储过程。我正在考虑摆脱存储过程并找到一种不同的方式,我可以在没有任何存储过程的情况下完成我正在寻找的东西。除了使用存储过程将输入数据存储到数据库之外,还有更好的方法吗?

2 个答案:

答案 0 :(得分:6)

除了使用存储过程将传入数据存储到数据库之外,还有更好的方法吗?不,不是真的。一个更好的问题是为什么你觉得有必要停止使用存储过程?

在与数据库交互时,您实际上只有三个选项;存储过程,内联查询(参数化)或对象关系映射(ORM)。当然,您可以使用内联查询或ORM替换存储过程调用,但我不认为您将获得任何收益。

使用存储过程而不是内联查询的一些好处是:

  
      
  • 减少服务器/客户端网络流量
      过程中的命令作为一批代码执行。这可以显着减少服务器和客户端之间的网络流量,因为只有通过网络发送执行该过程的调用。如果没有程序提供的代码封装,每一行代码都必须通过网络。

  •   
  • 更强的安全性
      多个用户和客户端程序可以通过过程对底层数据库对象执行操作,即使用户和程序对这些底层对象没有直接权限也是如此。该过程控制执行的进程和活动,并保护底层数据库对象。这消除了在单个对象级别授予权限并简化安全层的要求。   

    可以在CREATE PROCEDURE语句中指定EXECUTE AS子句以启用模拟其他用户,或使用户或应用程序能够执行某些数据库活动,而无需对基础对象和命令的直接权限。例如,某些操作(如TRUNCATE TABLE)没有可授予的权限。要执行TRUNCATE TABLE,用户必须对指定的表具有ALTER权限。授予用户对表的ALTER权限可能并不理想,因为用户将有效地拥有超出截断表能力的权限。通过将TRUNCATE TABLE语句合并到模块中并指定该模块作为具有修改表权限的用户执行,可以扩展权限以将表截断为对模块授予EXECUTE权限的用户。   

    通过网络调用程序时,只能看到执行该程序的调用。因此,恶意用户无法查看表和数据库对象名称,嵌入自己的Transact-SQL语句,或搜索关键数据。   

    使用过程参数有助于防止SQL注入攻击。由于参数输入被视为文字值而不是可执行代码,因此攻击者更难以将命令插入到过程内的Transact-SQL语句中并破坏安全性。   

    程序可以加密,有助于混淆源代码。有关详细信息,请参阅SQL Server加密。

  •   
  • 重复使用代码
      任何重复数据库操作的代码都是程序封装的理想选择。这消除了对相同代码的不必要的重写,减少了代码的不一致性,并允许任何拥有必要权限的用户或应用程序访问和执行代码。

  •   
  • 维护更方便
      当客户端应用程序调用过程并在数据层中保留数据库操作时,只需更新基础数据库中的任何更改的过程。应用程序层保持独立,无需了解对数据库布局,关系或进程的任何更改。

  •   
  • 提高效果
      默认情况下,过程在第一次执行时编译,并创建一个执行计划,该计划将重复用于后续执行。由于查询处理器不必创建新计划,因此处理该过程通常需要较少的时间。   如果对过程引用的表或数据进行了重大更改,则预编译计划实际上可能会导致过程执行速度变慢。在这种情况下,重新编译过程并强制执行新的执行计划可以提高性能。

  •   

其中一些特定于SQL Server,但大多数适用于任何数据库 Reference - Stored Procedures (Database Engine)

答案 1 :(得分:0)

这取决于存储过程的作用。它只插入一行数据吗?

我建议您使用循环将数据放入数组或结构中,然后进行一次数据库调用(通过cfquery或cfstoredproc)来插入数据。