I'm trying to create a script in ColdFusion that detects if a query exist for the specified user by using these queries:
// User one is defined by the current session
<cfquery name = "Friendship" datasource = "#DSN#">
SELECT *
FROM `conversations`
WHERE `user_one` LIKE '#user.id#'
ORDER by id ASC
</cfquery>
<cfquery name = "FriendshipToUsername" datasource = "#DSN#">
SELECT *
FROM users
WHERE id = '#user_two#'
ORDER BY id DESC
</cfquery>
But, when this query doesn't have a result i want to use the following queries:
<cfquery name = "Friendship" datasource = "#DSN#">
SELECT *
FROM `conversations`
WHERE `user_two` LIKE '#user.id#'
ORDER by id ASC
</cfquery>
<cfquery name = "FriendshipToUsername" datasource = "#DSN#">
SELECT *
FROM users
WHERE id = '#user_one#'
ORDER BY id DESC
</cfquery>
Is this possible to do in ColdFusion? I want to keep the names of the query this way, otherwise i will need to change my whole site. This is the code of my page, if you need it:
<cfif IsDefined("FriendshipToUsername.username")>
<div class="person">
<div class="avatar">
<div style="z-index:1;width: 64px; height: 73px; margin-bottom:-20px; margin-top:-30px; float: right; background: url(http://habbo.it/habbo-imaging/avatarimage?figure=#FriendshipToUsername.look#&action=wav&direction=3&head_direction=3&gesture=srp&size=b&img_format=gif);"></div>
</div>
<div class="info">
<h3>#FriendshipToUsername.username#</h3>
<p>#FriendshipToUsername.motto#</p>
<p>Laatst gezien: gisteren</p></a>
</div>
</div>
</cfif>
Thanks in advance!
You can test the .recordcount attribute as shown below.
<cfif friendship.recordcount eq 0>
<cfquery name = "Friendship" datasource = "#DSN#">
SELECT *
FROM `conversations`
WHERE `user_two` LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="#user.id#">
ORDER by id ASC
</cfquery>
<cfquery name = "FriendshipToUsername" datasource = "#DSN#">
SELECT *
FROM users
WHERE id = <cfqueryparam cfsqltype="cf_sql_varchar" value="#user_one#">
ORDER BY id DESC
</cfquery>
</cfif>
I would also suggest looking up and using the cfqueryparam tag to prevent your code from being affected by sql injections.
Check the recordcount property of the friendship and friendshipToUsername queries. You can simply re-query the database reusing the same query names as before.
You should also, of course, be using cfqueryparam to protect your database from sql injection attempts.
<!---(original friendship and friendshipToUsername queries)--->
<cfif NOT friendship.recordcount> <!--- or "friendship.recordcount EQ 0" if you prefer --->
<cfquery name = "Friendship" datasource = "#DSN#">
SELECT *
FROM `conversations`
WHERE `user_two` LIKE <cfqueryparam value="#user.id#" cfsqltype="cf_sql_integer">
ORDER by id ASC
</cfquery>
<cfquery name = "FriendshipToUsername" datasource = "#DSN#">
SELECT *
FROM users
WHERE id = <cfqueryparam value="#user_one#" cfsqltype="cf_sql_integer">
ORDER BY id DESC
</cfquery
</cfif>
I suggest modifying your original query a bit so that it tries to retrieve both records at the same time. This way, you won't need to make two trips to the server if the first query returns zero rows:
<cfquery name = "Friendship" datasource = "#DSN#">
SELECT *
FROM `conversations`
WHERE `user_one` LIKE '#user.id#'
OR [get other user here]
ORDER by id ASC
</cfquery>
Once your query has executed, simply pull out the appropriate user.
Related
<cfquery datasource = "myDb" name = "compare">
select *
from users
where cnic = #form.cnic#
</cfquery>
<cfif compare.cnic eq form.cnic>
<p> *CNIC already Exists </p>
</cfif>
I think you're misstating the problem. It should be more like,
"How can I show a form to add a record I know is not in the database?"
Please clarify if that is not the case.
Based on your code, I assume there's been a form submission from another page already. You're running a query to see if there is a record in the users table where cnic = #form.cnic#. If there was no previous form submission, then form.cnic wouldn't exist.
<cfquery datasource="myDb" name="compare">
select *
from users
where
cnic = #form.cnic#
</cfquery>
So when this page loads, you've done your "check if a record is already in the database" with the query named compare. Now all you need to do is check if there are 0 records in the query.
<cfif compare.recordcount EQ 0>
<!--- Display form here. ---->
</cfif>
If the query returns any records, then there is at least one record in the database, so no need to show the form or allow it to be submitted.
You can use bellow code in Jquery ajax calling
<cfquery datasource = "myDb" name = "compare">
select *
from users
where cnic = #form.cnic#
</cfquery>
<cfif compare.recordcount GT 0>
<p> *CNIC already Exists </p>
</cfif>
Depending on your database, too, there are other options. MySQL has some features for INSERT ON DUPLICATE KEY UPDATE (https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html)
In MSSQL you can do:
IF NOT EXISTS (SELECT 1 FROM [users] u WITH (NOLOCK) WHERE cnic = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#form.cnic#")
INSERT INTO [users].....
(My cfsqltype syntax might not be 100% correct, but always use . Always.
Those might give you some other ways to handle your scenario.
I have some code that I am trying to make more efficient.
I am running a query and then looping through those results and running additional queries to drill down into my data even further. The code takes long to process and I'm sure that it is not as efficient as it could be and I believe that doing a query of queries would be more efficient, but I'm am not sure how to exactly implement that.
Here is my current code
My first query:
<!--- Get equipment Query --->
<cfquery name="get_equipment" datasource="#datasource#">
select *
from equipment_maintenance
where machine_type != 'unifi_site' AND machine_type != 'firewall' AND machine_type != 'dvr' AND machine_type != 'pbx' AND active = 'yes'
ORDER by #querySortType#
</cfquery>
Then I output my query and run additional queries:
<cfoutput query="get_equipment">
<!--- Get In-Progress Maintenance History --->
<cfquery name="get_in_progress_history" datasource="#datasource#">
select *
from service_ticket
where equipment_id=#id#
</cfquery>
OUTPUT SOME DATA
<!--- Update due date in the database for this machine --->
<cfquery name="dueDate#id#" datasource="#datasource#">
update equipment_maintenance
set maintenance_due_date = #dueDate#
where id = #id#
</cfquery>
OUTPUT SOME DATA
<cfquery name="get_history" datasource="#datasource#">
select *
from equipment_service_history
where equipment_id = #id#
</cfquery>
<cfquery name="get_history_ticket_detail" datasource="#datasource#">
select *
from closed_tickets
where equipment_id = #id#
order by ticket_id DESC
</cfquery>
OUTPUT SOME DATA
<cfloop query="get_history_ticket_detail">
OUTPUT SOME DATA
</cfloop>
</cfoutput>
There is a lot of HTML code in the middle for outputing my data, but that is the basic structure of my Coldfusion code.
I'm assuming that my multiple queries within my CFOUTPUT tag are what's causing the performance issues correct? How can that be fixed using QoQ?
-Brian
Here is an easy one to do. Change the update statement to
<cfquery datasource="#datasource#">
update equipment_maintenance
set maintenance_due_date = #dueDate#
where machine_type != 'unifi_site' AND machine_type != 'firewall' AND machine_type != 'dvr' AND machine_type != 'pbx' AND active = 'yes'
</cfquery>
There is no need to give it a name because it is not returning any data
I have written a database query to extract information in ColdFusion and I want to know how may I pass a value to the WHERE clause to get the relevant data. This is my code sample. can any one help?
<cfquery name="FILM_STRIP_QUERY" datasource="#dsn#">
select distinct tm.id as teachingmoduleid,
(select concat(prs.first_name, ' ',prs.last_name) AS Video_presenter from presentations pss
inner join topics tpcs on tpcs.id = pss.topic_id
inner join presenters prs on prs.id = pss.presenter_id
where pss.name = ps.name
and tpcs.title = tp.title
) AS video_presenter,
(select pss.43_png from presentations pss
inner join topics tpcs on tpcs.id = pss.topic_id
inner join presenters prs on prs.id = pss.presenter_id
where pss.name = ps.name
and tpcs.title = tp.title) AS png_name
from teaching_modules tm
inner join tm_segments sg on sg.module_id = tm.id
inner join topics tp on tp.id = sg.topic_id
inner join presenters prs on prs.id = tm.presenter_id
left outer join presentations ps on ps.id = sg.presentation_id
where tm.id =
</cfquery>
and this is the calling function
<cfloop = "FILM_STRIP_QUERY">
<!--- this is where I wanna pass the parameter--->
</cfloop>
Do you mean something like this?
<cfset tmId = 5 />
<!--- or something like <cfset tmId = url.id /> --->
<cfquery name="FILM_STRIP_QUERY" datasource="#dsn#">
<!--- SELECT cols FROM wherever etc... --->
WHERE tm.id = <cfqueryparam cfsqltype="cf_sql_integer" value="#tmId#" />
</cfquery>
You could just do #tmid# without the CFQueryParam tag, but it's a good idea to use it for added security (validation) and the database will also cache the execution plan, hopefully improving performance the next time the query executes.
If you are using a CFC, then a function like this would work, including the query name ensuring CF releases the memory from the local variable declaration. Also uses the parameter and the cfqueryparam function.
<cffunction name="getFILM_STRIP" access="public" returntype="query" output="false">
<cfargument name="id" required="Yes" type="numeric">
<cfset FILM_STRIP_QUERY = "">
<cfquery name="FILM_STRIP_QUERY" datasource="#variables.dsn#">
<!--- select statement --->
WHERE colname = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#arguments.id# />
</cfquery>
<cfreturn FILM_STRIP_QUERY>
</cffunction>
You should use the cfqueryparam tag to do this. This helps DB execution and also helps prevent SQL injection. e.g.
where tm.id = <cfqueryparam value="#form.ID#" CFSQLType="CF_SQL_INTEGER">
I'll explain the 'real life' application of this so it's easier to understand.
I'm working on an eCommerce app that has a category structure. It starts at the top level and gradually moves down through subcategories. For example Home > Electronics > TVs > Plasma
I'm using a single page for this, showing the 'home' page if no category is defined, the subcategories if there are any, and finally the products if there are no subcategories.
This all works fine, however when I get to the 2nd part - displaying subcategories, the page is a little empty. Therefore, I'd like to display a selection of products that span all of the subcategories applicable.
This is where I'm struggling - in most cases, there will be a few subcategories. However, I'm not sure how to structure the 'where' query using the results of the previous query (code snippets below for reference).
I don't believe QofQ would be worth exploring, and I've made a vain attempt at doing something with substrings, without success.
Any pointers much appreciated!
<cfquery name="getcategories">
SELECT p.ID AS CategoryID, p.Cat_Name as CategoryName, p.Cat_Shortname, c.ID AS SubCategoryID, c.Cat_Name as SubCategoryName, c.Cat_Shortname AS SubCatShortname
FROM product_categories p LEFT JOIN product_categories c ON p.ID = c.SubcategoryOf
WHERE p.SubcategoryOf = 0
</cfquery>
<cfif IsDefined('url.cat')>
<!--- Look for additional subcategories --->
<cfquery name="getsubcategories">
SELECT *
FROM product_categories
WHERE Subcategoryof='#url.cat#'
</cfquery>
<cfquery name="getproducts">
SELECT *
FROM products
WHERE categoryid='#url.cat#'
ORDER BY RAND()
</cfquery>
</cfif>
Assuming your products table contains a subcategoryID of some kind you can use the following to get a list of sub category IDs from the query getsubcategories:
<cfset subCategoryIDs = valueList(getsubcategories.subCategoryID) >
This will give you a list of all subCategoryIDs. You can the feed this into the getproducts query like so:
<cfquery name="getproducts">
SELECT *
FROM products
WHERE subCategoryID in (<cfqueryparam cfsqltype="cf_sql_integer" value="#subCategoryIDs#" list="true">)
ORDER BY RAND()
</cfquery>
You should always cfqueryparam your query parameters.
If i understand your database structure, this query should return all products in all subcategories.
<cfquery name="getallproducts">
SELECT *
FROM products p LEFT JOIN product_categories pc ON p.categoryID = pc.ID
WHERE pc.Subcategoryof= <cfqueryparam cfsqltype="cf_sql_integer" value="#url.cat#">
</cfquery>
note: you really do want to use cfqueryparam here.
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>