使用ColdFusion& amp;插入文本文件的最佳方式SQL?

时间:2016-10-18 13:52:21

标签: sql coldfusion cfloop

我有一些文本文件,我必须在SQL的一个表中插入。我有单独的表,其中存储了我的文本文件名。我必须从该表中获取名称,然后使用fileOpen()从特定文件夹中获取文件。在我完成该步骤之后,我有问题来决定进行后续步骤的最佳方法是什么。所以我必须使用fileReadLine()来获取每个文本文件行的上下文。此外,我不应该读第一行,因为它只包含列名。其次,我必须检查一旦我到达文件的末尾。最后,我必须循环并将INSERT插入表中。我想知道有没有新方法这样做?我当前的代码有两个cfloops,看起来非常低效。这是我目前的代码:

<!--- Grab stuff from File Table.  --->
<cfquery datasource="test" name="myQuery1">
    SELECT * 
    FROM FilesTxt
</cfquery> 

<cfloop query="myQuery1"> 
    <!--- Read File --->
    <cfset dataFile = fileOpen(here is my path&"\"&#FileName#, "read" ) /> 
    <cfset line = fileReadLine( dataFile ) />

    <!--- Loop to see if hit the end of file, if not, read next line --->
    <cfloop condition="!fileIsEOF( dataFile )">
        <cfset line = fileReadLine( dataFile ) />

        <cfif trim(line) NEQ "">
           <cfset line = #Replace(line,"'","","ALL")#>
           <cfset line = #Replace(line,'"',"","ALL")#>
           <!--- Build array of junk in the file --->
           <cfset sList = ListToArray(line, chr(9),'yes')>

           <cftry>
                <cfquery datasource="test" name="Insert">
                //Here is my Insert statement
                </cfquery>
           </cftry>
        </cfif>
    </cfloop>
</cfloop>

我正在考虑做一个单独的循环,它将创建包含应插入的所有元素的数组,然后运行另一个循环来执行插入。我不确定在这种情况下最好的方法是什么。如果有人知道其他任何方式,请告诉我。感谢

3 个答案:

答案 0 :(得分:2)

您可以直接循环文件行:

<cfloop file="**path/filename**" index="LineOfMyFile">
    <cfoutput>#LineOfMyFile#</cfoutput> 
</cfloop>

循环终止于文件末尾,因此您不需要fileisEOF()函数。

在循环中,您可以使用列表函数而不是循环遍历数组。如果您知道列表中项目的位置。像这样:

<cfloop file="**path/filename**" index="LineOfMyFile">

    <cfquery name="myinsert" datasource="#blah#">
        INSERT INTO myTable (col1, col2, col3)
        VALUES (<cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#listgetat(lineOfMyFile,1,char(9))#">,
                <cfqueryparam cfsqltype="CF_SQL_CHAR" value="#listgetat(lineofmyFile,2,char(9))#">,
                <cfqueryparam cfsqltype="CF_SQL_CHAR" value="#listgetat(lineofMyFile,3,char(9))#">)
    </cfquery>

</cfloop>

这将是一个循环。根据文件的大小,它可能会更高效,也可能不会更高效。此外,通常会检查类型,null,空字符串 - 类似的东西。因此,在插入之前,您可能会有一些数据按摩代码。希望这会有所帮助。

答案 1 :(得分:1)

如果要在表中插入100,000个值,则无法生成100,000个INSERT语句。

专业的数据库专有工具或命令可以以更优化的方式完成,但我个人认为嵌套循环并没有太大的错误。

<cfquery name="files" datasource="test">
    SELECT FileName FROM FilesTxt
</cfquery> 

<cfloop query="files">
    <cfset file = fileOpen("here is my path\#FileName#", "read")>
    <cfset fileReadLine(file)>

    <cfloop condition="not fileIsEOF(file)">
        <cfloop list="#fileReadLine(file)#" delimiters="#Chr(9)#" index="item">
           <cftry>
                <cfquery datasource="test">
                    INSERT testTable (testColumn) VALUES (
                        <cfqueryparam value="#Trim(item)#" cfsqltype="CF_SQL_VARCHAR">
                    )
                </cfquery>
           </cftry>
        </cfloop>
    </cfloop>
</cfloop>

注意:

  • 不要SELECT *。为您需要的列命名。
  • 不要评论明显的。 “从文件表中获取内容”是一个完全多余的评论,代码说明了这一点。
  • 使用正确的变量名称。 filesmyQuery1好得多。
  • 除非要将变量内容插入字符串,CF标记属性或输出中,否则无需使用##

    <cfset line = #Replace(...)#>   <!--- useless use of ## --->
    <cfset line = Replace(...)>     <!--- much better --->
    
  • 您可以使用<cfloop list="">循环CSV文件中的一行。毕竟,这是一个简单的清单。

  • 始终在查询中使用<cfqueryparam>。这样您就不必担心值中的引号。它在循环中也更有效。
  • INSERT查询实际上不需要name
  • 避免<cftry>没有<cfcatch>,除非您确实不关心错误。
  • 最后,但并非最不重要:CSV是一种比人们想象的更复杂的格式。 “当TAB或NEWLINE由于某种原因(如果引用该值时有效),TAB或NEWLINE是该值的一部分时,”仅在TAB字符处按行拆分“将不起作用。四处寻找CSV解析器(可能会启动here)。

答案 2 :(得分:-2)

所有这些答案都是错误的。如果要插入一堆值,请使用SQL BULK INSERT

<cfset myInserts = "">
<cfloop file="test" index = "line">
   <cfset myInserts = listAppend(myInserts,"(#line#)">
</cfloop>
<cfquery>
INSERT INTO myTable VALUES #preserveSingelQuotes(myInserts)#
</cfquery>