I have a list of question ids to be inserted into an answers table while adding records.
<!--- answers query --->
<cfquery name="answers">
SELECT answer, rank
FROM answers
WHERE question_id IN (<cfqueryparam cfsqltype="cf_sql_integer" list="true" separator="," value="#qid#">)
</cfquery>
the qid
is the list of old question id through which I am retrieving answers and then I am duplicating the same answers with newer question id.
<!--- list of questionids --->
<cfset questionid = ArrayToList(idArray)>
<cfquery name="insertanswers">
INSERT INTO answers (
question_id, answer, rank
)
VALUES
<cfloop query="answers">
(
<cfqueryparam cfsqltype="cf_sql_integer" list="true" separator="," value="#questionid#">
,<cfqueryparam cfsqltype="cf_sql_varchar" value="#answers.answer#">
,<cfqueryparam cfsqltype="cf_sql_numeric" value="#answers.rank#">
)
<cfif answers.CurrentRow LT answers.RecordCount>,</cfif>
</cfloop>
</cfquery>
While adding records I am getting column count doesn't match value count
error but when I wrap code with cftry
and dump it I found that it is getting two ids for each answer in form of comma delimited. Is there any way to pass only single id for each answer? I am just replacing the older question ids with newer one.
Since you need to link the old and new id's, you will need a different approach than the one used here. When you generate the new question records, store the id's in a structure, rather than an array, so you can maintain a mapping of old => new values.
<!--- initialize mapping of old => new ids -->
<cfset idMapping = {}>
<cfloop ...>
<!--- use the "result" attribute to capture the new id --->
<cfquery result="addRecord" ....>
INSERT INTO YourTable (...) VALUES (...);
</cfquery>
<!--- save the id in the array -->
<cfset idMapping[ oldQuestionID ] = addRecord.GENERATED_KEY>
</cfloop>
When you insert the new answers, use the old id to do a look up and grab the new question id from the structure. This needs validation, but here is the general idea.
Note: To ensure data integrity, both query blocks should be enclosed in a single <cftransaction>
<cfquery name="insertanswers">
INSERT INTO answers (
question_id, answer, rank
)
VALUES
<cfloop query="answers">
(
<!--- get the new id from the structure --->
<cfqueryparam cfsqltype="cf_sql_integer" value="#idMapping[ oldQuestionID ]#">
,<cfqueryparam cfsqltype="cf_sql_varchar" value="#answers.answer#">
,<cfqueryparam cfsqltype="cf_sql_numeric" value="#answers.rank#">
)
<cfif answers.CurrentRow LT answers.RecordCount>,</cfif>
</cfloop>
</cfquery>
Update 1:
Here is a complete example:
Update 2:
If this is a regular occurrence, I would suggests a different approach that would eliminate the looping. Add a UUID column to the main table (used to identify the new records). Then use a temp table (with an auto populating UUID column) to store the records you want to transfer. It is not as complicated as it sounds ..
(I do not have the MySQL syntax handy, so this is for SQL Server, but the overall concept is the same).
-- use DEFAULT to automatically generate a UUID for each record
CREATE TABLE #NewQuestions (
, OldQuestionID int
, TheUUIDColumn uniqueidentifier DEFAULT(NewID())
)
--- insert the records you want to transfer
INSERT INTO #NewQuestions ( OldQuestionID )
SELECT QuestionID
FROM Questions
WHERE .....
Next, use a JOIN to insert those questions back into the main table. Note, how it stores the UUID so we can identify the new records later.
INSERT INTO Questions( TheUUIDColumn, Question, ... )
SELECT tmp.TheUUIDColumn, q.Question, ....
FROM Questions q INNER JOIN #NewQuestions tmp
ON tmp.OldQuestionID = q.QuestionID
Finally, use the UUID to identify both the old and new id's and insert the related "answers".
INSERT INTO answers ( QuestionID, Answer, ....)
SELECT q.QuestionID, a.Answer
FROM Questions q
INNER JOIN #NewQuestions tmp ON tmp.TheUUIDColumn = q.TheUUIDColumn
INNER JOIN answers a ON a.QuestionID = tmp.OldQuestionID
The temp table approach offers greater control. It is also set based, which is much more efficient than processing one record at a time via a loop.