如何在添加记录时插入ID列表?

时间:2013-08-30 15:10:36

标签: mysql coldfusion

我有一个问题ID列表,可以在添加记录时插入答案表。

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

qid是我正在检索答案的旧问题ID列表,然后我使用较新的问题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>

在添加记录时我收到column count doesn't match value count错误但是当我用cftry包装代码并转储它时,我发现它以逗号分隔的形式为每个答案获取两个ID。有没有办法只为每个答案传递单个ID?我只是用较新的问题替换旧的问题ID。

1 个答案:

答案 0 :(得分:1)

由于您需要链接旧ID和新ID,因此您需要采用与the one used here不同的方法。生成新问题记录时,将id存储在结构中,而不是数组中,这样就可以维护old =&gt;的映射。新的价值观。

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

当您插入新答案时,请使用旧ID进行查找并从结构中获取新的问题ID。这需要验证,但这是一般的想法。

注意:为确保数据完整性,两个查询块都应包含在一个<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>

更新1:

这是一个完整的例子:

更新2:

如果这是经常发生的话,我会建议采用不同的方法来消除循环。将UUID列添加到主表(用于标识新记录)。然后使用临时表(带有自动填充UUID列)来存储要传输的记录。它并不像听起来那么复杂。

(我没有方便的MySQL语法,所以这适用于SQL Server,但整体概念是相同的。)

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

接下来,使用JOIN将这些问题重新插入主表。请注意,它如何存储UUID,以便我们以后可以识别新记录。

    INSERT INTO Questions( TheUUIDColumn, Question, ... )
    SELECT  tmp.TheUUIDColumn, q.Question, ....
    FROM    Questions q INNER JOIN #NewQuestions tmp 
                 ON tmp.OldQuestionID = q.QuestionID

最后,使用UUID识别两者旧ID和新ID,并插入相关的“答案”。

    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

临时表方法提供更好的控制。它也是基于设置的,它比通过循环一次处理一个记录更有效。