<cfquery name="getList" datasource="context"> select * from Item </cfquery> <form name="pick" action="form.cfm" method="post"> <table> <tr><td>EDIT</td><td>NAME</td><td>NUMBER</td><td>DELETE</td></tr> <cfoutput query="getList"> <tr> <td><input type="submit" name="editme" value="#ItemID#"> </td><td>#ItemName#</td><td>#ItemNo#</td> <td><input type="submit" name="delme" value="#ItemID#"></tr> </cfoutput> </table> </form>
This form also implements an insert function. If the mode is not update, the entry fields are pre-filled from an empty query to which an empty row has been appended using the QueryAddRow function.
Finally, the page returns to the URL in the "Return" variable, form.cfm in this case. If there was a problem with an insert, update, or delete attempt, the page performing that function will return the problem in a query string attached to the URL of this page. The "Problem", if any, will be displayed on this page. The exit button takes the user to a page you have defined. (It will fail if you don't define it.)
<!--- Respond to pick.cfm --->
<cfparam name="form.editme" default="">
<cfparam name="form.delme" default="">
<cfparam name="form.addme" default="do this">
<cfset Return="../work/form.cfm">
<cfparam name="url.Problem" default="">
<cfoutput>#Problem#</cfoutput><br>
<cfif len(form.editme)>
<cfset myaction="../querybin/chgitem.cfm">
<cfquery name="getItem" datasource="context">
select * from Item
where ItemID = <cfoutput>#form.editme#</cfoutput>
</cfquery>
EDIT <cfoutput>#form.editme#</cfoutput><br>
<cfelse>
<cfquery name="getItem" datasource="context">
select * from Item
where 1 = 0
</cfquery>
<cfset dummy=QueryAddRow(getItem)>
ADD<br>
<cfif len(form.delme)>
<cfinclude template="../querybin/delitem.cfm">
<cfset form.delme="">
<cfelseif len(form.addme)>
<cfset myaction="../querybin/additem.cfm">
</cfif>
</cfif>
<!--- Accept data for insert or update --->
<form name="myForm"
action=<cfoutput>"#myaction#"</cfoutput> method="post">
ItemName: <input type="text" name="ItemName"
value=<cfoutput>"#getItem.ItemName#"</cfoutput>
size="22" maxlength="20"><br>
ItemNo: <input type="text" name="ItemNo"
value=<cfoutput>"#getItem.ItemNo#"</cfoutput>
size="6" maxlength="5"><br>
<input type="button" name="dothis" value="Exit"
onClick="document.location='../yoursite.cfm'; return false;">
<input type="reset" name="dummy" value="Reset">
<input type="submit" name="dothis" value="Submit">
<input type="hidden" name="ItemID"
value=<cfoutput>"#getItem.ItemID#"</cfoutput>>
<input type="hidden" name="Return" value=<cfoutput>"#Return#"</cfoutput>>
</form>
<!--- Pick for update or delete --->
<hr>
<cfinclude template="pick.cfm">
The Table and Key names are readily passed in variables. The query can be stored in a string (named Core). Notice that this is straight SQL except for the ColdFusion variables and the question marks around ID1.
ID1 surrounded by question marks represents the value that WILL be used for the desired key but which is not yet defined and therefore should be treated as text now but as a variable later. Your support code will turn this into a ColdFusion variable and then fill in the key value it has obtained before it actually performs the insert.
Finally, this query document includes the page that contains the support code for the kind of action being performed: insert, update, or delete. In this case, it's insert, to be performed by add.cfm.
<cfset TableName="Item"> <cfset KeyName="ItemID"> <cfset Core="insert into #TableName# (#KeyName#, ItemName, ItemNo) values (?ID1?, '#form.ItemName#', '#form.ItemNo#')"> <cfinclude template="../querybin/add.cfm">
<cfset Core="update Item set ItemName = '#trim(form.ItemName)#', ItemNo = '#trim(form.ItemNo)#' where ItemID = #form.ItemID#"> <cfset QueryName="chgItem"> <cfinclude template="../querybin/chg.cfm">
<cfset Core="delete from Item where ItemID = #form.delme#"> <cfinclude template="../querybin/del.cfm">
The general idea in this demo is that a query in the support code goes after the highest key value currently used and stores the next available value in the variable ID1, which is then used as the key in the insert query.
There are two important differences between hard-coding the query within this structure and using a query stored in a string. For insertion, after you determine the key value to be used, you need to convert the text representing that value (?ID1? in this case) to a ColdFusion variable that will carry the key value into the query. The string "?ID1?" must be changed to "#ID1#" where it appears in the insert query. The conversion must take place after ID1 is defined; that's why ID1 can't be specified as a variable when the core query is first written. The second difference holds true for all queries stored in a string: the preserveSingleQuotes function must be used to avoid dropping the single quotes from the query.
Here's what the result looks like. Notice that it contains no table-specific code and can be used to support any single-key insert query. Call it add.cfm and put it in the querybin directory.
<!--- Begin the loop ---> <cfset try=0> <cfloop condition="try lt 4"> <cfset try=try+1> <cfset Qstring=""> <cftry> <cftransaction> <cfset Qerr=0> <!--- (no error yet) ---> <!--- Get next ID for single-element key ---> <cfquery name="getMax1" datasource="context"> select max(#KeyName#) as Max1 from #TableName# </cfquery> <cfif len(getMax1.Max1)> <cfset ID1=getMax1.Max1+1> <cfelse> <cfset ID1=1> </cfif> <!--- Try to add the row ---> <cfset Core1=replaceNoCase(Core,"?ID1?","#ID1#")> <cfquery name="add" datasource="context"> <cfoutput>#preserveSingleQuotes(Core1)#</cfoutput> </cfquery> </cftransaction> <!--- Exit here when OK ---> <cfbreak> <!--- Retry up to max times ---> <cfcatch type="database"> <cfif try gt 3> <cfset Qstring="?Problem=Repeatedly failed to add to database; try again later or notify maintenance."> <cfbreak> </cfif> </cfcatch> </cftry> </cfloop> <cfset myURL="#Return##Qstring#"> <cflocation url="#myURL#">
<!--- Begin the loop ---> <cfset try=0> <cfloop condition="try lt 4"> <cfset try=try+1> <cfset Qstring=""> <cftry> <cftransaction> <cfset Qerr=0> <!--- (no error yet) ---> <!--- Try to change the row ---> <cfquery name="#QueryName#" datasource="context"> <cfoutput>#preserveSingleQuotes(Core)#</cfoutput> </cfquery> </cftransaction> <!--- Exit here when OK ---> <cfbreak> <!--- Retry up to max times ---> <cfcatch type="database"> <cfif try gt 3> <cfset Qstring="?Problem=Repeatedly failed to change database; try again later or notify maintenance."> <cfbreak> </cfif> </cfcatch> </cftry> </cfloop> <cfset myURL="#Return##Qstring#"> <cflocation url="#myURL#">
<!--- Begin the loop ---> <cfset try=0> <cfloop condition="try lt 4"> <cfset try=try+1> <cfset Qstring=""> <cftry> <!--- Try to delete the row ---> <cfquery name="del" datasource="context"> <cfoutput>#preserveSingleQuotes(Core)#</cfoutput> </cfquery> <!--- Exit here when OK ---> <cfbreak> <!--- Retry up to max times ---> <cfcatch type="database"> <cfif try gt 3> <cfset Qstring="?Problem=Repeatedly failed to delete from database; try again later or notify maintenance."> <cfbreak> </cfif> </cfcatch> </cftry> </cfloop> <cfset myURL="#Return##Qstring#"> <cflocation url="#myURL#">