1

私は検索してきましたが、これまでのところ、csvファイルに基づいてテーブルに日付を挿入する方法しか見つかりませんでした。

次のシナリオがあります。

ディレクトリ名=ticketID

このディレクトリ内には、次のようなファイルがいくつかあります。

  • Description.txt
  • Summary.txt -チケットヘッダーが含まれており、正常にインポートされています。
  • Progress_#.txt-これは、チケットが更新されるたびです。新しいファイルを取得します。
  • Solution.txt

Issue.txtこれは実際にはCSVであったため、インポートは簡単でした。

今私の問題は説明ファイルと進行状況ファイルにあります。

このファイルのデータで既存の行を更新する必要があります。のライン上の何か

update table_ticket set table_ticket.description = Description.txt where ticket_number = directoryname

私はPostgreSQLを使用していますが、COPYコマンドは新しいデータに対して有効ですが、'、;/特殊文字が原因で失敗します。

bashスクリプトを使用してこれを実行したかったのですが、それは不可能なようです。

for i in `find . -type d`
do
  update table_ticket 
  set table_ticket.description = $i/Description.txt
  where ticket_number = $i
done

もちろん、上記のコードはデータベースへの接続を考慮に入れます。

シェルスクリプトを使用してこれを実現する方法については、誰でも考えています。または、Javaで何かを作成し、レコードを読み取って更新する方がよいでしょうか。ただし、このアプローチは避けたいと思います。

ありがとうアレックス

4

3 に答える 3

5

答えてくれてありがとう、でも私はこれに出くわしました:

psql -U dbuser -h dbhost db 
\set content = `cat PATH/Description.txt`
update table_ticket set description = :'content' where ticketnr = TICKETNR;

これを簡単なスクリプトに入れて、次のように作成しました。

#!/bin/bash
for i in `find . -type d|grep ^./CS`
do
    p=`echo $i|cut -b3-12 -`
    echo $p
    sed s/PATH/${p}/g cmd.sql > cmd.tmp.sql
    ticketnr=`echo $p|cut -b5-10 -`
    sed -i s/TICKETNR/${ticketnr}/g cmd.tmp.sql
    cat cmd.tmp.sql
    psql -U supportAdmin -h localhost supportdb -f cmd.tmp.sql
done

欠点は、常に新しい接続が作成されることです。後で、単一のファイルを作成するように変更します。

しかし、それは私が探していたものを正確に実行し、内容を1つの列に収めます。

于 2013-03-25T07:40:53.183 に答える
2

psql大きなオブジェクトとして保存する場合を除いて、ファイルを直接読み込むことはできません。その場合は、を使用できますlo_importpsqlコマンドを参照してください\lo_import


更新:@AlexandreAlvesは、使用中にファイルコンテンツを実際に丸呑みできることを指摘しています

  \set myvar = `cat somefile`

次に、それを。でpsql変数として参照します:'myvar'。ハンディ。


シェルを使用してファイルを読み取ってフィードすることはpsql可能ですが、シェルはパラメーター化されたクエリをサポートするネイティブPostgreSQLデータベースドライバーもテキストエスケープ機能も提供しないため、せいぜい厄介です。あなたは逃げるあなた自身のひもを転がさなければならないでしょう。

それでも、入力ファイルのテキストエンコーディングが有効であることを知っておく必要があります。client_encodingそうしないと、ガベージを挿入したり、エラーが発生したりします。Python、Perl、Ruby、JavaなどのPostgreSQLと適切に統合することで、言語で簡単に実行できるようになります。

ただし、本当に必要な場合は、bashでやりたいことを実行する方法があります。SQLインジェクション攻撃を防ぐために、ランダム化された区切り文字でPgの区切られたドル引用符を使用します。完璧ではありませんが、かなり近いです。私は今例を書いています。


問題のあるファイルを指定します。

$ cat > difficult.txt <__END__
Shell metacharacters like: $!(){}*?"'
SQL-significant characters like "'()
__END__

およびサンプルテーブル:

psql -c 'CREATE TABLE testfile(filecontent text not null);'

あなたはできる:

#!/bin/bash
filetoread=$1
sep=$(printf '%04x%04x\n' $RANDOM $RANDOM)
psql <<__END__
INSERT INTO testfile(filecontent) VALUES (
\$x${sep}\$$(cat ${filetoread})\$x${sep}\$
);
__END__

これは少し読みにくいかもしれませんし、ランダムな文字列の生成はbash固有ですが、おそらく移植可能なアプローチがあると確信しています。

英数字(便宜上16進数を使用)で構成されるランダムなタグ文字列が生成され、に格納されseqます。

psql次に、引用符で囲まれていないヒアドキュメントタグを使用して呼び出されます。文字列内のシェルメタ文字を解釈しないよう<<'__END__'に指示するように、引用符がないことは重要ですが、プレーンではシェルがそれらを解釈できます。ヒアドキュメントに置き換える必要があるため、メタ文字を解釈するためのシェルが必要です。また、ファイルテキストを挿入するために(バッククォートと同等)を使用する必要があります。ヒアドキュメントタグは有効なPostgreSQL識別子である必要があるため、の各置換の前にあります。そのため、タグは数字ではなく文字で始まる必要があります。PostgreSQLのドル引用符はの形式であるため、各タグの最初と最後にエスケープされたドル記号があります。bash<<__END__sep$(...)xseq$taghere$quoted text$taghere$

bash testscript.sh difficult.txtしたがって、ヒアドキュメントが次のようなものに展開されるときにスクリプトが呼び出されると、

INSERT INTO testfile(filecontent) VALUES (
$x0a305c82$Shell metacharacters like: $!(){}*?"'
SQL-significant characters like "'()$x0a305c82$
);

タグは毎回変化するため、引用を途中で終了することに依存するSQLインジェクションのエクスプロイトは困難です。

それでも実際のスクリプト言語を使用することをお勧めしますが、これはそれが実際に可能であることを示しています。

于 2013-03-25T04:31:58.543 に答える
0

最善の方法は、一時テーブルを作成し、問題のファイルからそれらをコピーしてから、更新を実行することです。

2番目のオプションは、pl / perluのような言語で関数を作成し、これをストアドプロシージャで実行することですが、一時テーブルから更新するときに実行できるパフォーマンスの最適化の多くが失われます。

于 2013-03-25T04:31:13.397 に答える