2016-10-18 6 views
0

SQLのテーブルに挿入する必要があるテキストファイルがあります。私は自分のテキストファイル名が格納されている別のテーブルを持っています。私はそのテーブルから名前をつかみ、特定のフォルダからファイルを取得するためにfileOpen()を使用しなければなりません。私がそのステップを完了した後、次のステップを行う最良の方法が何であるかを決めるのに問題があります。だから私はfileReadLine()各テキストファイルの行のコンテキストを取得するために使用する必要があります。また、最初の行には列名だけが含まれているので、これを読んではいけません。二番目に、ファイルの最後に一度着いたらチェックしなければなりません。最後に、テーブルにINSERTをループして実行する必要があります。私はこれを行うための新しい方法があるのだろうかと思っていましたか?現在のコードには2つのcfloopsがあり、非常に非効率的です。ここに私の現在のコードは次のとおりです。ColdFusionとSQLを使用してテキストファイルを挿入する最も良い方法は?

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

ほとんどのデータベースにはテキストファイルを読み込むためのツールがありますが、これは通常はループ処理よりもはるかに効率的です。これらのツールは、DBMS固有のものです。 MySQL - LOAD DATA、SQL Server - BULK INSERTなどで検索してください。たくさんの例があります。 (データベースに関する質問があれば、常にあなたのDBMSとバージョンが含まれています) – Leigh

答えて

2

ことはでき直接そのようなループファイルの行:あなたは本当にfileisEOF()関数を必要としないので、

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

ループは、ファイルの終わりで終了します。

ループ内では、配列をループするのではなく、リスト関数を使用できます。リスト内のアイテムの位置を知っている場合。このように:

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

これは単一ループになります。ファイルのサイズによっては、より効率的である場合とそうでない場合があります。また、通常、タイプ、ヌル、空の文字列のチェックがあります。そのようなものです。したがって、あなたの挿入の前にそのデータマッサージコードのいくつかを持っているかもしれません。お役に立てれば。

+1

ニースキャッチ ''私はこれを考えませんでした。 (何らかの理由で列の数が少なすぎる行のために 'ListLen()'チェックがうまくいくでしょう) – Tomalak

+0

@MarkAKruger上記のあなたの答えに関連する質問がもう少しあります。Replace()コードを削除してください?それはあなたのコードですでにどのようにして終わっていますか?また、listgetAt()を使うと、基本的に私のファイルから必要な要素の位置を指定するだけです。または、私はその仕組みを理解していませんでした...また、私のINSERT INTO ... cfloopの部分を移動して、VALUESの後ろにループを置く必要がありますか?私はそれが良いオプションかもしれないが、100%確実かもしれないと思いますか? –

+0

私は位置を指定するlistGetAt()をテストしていましたが、私はまだ列名を持つ最初の行を持っています。どのように私の.txtファイルから最初の行を取り除くことができますか?前もって感謝します。 –

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 *をしないでください。必要な列に名前を付けます。
  • 明らかにコメントしないでください。 "ファイルテーブルのものを掴む"は、まったく余計なコメントです。
  • 適切な変数名を使用してください。 filesは、myQuery1よりはるかに優れています。
  • を使用する必要はありません。可変コンテンツを文字列、CFタグ属性、または出力に内挿したい場合を除きます。

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

  • 質問には常に<cfqueryparam>を使用してください。この方法では、値の引用符を心配する必要はありません。それはまた、ループ内でより効率的です。
  • INSERTクエリは本当にあなた本当にがエラーを気にしない場合を除きname
  • <cfcatch>なし<cftry>を避ける必要はありません。
  • 最後に重要なことは、CSVは考えているよりも複雑な形式です。なんらかの理由でTABまたはNEWLINEが値の一部である場合(値が引用されている場合は有効)、「TAB文字で行を分割するだけです」は機能しません。 CSVパーサーを探してみてください(多分hereを起動してください)。
関連する問題