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

Joh*_*ohn 0 mysql coldfusion stored-procedures 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>
Run Code Online (Sandbox Code Playgroud)

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

Mig*_*l-F 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,但大多数适用于任何数据库
参考 - 存储过程(数据库引擎)