how can I check if a record already in database before submitting form in ColdFusion applications - coldfusion

<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.

Related

ColdFusion cfset issue

I am new to ColdFusion. Anyone know why this code is not working. When I leave the form null it is not showing 100 in the database.
<cfif isdefined("FORM.Percentage")>
<cfset Form.Percentage = #Form.Percentage#>
<cfelse>
<cfset Form.Percentage = 100>
</cfif>
<cfquery name="percent" datasource ="abc">
Insert into Employees
(Percentage)
Values
(#Form.Percentage#)
</cfquery>
If you have a textbox it is submitted to the form even if it's left blank, so you want to check if the field was left blank. If it was then you can set the default.
You'll also want to do some server side validation that the value is a number and use cfqueryparam for inserting your value into the database.
<cfif NOT len(trim(FORM.Percentage))>
<cfset Form.Percentage = 100>
<cfif>
<cfquery result="percent" datasource="abc">
Insert into Employees (Percentage)
Values (
<cfqueryparam cf_sql_type="cf_sql_integer" value="#Form.Percentage#">
)
</cfquery>
When using cfquery with an INSERT the name attribute doesn't provide anything. Using result would allow you to view some data about the query if needed, but generally it shouldn't be used.
You could also have dumped form to the screen by using <cfdump var="#form#"> to see what it was returning. If you want to check that the key exists for a radio button or checkbox you can use structKeyExists(form,'myCheckbox') rather than using isDefined().

Check form submission against data in database?

We have a registration system that we're using where people fill out a form, and their info is put into our SQL database. However, we don't have a system in place to check for duplicate registrations, and I'm hoping to get some guidance on how to check maybe name or email address and set an error.
Here's our error setting code (one example, we have several checks):
<cfif not len(trim(form.last_name)) or form.last_name eq "Last Name">
<cfset errors = errors & "<li>You must include your complete last name.</li>">
</cfif>
If no errors are found, here is the query code to insert the data into the database:
<cfquery name="InsRegistrant" datasource="#application.Datasource#" dbtype="odbc">
INSERT INTO Schedule_Registrations(
schedule_id,
first_name,
last_name,
phone_number,
email,
guest,
list_type,
datetime_registered
)
VALUES(
#url.schedule_id#,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.first_name#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.last_name#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#CleanPhoneNumber#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.email#">,
#attendee.guest#,
<!--- Values for list types
0 = NEVER USE Will cause many many problems
1 = Main List
2 = Waiting List --->
#attendee.list_type#,
#createodbcdatetime(now())#
)
</cfquery>
There's no "unique" identifier tied to a specific individual, so I'm thinking the best way is to prevent registrations that match someone with an identical first/last name or even just the email address. Any ideas on how to implement such a function using the above system would be helpful.
This is simplified but.. you get the idea.
<cfquery name="RegistrantEmailExists" datasource="#application.Datasource#" dbtype="odbc">
SELECT COUNT(email) as EmailExists FROM Schedule_Registrations WHERE email = <cfqueryparam value="#form.email#" cfsqltype="cf_sql_varchar" >
</cfquery>
<cfif RegistrantEmailExists.EmailExists gt 0>
<cfset errors = errors & "<li>That Email Address already exists.</li>">
</cfif>
You could also set the email column in the database as a primary key, which would definitely prevent duplicate registrations. You would of course have to gracefully handle the duplicate primary key which would be thrown from the DB!
Placing a unique key on the mail-column would be the easier way than changing the primary key. But you've also to handle the error thrown by the db
<cfquery name="checkdup" datasource="whatever">
Select 1 from Schedule_Registrations where email=#form.email#
</cfquery>
<cfif #checkdup.recordcount# is 0>
<cfquery name="doyourquery" datasource="whatever">
insert into Schedule_Registrations
(email,etc1,etc2) values ('#form.email#','#etc1#','#etc2#')
</cfquery>
Thanks for registering
<cfelse>
You have already registered an account
</cfif>
And yes, all the cfqueryparam stuff you'd need would go in there. This is just the basics of it.
Good Luck :)
WHeis

CFQuery 'WHERE' from results of another query?

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.

can't define id ColdFusion

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>

Session Variables, welcome messages

Why does this not work? My welcome message, it just doesn't show up:
<p>Welcome <cfoutput>#Recordset1.UserID#</cfoutput>.</p>
The session variable on the login page I created is:
<cflock timeout=999 scope="Session" type="Exclusive">
<cfset Session.IDUsers =''>
</cflock>
is this incorrect? On the index page where I'm trying to display my welcome message I have:
<cfquery name="Recordset1" datasource="cfGossip">
SELECT *
FROM users
WHERE users.IDUsers = <cfqueryparam value="#Session.IDUsers#">
</cfquery>
I'm not sure if this works, or is necessary?
If you set the userid stored in the session to be the empty string, when you query on it, you will only get users for whom the id is the empty string, which shouldn't be any of them. Therefore, the query is returning an empty set, and your page is (correctly) not displaying a user id.
How are you initially identifying the user? Are you querying against a database when they log in? Are you storing a cookie? Reading Tarot cards? For this to work, at some point, you have to store the correct userid, probably in the session. To do that, you need to first identify who the user is.
Also, if you are using CF6+, you probably do not need the cflock. It is now used to prevent race conditions, as CF is now thread-safe.
Looks like you're just starting with CF, welcome to the community.
My understanding of your code makes the structure look like the following, if I'm understanding you correctly:
<cfset session.idUsers = '' />
<cfquery datasource = "cfgossip" name = "recordset1">
SELECT * FROM USERS WHERE USERS.ID_USERS = <cfqueryparam cfsqltype = "cf_sql_integer" value = "#session.idUsers# />
</cfquery>
<cfoutput>Welcome #recordset1.userID#</cfoutput>
The reason this doesn't work is because your session.idUsers value is blank. Assuming you have a user in your database with an ID_USERS value of 1, you could change the CFSET to look like and it should return results.
Additionally, while it's great to see you using CFQUERYPARAM, I'd recommend including a CFSQLTYPE attribute in the tag whenever possible to provide an added line of defense against injection attacks. You can check out http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_p-q_18.html to see the list of available types.
Is there anywhere in your code where you set your session.IDUsers? You initialize it as a blank ''. Coldfusion does not populate it for you. The session scope is a place that will remember things for that user that you put there for a specified period of time inactivity, usually 20 minutes. So hopefully, somewhere before you run your query you have additional logic that fills that in, otherwise you are asking the database for a user named, ''.
This is just a point of style, but the following may work better for you:
<cfset Session.IDUsers =''>
<!--- Do something here to populate Session.IDUsers --->
<!--- Creates a blank query - not necessary, but can reduce errors later --->
<cfset Recordset1 = queryNew("UserID")>
<!--- Populate the query from the database --->
<cfquery name="Recordset1" datasource="cfGossip">
SELECT *
FROM users
WHERE users.IDUsers = <cfqueryparam value="#Session.IDUsers#">
</cfquery>
<!--- If the query has data, use it, otherwise show generic message --->
<cfoutput>
<cfif Recordset1.recordcount>
<p>Welcome #Recordset1.UserID#.</p>
<cfelse>
<p>Welcome new user!</p>
</cfif>
</cfoutput>
<!--- OR since we used queryNew("userID"), we can simplify without throwing an error. ---->
<cfoutput>
<p>Welcome <cfif len(Recordset1.userID)>#Recordset1.userID#.<cfelse>new user!</cfif></p>
</cfoutput>
Putting the cfoutput outside the paragraph block will make it easier if you have additional variables to insert into the text. (but will work either way)
Regardless of all that, unless you forgot to share a bit more of the code, I think the issue is that the session.IDUsers is blank and needs to be populated before the query. I hope this helps!