I am trying to make a CF code that will select the row "welcome" from the table
"users" where username = #session.username#.
If "welcome" = 1 then i want it to direct the user to /me/index.cfm
I am new at CF, how would this be possible.
Firstly you need to do a DB query by the sounds of it:
<cfquery name="getWelcome" datasource="yourDSN">
SELECT welcome
FROM users
WHERE username = <cfqueryparam value="#session.username#" cfsqltype="CF_SQL_VARCHAR">
</cfquery>
Then you need to check the value from the query, and also taking into account the fact that the query might not find anything at all.
<cfif NOT getWelcome.recordcount>
<!--- do something, maybe redirect to the login page --->
</cfif>
<cfif getWelcome.welcome EQ 1>
<cflocation url="/me/index.cfm">
</cfif>
The most important thing here is the use of cfqueryparam to prevent SQL injection.
You can write like :
<cfif welcome EQ 1>
<cflocation url="/me/index.cfm">
</cfif>
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 am trying to set a variable dynamically into a structure via CFLOOP. I have read Ben Nadal's blog post but cant seem to get the assignment correct. I would like to use dot notation and make the VIN a sub structure of values.
Here is my code:
<cfloop query="VINs">
<cfquery name="carsQue" datasource="carsData">
SELECT VIN, MODEL, MAKE, etc
FROM CarsDB
WHERE (VIN = #VIN#)
</cfquery>
<cfset carsStruct= StructNew()>
<cfset carsStruct.[VIN].MAKE = '#carsQue.MODEL#'>
<cfset carsStruct.[VIN].MODEL = '#carsQue.MAKE#'>
</cfloop>
Any guidance would be greatly appreciated,
Thanks
Running a query inside a loop is almost always a bad idea. In your case, a better option would be:
<cfif ListLen(valuelist(vins.vin)) gt 0>
<cfquery name=CarsQue datasource = "carsData">
select vin, model, make, etc
from carsDB
where vin in (<cfqueryparam cfsqltype="cf_sql_varchar"
value="#valuelist(vins.vin)#" list="true">)
</cfquery>
<cfset carsStruct = StructNew()>
<cfloop query="carsQue">
code for your struct
</cfloop>
<cfelse>
code for vins query returning no data
</cfif>
Better yet would be to get all the data with one query. You didn't provide enough information to determine if this was possible, but it often is.
Create a structure outside loop and and setting variable within loop can solve the problem. in a current scenario each time loop run its create a new structure.
you can do some thing like this
<cfset carsStruct= StructNew()>
<cfloop query="VINs">
<cfquery name="carsQue" datasource="carsData">
SELECT VIN, MODEL, MAKE, etc
FROM CarsDB
WHERE VIN = <cfqueryparam cf_sql_type="cf_sql_varchar" value="#VINs.VIN#">
</cfquery>
<cfset carsStruct[VINs.VIN].MAKE = carsQue.MODEL>
<cfset carsStruct[VINs.VIN].MODEL = carsQue.MAKE>
</cfloop>
Based on the limited information you've given you should be able to run one query and loop through that to add to your struct.
<cfset carsStruct= {}> //new struct
<cfif VINs.RecordCount> //your VINs query has records
<cfquery name="carsQueue" datasource="carsData">
SELECT VIN, MODEL, MAKE, etc
FROM CarsDB
// Quoted list of all your VINs. cfqueryparam prevents against SQL injection
WHERE VIN IN (<cfqueryparam cf_sql_type="cf_sql_varchar" value="#ValueList(VINs.VIN)#" list="true">
</cfquery>
<cfloop query="carsQueue">
<cfset carsStruct.[carsQueue.VIN].MAKE = carsQueue.MODEL>
<cfset carsStruct.[carsQueue.VIN].MODEL = carsQueue.MAKE>
</cfloop>
<cfelse>
// if VINs query return nothing a blank struct will be returned.
//You do NOT need this <cfelse> unless you are returning something when the query is blank
</cfif>
I am trying to write a function for a survey where it pulls questions from a database. The catch is that there are both active and unactive questions. I need older questions to show up when someone views the results from an old survey.
Here is the code I am trying within a CFC:
<cffunction name="getAllQuestions" access="public" returntype="query">
<cfargument name="survey" default=0>
<cfif len(#survey#) gt 0>
<cfquery name="getsdate" datasource="blah.database">
select * from past_survey
where survey_id = #survey#
</cfquery>
<cfreturn getsdate>
</cfif>
<cfquery name="getquestions" datasource="blah.database">
select * from pool_questions
<cfif len(#survey#) eq 0>
where active_flag='Y'
<cfelse>
where <cfqueryparam value="#dateformat
(getsdate.survey_date, "yyyy/mm/dd")#"> BETWEEN start_date AND
end_date
</cfif>
order by qtn_nb
</cfquery>
<cfreturn getquestions>
</cffunction>
#survey# is the survey id which is generated by the form. What I am trying to do is that if survey has a value to run query getsdate. Then the second query would run no matter if survey has a value or not. If there is not value it should pull all active questions. If there is a value then it should check if the survey date is between the start date and end date for past questions.
Any advice on how to make this work would be greatly appreciated. Thank you in advance!
<cffunction name="getAllQuestions" access="public" returntype="struct">
<cfargument name="survey" required="true" default="0" type="numeric">
<cfset var qryReturn = ""> <!---Always var scope your variables to prevent them from leaking to other functions --->
<cfset var structReturn = structNew()>
<cfset structReturn.pastSurvey = "">
<cfset structReturn.surveyQuestions = "">
<cfif survey GT 0>
<cfquery name="qryReturn" datasource="blah.database">
SELECT *
FROM past_survey
<!--- Always cfqueryparam to prevent SQL injection attacks & also always reference the scope to prevent confusion --->
WHERE survey_id = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.survey#">
</cfquery>
<cfset structReturn.pastSurvey = qryReturn>
<cfelse>
<cfquery name="qryReturn" datasource="blah.database">
SELECT *
FROM pool_questions
<cfif arguments.survey EQ 0>
WHERE active_flag = 'Y'
<cfelse>
WHERE <cfqueryparam value="#dateformat
(getsdate.survey_date, "yyyy/mm/dd")#"> BETWEEN start_date AND
end_date
</cfif>
ORDER BY qtn_nb
</cfquery>
<cfset structReturn.surveyQuestions = qryReturn>
</cfif>
<cfreturn structReturn>
</cffunction>
You probably should be doing this in two separate functions, but I will attempt to answer your question.
My code will return a struct of queries (you can change to an array if you prefer) that returns a past survey and the survey questions
Note: In your example code, you have a few bad practices.
You are checking the length of the survey value rather than checking the value itself.
If you want to ensure that survey always has a value regardless of if it is passed or not, set requried=true and give it a default value.
Use cfqueryparam to prevent sql injection attacks
Any variables created in the function need to be var scoped to prevent them from leaking to other cffunctions in the same cfcomponent. I always do this at the top. Yes, even the name you give a cfquery needs to be var scoped.
Since you are doing a return after your first query, if the survey value is greater than 0 it will never get to the second query where it has the date check.
I see the following problems you need to address.
First, your survey argument has a default value of 0 and you are doing conditional logic on the length of it. The length of "0" is 1, so that condition will always return true.
Next, you state that you want the 2nd query to run whether the first one runs or not, but you refer to a value from the 1st query in the 2nd one. That means if the 1st query does not run, the 2nd one will crash due to an undefined variable.
Next, dateformat returns a string. Applying it the way you do in the 2nd query is at best unnecessary, and at worse, and indication that you are storing the start and end dates in pool_questions as strings. If you are attempting to strip out the time portion of the datefield in the first query, ColdFusion has a cast() function for that.
Also, scope your variables. ie - instead of <cfif len(survey), do this <cfif len(arguments.survey).
Also, var your local variables. In this case, it's the names of your two queries.
That should get you started.
Hi I am trying to build a query parameter dynamically, and am getting an error, i am using the code below,
<cfset featQuery="">
<cfloop list="#arguments.uid_features#" index="x">
<cfif x neq "0">
<cfif Len(featQuery) gt 0>
<cfset featQuery = featQuery& " AND ">
</cfif>
<cfset featQuery = featQuery & 'uid_prodf_featid = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="' & x & '">'>
</cfif>
</cfloop>
I get this error message from coldfusion;
[Macromedia][SQLServer JDBC Driver][SQLServer]Incorrect syntax near '<'.
If i look at the output, it looks correct, but normaly using cfquerypram, you just get (param1), uid_prodf_featid=(param1) in the error message it displays the following;
uid_prodf_featid = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="5">
Jason
You can't really build and execute CFML dynamically like you're attempting to do. It looks to me like you're trying to build a SQL query outside of a cfquery tag context; this would be fine, except for your need to parameterize it. If possible, change your code to run within a cfquery tag pair:
<cfquery...>
SELECT * FROM tableFoo
<cfif ListLen(arguments.uid_features)>
WHERE uid_prodf_featid IN (<cfqueryparam value="#arguments.uid_features#" list="true" cfsqltype="CF_SQL_INTEGER">)
</cfif>
</cfquery>
Also, as you can see I've changed your query structure a bit - you had a lot of code to do something that is much more easily accomplished as I show above.
edit
I see that you actually are doing AND operations with each item in your uid_features list... I have a hard time imagining there being a valid logical reason for that (rather than OR), but if so, my example won't work for that - instead change it back to a series of AND conditions within the loop.
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