How to prevent Query of Queries returning case sensitive results from CFC in Coldfusion - coldfusion-11

I have an issue where I'm joining two record sets from two different datasources using Ben Nadel's QueryAppend.cfc. The data I get back is correct but the ordering of the data is not expected. The combined result set is being sorted like so with all results starting with a lowercase letter appended to the bottom of the record set:
Screen grab of cfdump
I'm expecting (and need) the following type of sort:
Apple
art
bottle
Boy
Cat
coin
dart
Dog
Code follows:
<!---Calling Template--->
<cfquery name="getDataSet1" datasource="datasource1">
SELECT param1
FROM table1
</cfquery>
<cfquery name="getDataset2" datasource="datasource2">
SELECT param1
FROM table2
</cfquery>
<cfscript>
// Create object
TheUnionObject = createObject("component", "cfc/QueryAppend");
// Call the function
myUnionResult = TheUnionObject.QueryAppend(getDataSet1, getDataSet2);
</cfscript>
<!---Dump results--->
<cfdump var="#myUnionResult#">
<!---QueryAppend.cfc--->
<cfcomponent>
<cffunction name="QueryAppend" access="public" returntype="query"
output="false"
hint="This takes two queries and appends the second one to the first one.
Returns the resultant third query.">
<cfargument name="QueryOne" type="query" required="true" />
<cfargument name="QueryTwo" type="query" required="true" />
<cfset var LOCAL = StructNew() />
<cfquery name="LOCAL.NewQuery" dbtype="query">
(
SELECT
*
FROM
ARGUMENTS.QueryOne
)
UNION
(
SELECT
*
FROM
ARGUMENTS.QueryTwo
) ORDER BY Param1 ASC
</cfquery>
<cfreturn LOCAL.NewQuery />
</cffunction>
</cfcomponent>
I'm assuming that this default sorting behavior is some under-the-hood ColdFusion code. Can anyone tell me how to effect a change to this default ORDER BY behavior?

A quick fix would be to add a field to your select statement that upper cases (upper) the field value you want to sort by and then order by that field, but still output the uncased field. Something along the lines of:
select *,
upper(name) as upperName
from query
order by upperName

Related

coldfusion combine results from two queries

I have two coldfusion queries, like below which return different columns along with a date column.
<cfquery name="qry1" datasource="test">
select title, name, id, test_date from table1 , table2
</cfquery>
<cfquery name="qry2" datasource="test">
select headline, itemid, create_dt from table3 , table4
</cfquery>
I want to join the results of these two queries and in the final query need the results to be ordered by the date desc (note: date returned in the 2 queries is 2 different columns). I know there is the option of union all these two queries and I do not want to use it as it will slow down the request. Any ideas on different way to achieve this.
<CFQUERY NAME="getDetails" DBTYPE="query"> 
SELECT emp_id, url_shortcut, title, name, join_dt
,'' as item_id,'' as batch_id, '' as item_text
FROM get_related_info_one
 
UNION ALL
SELECT  to_number('') as emp_id,  '' as url_ shortcut,  '' as title, '' as name
,item_date as join_dt, item_id, batch_id, item_text 
FROM get_related_info_two
</CFQUERY> 
I am getting the error:
Query Of Queries syntax error.
Encountered "(.
Incorrect Select Statement,
Expecting a 'FROM', but encountered '(' instead,
A select statement should have a 'FROM' construct.
Any idea what am i missing here.
As long as the column types are the same you can UNION them like this.
<cfquery name="qry1" datasource="test">
select title, name, id, test_date
from table1 , table2
UNION
select headline, '' as name, itemid, create_dt
from table3 , table4
ORDER BY test_date
</cfquery>
If you're looking for a CF-based approach (especially when using in-memory query-of-queries), Ben Nadel wrote a QueryAppend UDF.
https://www.bennadel.com/blog/114-coldfusion-queryappend-qone-qtwo.htm
I made some recent tweaks to it so that NULL dates (treated as "empty" by ColdFusion) aren't incorrectly cast.
https://gist.github.com/JamoCA/5a2adb52cbeb4e15337a7d899222072e
<!--- 7/5/2006 QueryAppend By Ben Nadel https://www.bennadel.com/blog/114-coldfusion-queryappend-qone-qtwo.htm
1/5/2017 New "EmptyAsNull" option to prevent NULL values (dates & numbers) from being incorrectly recast
to an invalid "empty string" by ColdFusion's Query-of-Queries and throwing "Error casting an object
of type to an incompatible type" error. --->
<cffunction name="QueryAppend" access="public" returntype="void" output="false" hint="This takes two queries and appends the second one to the first one. This actually updates the first query and does not return anything.">
<cfargument name="QueryOne" type="query" required="true">
<cfargument name="QueryTwo" type="query" required="true">
<cfargument name="EmptyAsNull" default="" required="false">
<cfset var LOCAL = StructNew()>
<cfset LOCAL.Columns = ListToArray(ARGUMENTS.QueryOne.ColumnList)>
<cfset LOCAL.EmptyAsNull = 0>
<cfif isValid("boolean", ARGUMENTS.EmptyAsNull) AND ARGUMENTS.EmptyAsNull>
<cfset LOCAL.EmptyAsNull = 1>
</cfif>
<cfloop query="ARGUMENTS.QueryTwo">
<cfset QueryAddRow(ARGUMENTS.QueryOne)>
<cfloop ARRAY="#LOCAL.Columns#" index="LOCAL.ColumnName">
<cfif StructKeyExists(ARGUMENTS.QueryTwo, LOCAL.ColumnName) AND (NOT LOCAL.EmptyAsNull OR LEN(ARGUMENTS.QueryTwo[LOCAL.ColumnName][ARGUMENTS.QueryTwo.CurrentRow]))>
<cfset ARGUMENTS.QueryOne[LOCAL.ColumnName][ARGUMENTS.QueryOne.RecordCount] = ARGUMENTS.QueryTwo[LOCAL.ColumnName][ARGUMENTS.QueryTwo.CurrentRow]>
</cfif>
</cfloop>
</cfloop>
<cfreturn>
</cffunction>

Fetch out of sequence in coldfusion fw1 application

I am working on a coldfusion fw1 application and am trying to get all records in a table greater than a certain date.
START_DATE is a varchar not a date.
The query works if I type it directly into Oracle Sql Developer.
I have tried using the cfqueryparam tag but get the same error.
The query is located in a service.
<cfargument name = "studyType" default="null">
<cfset minDate = '12/31/99'>
<cfset maxDate = '01/01/55'>
<cfquery name="summaryInformation" datasource="#application.dsStudy#">
select
START_DATE
from RPTS_STUDY
where TO_DATE(START_DATE, 'MM/DD/YY') >= TO_DATE('#minDate#', 'mm/dd/yy')
</cfquery>
Error:
[Oracle JDBC Driver][Oracle]ORA-01002: fetch out of sequence

How to query a list of several thousand IDs [duplicate]

This question already has an answer here:
Select IN on more than 2100 values
(1 answer)
Closed 8 years ago.
In Coldfusion I'm trying to do a select query on an Oracle database table that I only have read access to. I have a list (lets call it myList) of several thousand IDs that I want to do the query on.
SELECT * FROM table
WHERE userID IN (#myList#)
The issue I have is that Oracle only lets me use IN with 1000 items at a time. What is the most efficient way to approach this? Break up the list by 1000 and append the resulting queries? If so what should my code for breaking the list look like?
Thanks!
There is a function available on cflib.org called ListSplit. It splits your long list into an array of shorter lists. Once you find and run this, your query starts to look like this:
select JustTheFieldsYouNeed
from SomeTables
where 1 = 3
<cfloop array="#ArrayOfShorterLists#" index = "ThisList">
or SomeField in
(<cfqueryparam cfsqltype="cf_sql_integer" value = "#ThisList#" List = "yes"> )
</cfloop>
If you're looking to do this for ad hoc queries, this can be done with a WITH query:
WITH
UserList AS
(
SELECT 'UserID1' AS UserID FROM DUAL UNION ALL
SELECT 'UserID2' AS UserID FROM DUAL UNION ALL
...
SELECT 'UserIDX' AS UserID FROM DUAL
)
SELECT t.*
FROM table t
JOIN UserList U
ON t.UserID = U.UserID
That list in between the parentheses of the UserList WITH query can be as long as you want it to be, and can pretty easily be created with Excel (assuming that's where the list you want to check originated).
-
Example Excel formula (assuming your first value is in A2):
="SELECT '" & A2 & "' AS UserID FROM DUAL" & IF(A3="", "", " UNION ALL ")
or, if your UserID is numeric:
="SELECT " & A2 & " AS UserID FROM DUAL" & IF(A3="", "", " UNION ALL ")
(autofilling this down to the bottom of your list will create everything you need to paste in between the parentheses of that query above)
-
HOWEVER, note that this is only good for ad hoc type queries. This is not a good solution if you need to do this on an automatic basis. If this is for a more permanent solution, use temp (or permanent) tables.
Edit Starts Here
Here is some simple code that shows how to do this in ColdFusion
<cfset ids = "1,2">
<cfquery name="x" datasource="oraclesomething">
with IDList as (
select 0 id
from dual
where 1 = 2
<cfloop list="#ids#" index="ThisID">
union
select #ThisID# id
from dual
</cfloop>
)
select count(*) from some_table join IDList on someid = id
</cfquery>
<cfdump var="#x#" metainfo="no">

Coldfusion/Oracle - Inserted BLOB Value is Returning an Empty String

Using coldfusion 8, blob values selected from a table are appearing as "[empty string]".
Is there a mistake in my cfml or is there another issue?
I appreciate the help!
ColdFusion Server - 8,0,1,195765
Oracle Database 11g - 11.2.0.3.0 - 64bit
BLOB test -
<cfset idval="1">
<cfset val="hello world">
<cfset encoding="utf-8">
<!---STRING CONVERSION TO BINARY DATA--->
<cfset form.binVal = CharsetDecode(val,encoding)>
<cfdump var="#form.binVal#">
<!---CLEAR TABLE--->
<cfquery name="delete" datasource="DATA1">
DELETE FROM DATA1.TEST_BLOB
</cfquery>
<!---INSERT--->
<cfquery name="insert" datasource="DATA1">
INSERT INTO DATA1.TEST_BLOB
VALUES(<cfqueryparam value="#idval#">,
<cfqueryparam cfsqltype="CF_SQL_BLOB" value="#form.binVal#">
)
</cfquery>
<!---SELECT AND DISPLAY DATA--->
<cfquery name="select" datasource="DATA1">
SELECT *
FROM DATA1.TEST_BLOB
</cfquery>
<cfdump var="#select#">
A utl_raw.cast_to_Varchar2() is needed to get results:
<cfquery name="select" datasource="DATA1">
SELECT UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(*name_of_field*))
FROM DATA1.TEST_BLOB
</cfquery>
OR
To return the data without casting
Go to the CF admin setting for the DSN, there are advanced setting that enable BLOB data

ColdFusion using Oracle's "INSERT ... RETURNING ... INTO" statement

I am building a simple chat application with ColdFusion and I am trying to get a message ID when I run my insert. Here is what I have so far
<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>
The error I am getting is
Error Executing Database Query.
Not all return parameters registered
I know there are workarounds with stored procedures, and running multiple queries. I would like to know how to do it this way.
This is an old question so apologies in advance for the necromancy. In my opinion the best (and maybe only) way to accomplish this is by wrapping the INSERT statement in a stored procedure and returning the values from the RETURNING ... INTO clause in an output parameter.
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;
/
You can then invoke this stored procedure from ColdFusion as follows:
<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>
Hope this helps.
ID is something returned by the query - not something you are going to send into the query - right? Something like (note - untested):
<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 />
Otherwise you are expecting the driver to turn an Oracle var into a CF var before CF has actually received results from the driver conneciton (you are also passing the value 0, and not the name of the var you wish to return when you use #local.id# in value="").
EDIT:
If this is an "autoincrement" field another approach is to use the "Result" variable. That looks like this.
<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 is the Oracle version I think. Note - this is CF8 or later.

Resources