0

我有一些文本文件必须插入到我的 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>

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

4

3 回答 3

1

您可以像这样直接循环文件行:

<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、空字符串——诸如此类。因此,您可能在插入之前有一些数据按摩代码。希望这可以帮助。

于 2016-10-18T14:34:36.080 回答
0

如果要向表中插入 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 字符处按行拆分”将不起作用。寻找 CSV 解析器(也许从这里开始)。
于 2016-10-18T14:36:15.493 回答
-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>
于 2020-10-01T16:52:48.280 回答