Coldfusion cfloop through checkboxes in a cfquery - mysql

I have had a good search through to see if there was something similar to what I am trying to do. Nothing specifically covers it though so without further ado.
I would like my cfloop to work through any of the checked boxes on a search page and display the appropriate results drawn from the database. This is what I have so far:
<cfquery name="joblibrary">
SELECT *
FROM tblJobLibraryRoles JOIN tblJobLibraryCategories
ON tblJobLibraryRoles.category = tblJobLibraryCategories.id
<cfloop list="#form.cbGrade#" index="i">
WHERE grade=<cfqueryparam cfsqltype="cf_sql_varchar" value="#i#"/>
</cfloop>
ORDER BY category, grade, title, heraRef;
</cfquery>
Now it works all fine if only one checkbox is ticked, so I am basically asking can I get this type of CFLOOP to work in the way I've created it, or am I barking up the wrong tree?

You don't need a loop. Just use the sql keyword "in".
where somefield in (
<cfqueryparam
cfsqltype="cf_sql_varchar" value="#form.checkboxfield#"
list="yes">
)
You just have to do something to contend with the situation where no boxes are checked.

IN () is certainly the way to handle this (works with other sql statements as well), but there may be times where you want multiple WHERE conditions that are all entirely defined by variables.
Again, IN () is the solution here, but I'll demonstrate with your query on how to do what you were originally wanting to do.
Simply add a WHERE 0=0 (or 1=1 or anystring=anysamestring. You could even say Where 'trickwhere'='trickwhere' but there's no reason to get wordy with it) and loop over the rest using an AND instead.
<cfquery name="joblibrary">
SELECT * from tblJobLibraryRoles JOIN tblJobLibraryCategories ON tblJobLibraryRoles.category=tblJobLibraryCategories.id
WHERE 0=0
<cfloop list="#form.cbGrade#" index="i">AND grade=<cfqueryparam cfsqltype="cf_sql_varchar" value="#i#"/></cfloop>
ORDER BY category, grade, title, heraRef;
</cfquery>

Related

When I enter a name in a form and that name already exists in a database, I want to give a message saying "This name already exists" using queries

I'm a beginner so I Want to know how you can check if a name already exist in the database and give an alert or a message saying the name already exist in the database
but i don't want to use jquery or js just cf and the queries.
<cfif isDefined("Button")>
<cfquery name='Insert' datasource='mysql'>
INSERT INTO tbl_products_manager
(Name)
VALUES ('#name#')
</cfquery>
<cfinclude template="pr.cfm">
</cfif>
I want to know what i should write in the next cfquery or to add the message
You can do:
<cfquery name='Insert' datasource='mysql' result='local.stResult'>
INSERT INTO tbl_products_manager
(Name)
VALUES (<cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#name#" />)
WHERE NOT EXISTS (SELECT 1 FROM tbl_products_manager WHERE Name = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#name#" />)
</cfquery>
Then you can dump local.stResult and figure out the result value that has the modified record count. (Can't remember offhand.) If the value is 0, you know it wasn't inserted.
As you indicate you are new to Coldfusion, please, please look up <cfqueryparam> and use it in every...single...query, every time.
The above is but one solution. You can also do a separate query first. Or you can have an identity (or MySQL equivalent) on the table and also get that in the stResult struct. There are a myriad of ways. Strenghten your sql-fu, and your CFML query/proc usage will get stronger, too!

Mysql getting wrong information from information_schema

Writing in Linux/Lucee and Coldfusion/Mysql. I have several databases in my system, with quite a few tables overlapping. I have a program which would add a field to a given table, say Activity, in each database. Of course I don't want to alter a non-existent table, so I am checking to make sure the table is there.
The simplest way would be to go to the database and use "show tables like 'Activity'". To do that in ColdFusion I used the datasource that belongs to that database. However, when I tried that, I got zero tables even when the table is present.
<cfquery name = 'tbl' datasource = '#thedatasource#'>
show tables like 'Activity'
</cfquery>
The record count for this query is zero. Then I tried using the information schema and got better results with this test program:
<cfquery name = 'dblist' datasource = 'Moxart'>
select MoxcoId from Moxco
</cfquery>
<cfloop query = 'dblist'>
<cfoutput>
<cfquery name = 'tbl' datasource = 'Moxart'>
select table_schema,table_name from information_schema.tables
where table_schema = '#MoxcoId#' AND table_name = 'Activity'
</cfquery>
<cfdump var = '#tbl#'>
</cfoutput>
</cfloop>
This gave exactly the right answer. However, when I put the same code into the real program, it keeps returning zero records. The real program is rather long, however most of the beginning consists of picking up info from the previous form . From the line
<cfquery name = 'dblist' datasource = 'Moxart'>
the only difference is the addition of this section because #MoxcoId# is not always the schema name. The variable #mmox# is in this case blank, so doesn't add anything.
<cfif #MoxcoId# EQ 'Moxart'>
<cfset pref = '#mmox#Moxware'>
<cfelse>
<cfset pref = '#mmox##MoxcoId#'>
</cfif>
When I do a dump on the query 'tbl' it shows that zero records were retrieved, even though the code appears to be exactly correct.
I am baffled. There must be something wrong in my code, but I just can't see it. If anyone can suggest something I would appreciate it.

Lucee need duplicate columns in SQL query

Programming in Lucee (Ubuntu, Firefox) and have a query in which I need duplicate columns. In generic SQL run from my terminal this produces exactly what I ask for. It works fine in ColdFusion. But when I run it in Lucee, it refuses to accept the request for the duplicate column.
<cfoutput>
<cfset mylist = "PersonFn, PersonLn, PersonState, PersonLn">
<cfquery name = "betty" datasource = "Moxart">
select #mylist#
from Person
limit 5
</cfquery>
</cfoutput>
When I get the columnlist for this Query, it has only 3 items in it, having eliminated the duplicate column. When I run a report against the output:
<cfset m = 0>
<cfoutput query = "betty">
<cfloop list = #mylist# index = "xxcol">
<cfset m = m + 1>
#betty[xxcol][currentrow]#
<cfif m EQ 4>
<br>
</cfif>
</cfloop>
</cfoutput>
I get this error:
key [ PersonLn] not found in query, columns are [PersonFn,PersonLn,PersonState]
I really, really need that duplicate column. Programming around this would be very difficult and excruciating.
I cannot use an alias, because the actual list is chosen by the user and there is no way to know what he might choose, or how many duplicates I might have. For similar reasons, I cannot reconstruct the data after the query to create the extra columns -- since I don't know what they are.
To be more exact, I probably can do those things, but the amount and complexity of programming is significant -- and all because Lucee just won't do what generic MySql will do.
Can anyone think of a way I can get those duplicate columns back into my output without major programming?
You can't have duplicate columns in sql you have to rename it to field1 and field2 for example.
What you seek violates the Sql standard.

Can I use MySQL "IN" with a list of strings in Coldfusion?

I'm trying to feed a variables into an MySQL query from Coldfusion. My query currently includes:
<cfif Session.app_assign EQ "0">
AND art.iln IN ( #Session.app_ilns# )
<cfelseif Session.app_assign EQ "1">
AND art.marke IN ( "#Session.app_keys#" )
</cfif>
Session.app_ilns will be a list of numbers like so: 1111111111111,2222222222222.... which works fine. Howerver, Session.app_keys will be list of strings, like:
sample_1, sample_2, sample_3
which will produce an error in my script, because of
unknown column "sample_1, sample_2, sample_3" in where clause.
Question:
Is there a way to use MySQL IN with a list of string values or do I need to pre-loop over the variables to add quotation marks. Are there any other ways to get this done?
Thanks!
Try using a cfqueryparam (good practice anyhow) with list="yes"
See this Ben Nadel blog post
Code would look like:
AND art.marke IN ( <cfqueryparam value="#Session.app_keys#" cfsqltype="cf_sql_varchar" list="yes" />)
Got it. I can set list="true" in cfqueryparam. See here

migrating ms access to mysql -- changing CF coding (from newbie)

I am migrating my coldfusion9 query code from ms access 2003 to mySql. My MySql knowledge is limited, so this is a beginner's question :)
In my MS Access code, I used simple cfqueries... here's an example:
<cfquery name="catalog" datasource="mydatasource">
SELECT TableID, DateListed, FirstColor, SecondColor
FROM mytable
WHERE FirstColor='blue' OR SecondColor='blue'
ORDER BY DateListed DESC
</cfquery>
I understand from online reading that one needs to use cfqueryparam with mySql to protect from injected malicious code. I'm not sure how the malicious code is injected .... as online website users don't interact with my database via forms, will I still need to use cfqueryparam?
If so, could you give me an example of an way to add cfqueryparam to the above code? -or- suggest a good, simple how-to resource for writing mySql code (in my searches online most of the coding info presupposes a higher level of knowledge than I have)
In addition to protecting from SQL injection, CFQUERYPARAM lets you use bind variables, which can give you performance gains because queries that are the same except for some variables only need to be compiled once and can be cached.
From your sample, this is how you'd used cfqueryparam:
<cfquery name="catalog" datasource="mydatasource">
SELECT TableID, DateListed, FirstColor, SecondColor
FROM mytable
WHERE FirstColor=<cfqueryparam cfsqltype="cf_sql_varchar" value="blue">
OR SecondColor=<cfqueryparam cfsqltype="cf_sql_varchar" value="blue">
ORDER BY DateListed DESC
</cfquery>
That doesn't buy you much, however. The payoff is in situations like this:
<cfquery name="catalog" datasource="mydatasource">
SELECT TableID, DateListed, FirstColor, SecondColor
FROM mytable
WHERE FirstColor=<cfqueryparam cfsqltype="cf_sql_varchar" value="#form.color#">
OR SecondColor=<cfqueryparam cfsqltype="cf_sql_varchar" value="#form.color#">
ORDER BY DateListed DESC
</cfquery>
Now whether the color is blue or red or chartreuse this query is compiled in the database and will be faster on subsequent calls. Further, a malicious user could change form.color to have the value of blue';drop table users; and you'll be protected from the SQL injection.
There are at least three good reasons to use cfqueryparam
1) Security from injection or other bad intent from users.
2) Queries execute faster because you explicitly state their type.
3) Its just a good idea, plus similar to other language features, like
$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);
We used examples like this all over of DAO objects (these are the cfcs that have the code in them that speak to the database)
<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#arguments.assessmentID# />
<cfqueryparam cfsqltype="CF_SQL_CHAR" value='%#arguments.searchString#%' />
<cfqueryparam cfsqltype="CF_SQL_DATE" value=#arguments.assessmentDate# />
Where the #arguments.varname# was passed into the method containing the SQL.