I have a query created from using cfspreadsheet that has a date column named "Actiondate", and looping through the query using isDate() shows that it's a date column, but in a query of that query it is being treated as a string. So when I apply a date filter in the where clause, it doesn't do the comparison correctly:
<cfquery ... >
SELECT *
FROM arguments.q
WHERE 1=1
<cfif isDate(arguments.dateFrom)>
AND actiondate >= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.dateFrom#">
</cfif>
<cfif isDate(arguments.dateFrom)>
AND actiondate <= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.dateTo#">
</cfif>
</cfquery>
actiondate comes in the format of mm/dd/yyyy. When I do the where clause using string literals as a test, it works:
...where actiondate = '11/05/2015' --returns all rows with that "date"
<cfset tempdate = createdate(2015,11,5)>...
...where actiondate = <cfqueryparam cfsqltype="cf_sql_date" value="#temp#"> --returns nothing
But again, isDate(actiondate) returns true when looping through the query. I can work around the problem, but is there a way to do what I need to still using a query of query?
(From comments ...)
IsDate verifies a value can be converted into a date. That does not mean the value already is a date/time object. In the case of cfspreadsheet, the returned query values are strings. When you compare them to the cfqueryparam values, which are date/time objects, you are comparing apples and oranges. So the QoQ does an implicit conversion of the date/time values to string and comes up with the wrong answer.
To perform a date comparison on "ActionDate", you must use CAST to convert the strings into a date/time objects first. Assuming all of the values are valid date strings, in the format mm/dd/yyyy, try it with a hard coded value like 11/05/2015 first. Then plug in your variables.
WHERE CAST(actionDate AS DATE) = <cfqueryparam value="11/05/2015"
cfsqltype="cf_sql_date">
Related
I have a database field which contains VARCHAR values like
XY23(CX Web)
AND I am writing a Query of Queries like
SELECT qPdfs.filename, qPdfs.code, qObjects.id
FROM qPdfs, qObjects
WHERE qPdfs.code = qObjects.code
OR like
SELECT qPdfs.filename, qPdfs.code, qObjects.id
FROM qPdfs, qObjects
WHERE <cfqueryparam value="#qObjects.code#" cfsqltype="CF_SQL_VARCHAR"> = <cfqueryparam value="#qPdfs.code#" cfsqltype="CF_SQL_VARCHAR">
But I am getting an error message like
XY23(CX Web) must be interpretable as a valid number in the current locale.
Any help?
Thank you
Are both of the database columns type varchar? If so, the QoQ is probably applying some implicit conversion based on the contents of the columns. If some of the codes are all numeric, the QoQ may be attempting to cast them to numbers internally before performing the comparison. Hence the error. cfqueryparam won't help here, because it can only be used on literals, not query columns. If a straight equality comparison ie ColName = ColName causes that error, try casting instead:
WHERE CAST(qPdfs.code AS VARCHAR) = CAST(qObjects.code AS VARCHAR)
NB: QoQ string comparisons are case sensitive, so you may want to convert the columns to upper/lower case first.
I need to provide some status on items in my table which I do in the last column of my table.
First I go and query one table to see if I have a confirmation for the item .
<cfquery name="focnotice" datasource="******" result="FocResult">
SELECT ecspc
FROM tbl_CNR_H
WHERE icsc = '#myarray[i].ICSC#'
AND asr_no = '#myarray[i].ASR#'
</cfquery>
The ECSPC is a field in my Table, so logic is see if there is a record. If so, see if the ECSPC value is something other then "". If so, query another table to see if there is a matching record for this ECSPC.
<cfset ISUPStatus = "#focnotice.ecspc#">
<cfif ISUPStatus NEQ "">
<cfquery name="isupStatus" datasource="******" result="ISUPResult">
select *
from tbl_ISUP
where dpc = '#ISUPStatus#'
</cfquery>
<cfset isupcount = #ISUPResult.RecordCount#>
<cfif #isupcount# GT 0>
<cfset ISUPorder = "Yes">
<cfelse>
<cfset ISUPorder = "No">
</cfif>
<cfelse>
<cfset ISUPorder = "No">
</cfif>
I get the following error in my debug
Complex object types cannot be converted to simple values.
The expression has requested a variable or an intermediate expression
result as a simple value. However, the result cannot be converted to a
simple value. Simple values are strings, numbers, boolean values, and
date/time values. Queries, arrays, and COM objects are examples of
complex values. The most likely cause of the error is that you tried
to use a complex value as a simple one. For example, you tried to use
a query variable in a cfif tag.
What am I missing here ?
You are passing invalid parameter into the Query "myarray[i].ICSC",'#myarray[i].ASR#'. You need to specify what index of array you are using.
<cfquery name="focnotice" datasource="*******" result="FocResult">
Select ecspc
From tbl_CNR_H
Where icsc = <cfqueryparam cfsqltype="cf_sql_varchar" value="#myarray[1].ICSC#">
AND
asr_no = <cfqueryparam cfsqltype="cf_sql_varchar" value="#myarray[1].ASR#">
</cfquery>
I believe the error causing you the issue lies in:
<cfset isupcount = #ISUPResult.RecordCount#>
From a quick look of your code, try using instead:
<cfset isUpCount = isUpStatus.recordCount>
But in addition please look at the comments above, especially joins.
CF8
I was using this line to get the MIN value of a query column. I just noticed a null value in a recordset causes an error. Is there a simply way to tell ArrayMin to skip nulls w/o having to loop the column and load an array with all non-null values?
<cfset temp_data_min = #round(ArrayMin(query_x["some_field"]))#>
thanks!
Building off of what Al said with using the query-of-queries, just adding the Min() call into the query.
<cfquery name="query_x_fixed" dbtype="query">
SELECT Min(some_field) as some_field
FROM query_x
WHERE some_field IS NOT NULL
</cfquery>
<cfset temp_data_min = round(query_x_fixed.some_field)>
Tested to work in CF9
You could loop through your array and create a new array that doesn't contain any null values. Then apply the ArrayMin function to the new array.
<cfset newArray = []>
<cfloop index="x" array="#query_x["some_field"]#">
<cfif x NEQ 'null'>
<cfset arrayAppend(newArray, x)>
</cfif>
</cfloop>
<cfset temp_data_min = round(ArrayMin(newArray))>
NOT TESTED
Simplest way is probably to do a query-of-queries with just that column and remove the nulls.
<cfquery name="query_x_fixed" dbtype="query">
SELECT some_field
FROM query_x
WHERE some_field IS NOT NULL
</cfquery>
<cfset temp_data_min= round(ArrayMin(query_x_fixed["some_field"]))>
(not tested)
You can keep the solution at one line by converting the column to a list then into an array. ListToArray defaults to ignoring empty list items, which is what the null values will be.
<cfset temp_data_min = Round(ArrayMin(ListToArray(ValueList(query_x.some_field, Chr(7)), Chr(7))))>
This should be faster than any of the other proposed solutions and is less code.
I've specified the delimiter for locales that use the comma as the decimal separator in numbers. If you're in the US or another locale that uses the "." then you can remove the delimiter arguments.
Additional functions used:
ListToArray
ValueList
Chr
here is my ColdFusion code:
Example1:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = PRODUCT_CATID
</cfquery>
#get_brand.product_catid#
But it shows all the time number 1, i just can't understand why, and how do i make it work properly, this code should have defined the brand_id, but instead shows 1.
The system is Workcube.
Here is my example for getting from the static product's id, its dynamic price:
Example 2:
<cfset product_id = 630>
<cfquery name="price_standart" datasource="#dsn3#">
SELECT
PRICE_STANDART.PRICE PRICE
FROM
PRICE_STANDART
WHERE
PRICE_STANDART.PRODUCT_ID =
<cfqueryparam value="#product_id#" cfsqltype="cf_sql_integer">
</cfquery>
But this time i need to get from dynamic product's ID its dynamic brand id.
This script works the same way as the Example 1:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT BRAND_ID
FROM PRODUCT_BRANDS
WHERE BRAND_ID = BRAND_ID
</cfquery>
#get_brand.BRAND_ID#
As Andreas shows in his code, your query isn't going to work as written. The statement WHERE PRODUCT_CATID = PRODUCT_CATID doesn't actually pass a value - it would actually just be self-referential within the table values. In this case, it would return everything in the table.
You should instead have:
WHERE PRODUCT_CATID = #PRODUCT_CATID#
Where #PRODUCT_CATID# represents a variable. Better yet, use cfqueryparam as Andreas shows (this prevents SQL injection and improves query performance). However, I am not even sure that is what you intend since if you have the product ID why do you need to get it from the database? Instead, I assume you probably want to get the brands from the product in a particular category. Not knowing your table structure, it's hard to write that query for you but it might look something like:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT.BRAND_ID
FROM PRODUCT
INNER JOIN PRODUCT_CAT
ON PRODUCT.PRODUCT_CATID = PRODUCT_CAT.PRODUCT_CATID
WHERE PRODUCT_CATID = <cfqueryparam cfsqltype="cf_sql_integer" value="#product_catid#">
</cfquery>
Lastly, as both comments indicate, you would need to loop through the results to see all the records returned.
You need to wrap the statement in tags like this.
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID FROM PRODUCT_CAT WHERE PRODUCT_CATID = PRODUCT_CATID
</cfquery>
<cfoutput query =GET_Brand">
#get_brand.product_catid#
</cfoutput>
It's not very clear what your question really is about, but let me guess:
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT PRODUCT_CATID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = <cfqueryparam cfsqltype="cf_sql_integer" value="#product_catid#">
</cfquery>
where #product_catid# refers to a variable you defined earlier in your code or received via form or url scope.
<cfloop query="GET_BRAND">
#get_brand.product_catid#<br />
</cfloop>
will show a list of all the product_catid's returned by the query.
It's not too clear what you are after here, but in the queries there are at least 2 problems. First your WHERE clause
WHERE PRODUCT_CATID = PRODUCT_CATID
is like saying
WHERE 1=1
This will return the full recordset. You can see this by adding
<cfdump var="#GET_BRAND#">
under your code to see the query output. I'm guessing this will show all records in the table.
To match just one record you need your WHERE clause to be like
WHERE PRODUCT_CATID = 3
or have the #...# wrapped around the variable you are trying to match to make it dynamic.
Secondly to the query result may be more than one record, and to see any more than the first record you need to loop over the output. One way is to use
<cfoutput query="GET_BRAND">
#BRAND_ID# <br>
</cfoutput>
My guess of what you are after is
<cfset ID_TO_MATCH=3>
<cfquery name="GET_BRAND" datasource="#dsn1#">
SELECT BRAND_ID
FROM PRODUCT_CAT
WHERE PRODUCT_CATID = #ID_TO_MATCH#
</cfquery>
<cfoutput query="GET_BRAND">
#BRAND_ID# <br>
</cfoutput>
I am outputting a query but need to specify the first row of the result. I am adding the row with QueryAddRow() and setting the values with QuerySetCell().
I can create the row fine, I can add the content to that row fine. If I leave the argument for the row number off of QuerySetCell() then it all works great as the last result of the query when output. However, I need it to be first row of the query but when I try to set the row attribute with the QuerySetCell it just overwrites the first returned row from my query (i.e. my QueryAddRow() replaces the first record from my query). What I currently have is setting a variable from recordCount and arranging the output but there has to be a really simple way to do this that I am just not getting.
This code sets the row value to 1 but overwrites the first returned row from the query.
<cfquery name="qxLookup" datasource="#application.datasource#">
SELECT xID, xName, execution
FROM table
</cfquery>
<cfset QueryAddRow(qxLookup)/>
<cfset QuerySetCell(qxLookup, "xID","0",1)/>
<cfset QuerySetCell(qxLookup, "xName","Delete",1)/>
<cfset QuerySetCell(qxLookup, "execution", "Select this to delete",1)/>
<cfoutput query="qxLookup">
<tr>
<td>
#qxLookup.xName#
</td>
<td>#qxLookup.execution#</td>
</tr>
</cfoutput>
Thanks for any help.
I would add some kind of sort order column to your original query, populating it with a fixed value of 1.
<cfquery name="qxLookup" datasource="#application.datasource#">
SELECT xID, xName, execution, 1 as sortorder
FROM table
</cfquery>
Set the value of that column in your synthetic row to a value of 0.
<cfset QueryAddRow(qxLookup)>
...
<cfset QuerySetCell(qxLookup, "sortorder", "0",1)>
Then use query-of-queries to reorder the recordset by the sortorder column.
<cfquery name="qxLookup" dbtype="query">
select xid, xname, execution
from qxLookup
order by sortorder
</cfquery>
Well I have dealt with this problem before, for me the answer was to have 2 seperate queries.
1st, being your normal query, 2nd being the query of queries, then do a union of them, with the qofq being above the normal query, and that should give you results in the order you want.
Something like this:
<cfquery name="table_a_results" datasource="">
select a, b, c
from table_a
</cfquery>
cfset table_b = querynew("a, b, c")
cfset temp = queryaddrow("table_b")
cfset temp = querysetcell(table_b,10)
cfset temp = querysetcell(table_b,20)
cfset temp = querysetcell(table_b,30)
<cfquery name="final_query" dbtype="query">
select a, b, c
from table_b
union
select a, b, c
from table_a_results
</cfquery>
Then using this tool you can put queries in any order you like, but remember to use the order by tag, to change order...
Just an alternative to above, but you could take ColdFusion out of the picture and do this solely in the SQL using something like (eg in oracle)
select 'myinsertedvalue' from dual
union
select myrealvalues from mutable
You could combine with Kens sort column to get full ordering. Assuming you are getting the main query from a DB!