0

SQL のテーブルの 1 つに挿入する必要があるテキスト ファイルがいくつかあります。テキストファイル名が保存されている別のテーブルがあります。そのテーブルから名前を取得し、を使用しfileOpen()て特定のフォルダーからファイルを取得する必要があります。そのステップを終えた後、次のステップを実行する最善の方法は何かを決定する問題があります。したがってfileReadLine()、テキスト ファイルの各行のコンテキストを取得するために使用する必要があります。また、列名のみが含まれているため、最初の行を読むべきではありません。次に、ファイルの最後に到達したら確認する必要があります。最後に、ループしてテーブルに INSERT を実行する必要があります。これを行う新しい方法はありますか?私の現在のコードには 2 つ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

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 *。必要な列に名前を付けます。
  • 明らかなことをコメントしないでください。「ファイルテーブルから何かを取得する」は、まったく余計なコメントです。コードはそう言っています。
  • 適切な変数名を使用してください。filesよりもはるかに優れていmyQuery1ます。
  • 変数コンテンツを文字列、CF タグ属性、または出力に補間 する場合を## 除き、使用する必要はありません。

    <cfset line = #Replace(...)#>   <!--- useless use of ## --->
    <cfset line = Replace(...)>     <!--- much better --->
    
  • <cfloop list="">CSV ファイルから行をループするために使用できます。結局のところ、これは単純なリストです。

  • <cfqueryparam>クエリで常に使用します。このようにして、値の引用符について心配する必要はありません。また、ループ内ではより効率的です。
  • INSERT クエリは実際には必要ありませんname
  • エラーが本当に気にならない場合を除き、<cftry>なしは避けてください。<cfcatch>
  • 最後に、CSV は思ったよりも複雑な形式です。「タブ文字で行ごとに分割するだけ」は、何らかの理由で TAB または NEWLINE が値の一部である場合には機能しません (値が引用符で囲まれている場合は有効です)。CSV パーサーを探します (おそらくここから開始します)。
于 2016-10-18T14:36:15.493 に答える