使用Oracle的“INSERT…RETURNING…INTO”语句的ColdFusion
我正在用ColdFusion构建一个简单的聊天应用程序,并试图在运行insert时获取消息ID。这是我到目前为止所拥有的使用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 />
<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可能更好。