使用Oracle的“INSERT…RETURNING…INTO”语句的ColdFusion

使用Oracle的“INSERT…RETURNING…INTO”语句的ColdFusion,oracle,coldfusion,Oracle,Coldfusion,我正在用ColdFusion构建一个简单的聊天应用程序,并试图在运行insert时获取消息ID。这是我到目前为止所拥有的 <cffunction name="putMessage" access="remote" returnformat="JSON"> <cfargument name="message" /> <cfset LOCAL.id = 0 />

我正在用ColdFusion构建一个简单的聊天应用程序,并试图在运行insert时获取消息ID。这是我到目前为止所拥有的

<cffunction name="putMessage" access="remote" returnformat="JSON">

     <cfargument name="message" />
     <cfset LOCAL.id = 0 />

     <cfquery name="insertquery" datasource="myDS"> 
          insert into 
               chat (message) 
          values 
               (<cfqueryparam cfsqltype="cf_sql_varchar" value="#ARGUMENTS.message#">)
          RETURNING
               id
          INTO
               <cfqueryparam cfsqltype="cf_sql_numeric" value="#LOCAL.id#">
     </cfquery>

     <cfreturn LOCAL.id />
        
</cffunction>
我得到的错误是

执行数据库查询时出错

并非所有返回参数都已注册

我知道存储过程和运行多个查询有一些变通方法。我想知道如何这样做。

ID是查询返回的内容,而不是您将发送到查询中的内容,对吗?类似于note-未经测试:

 <cfargument name="message" />
 <cfset LOCAL.id = 0 />

 <cfquery name="insertquery" datasource="myDS"> 

      DECLARE newID NUMBER;

      insert into 
           chat (message) 
      values 
           (<cfqueryparam cfsqltype="cf_sql_varchar" 
                                  value="#ARGUMENTS.message#">)
      RETURNING
           id
      INTO
          newID
 </cfquery>

 <cfreturn insertquery.newID />
否则,您希望驱动程序在CF实际收到来自驱动程序连接的结果之前将Oracle var转换为CF var。您同时传递的是值0,而不是在value=中使用local.id时希望返回的var的名称

编辑: 如果这是一个自动递增字段,另一种方法是使用结果变量。看起来像这样

<cfquery name="insertquery" datasource="myDS" result="r"> 
      insert into 
           chat (message) 
      values 
           (<cfqueryparam cfsqltype="cf_sql_varchar" 
                                  value="#ARGUMENTS.message#">)

 </cfquery>

<cfreturn r.rowID/>  

我认为RowID是Oracle的版本。注-这是CF8或更高版本

这是一个老问题,所以提前为巫术道歉。在我看来,实现这一点的最好也是唯一的方法是将INSERT语句包装在存储过程中,然后从返回的语句返回值。。。输出参数中的INTO子句

CREATE OR REPLACE PROCEDURE chat_insert
  ( p_message IN VARCHAR2, r_id OUT NUMBER )
AS
BEGIN
  INSERT INTO chat ( message )
  VALUES ( p_message )
  RETURNING id INTO r_id;
END;
/
然后,您可以从ColdFusion调用此存储过程,如下所示:

<cffunction name="putMessage" access="remote" returnformat="JSON">
    <cfargument name="message" />
    <cfset LOCAL.id = 0 />

    <cfstoredproc procedure="chat_insert" datasource="myDS">
        <cfprocparam cfsqltype="CF_SQL_VARCHAR" type="in" value="#ARGUMENTS.message#" />
        <cfprocparam cfsqltype="CF_SQL_VARCHAR" type="out" variable="LOCAL.id" />
    </cfstoredproc>

    <cfreturn LOCAL.id />
</cffunction>

希望这有帮助。

是的。。您需要调试它,但这是正确的方法。也许在最后添加一个select as*select newID将其放入结果集中。只是好奇,没有Oracle需要测试。使用cfquery,您是否可以像Mark建议的那样,返回末尾带有SELECT的r_id变量?或者返回不是那样工作的?Oracle不是那样工作的——或者,至少,用ColdFusion打包的JDBC驱动程序不是这样的。cfquery块中不能有多条语句,就像MSSQL一样。事实上,如果从ColdFusion调用Oracle存储过程并希望返回查询,则需要有一个SYS_REFCURSOR类型的OUT参数,并在过程主体中为SELECT打开一个游标-同样,与MSSQL不同,在MSSQL中,您可以将SELECT作为过程中的最后一条语句插入。是的,我刚刚尝试使用Oracle的JDBC瘦客户端,这也不允许在单个cfquery块中使用多条语句。我不确定这是否是一件坏事——它有助于防止SQL注入——但如果它是可以打开和关闭的,那就太好了。没错,就像MySQL一样,只需将DSN设置中的参数更改为启用/禁用即可。尽管考虑到cfquery不会执行多个语句,但对于这样的东西,使用proc可能更好。