1

しばらく前に、isql を使用してテキスト フィールドに値を挿入する方法を探していたところ 、最終的にうまくいくロード コマンドを見つけました。

Perl から実行しようとすると動作しません。構文エラーが発生します。私は2つの別々の方法を試しましたが、どちらも今のところうまくいきません。

各ループ サイクルの最後に SQL ステートメント変数を出力するので、構文が正しいことはわかっていますが、正しく理解できていません。

私がテストしていたコードの最新のスニップは次のとおりです。

foreach(@files)
{

$STMT = <<EOF;
load from $_ insert into some_table
EOF

$sth = $db1->prepare($STMT);
$sth->execute;

}

@files要素がパイプ区切りのテキスト ファイルのフル パス/場所である配列 (例: /home/xx/xx/xx/something.txt)

テーブル内の列の数はテキスト ファイル内のフィールドの数と一致し、型チェックは問題ありません (テスト ファイルを手動でロードしたことは間違いありません)。

私が返すエラーは次のとおりです。

DBD::Informix::db prepare failed: SQL: -201: A syntax error has occurred.

何がこれを引き起こしているのでしょうか?


RETとPetrの回答を編集

$STMT = "'LOAD FROM $_ INSERT INTO table'";
    system("echo $STMT | isql $db")

die コマンドは不自然な死を強制し、ステートメントを単一引用符で囲む必要があったため、これに変更する必要がありました。

4

4 に答える 4

2

Notes/load.unloadこのファイルは DBD::Informix とともに配布され、Perl、DBI、および DBD::Informix を使用して UNLOAD 操作を処理する方法に関するガイドラインが含まれていることに注意してください。残念なことに、LOAD セクションに「TBD」(多かれ少なかれ) と表示されています。

他の人が述べているように、LOAD ステートメントと UNLOAD ステートメントは、さまざまなクライアント側ツールによって SQL ステートメントのように偽装されていますが、Informix サーバーはそれら自体をサポートしていません。これは主に、クライアント マシンからファイルを取得する際の問題 (おそらくPC) をサーバーマシン (おそらく Solaris マシン) に接続します。

LOAD ステートメントをシミュレートするには、パーツを分析する必要がありますINSERT INTO Table。列 ( ) がリストされている場合INSERT INTO Table(Col03, Col05, Col09)、ロード データ ファイルには 3 つの値があり、これらの 3 つの列に入力されます。列の型を取得するには、ステートメント ' SELECT Col03, Col05, Col09 FROM Table' を準備します。それ以外の場合は、ステートメント ' SELECT * FROM Table' を準備して、列 (およびその型) の完全なリストを取得する必要があります。列名と列数を指定すると、適切な挿入ステートメント ' INSERT INTO Table(Col03, Col05, Col09) VALUES(?,?,?)' または ' INSERT INTO Table VALUES(?,?,?,?,?,?,?,?,?)' を作成して準備できます。2 番目の列名に列名を含めることができます (ほぼ間違いなくそうすべきです)。

これで、アンロードされたデータを解析できました。IIUG Software Archiveから入手できる SQLCMD プログラムで入手できるドキュメントがあります(これは、Microsoft の同名の新興プログラムよりもずっと前から存在しています)。これは、UNLO​​AD 形式をかなり詳細に説明しています。Perl には、Informix が使用するあらゆるものを処理する機能がありload.unloadます。DBD::Informix で配布されるファイルの UNLOAD 情報を確認してください。

于 2009-10-04T01:30:06.020 に答える
2

これは、クエリが SQL クエリではなく、入力ファイルを解析して INSERT ステートメントを生成するように isql に指示する isql コマンドであるためです。

考えてみると、サーバーはまったく別のマシンにある可能性があり、どのファイルについて話しているのか、どのようにアクセスするのかわかりません。

したがって、基本的に2つのオプションがあります。

  1. isql を呼び出し、それに LOAD コマンドをパイプします - 非常に醜いです
  2. 自分でファイルを解析し、INSERT ステートメントを生成する
于 2009-10-02T19:53:28.250 に答える
2

Petr の言うとおりです。LOAD ステートメントは ISQL または DB-Access 拡張であるため、DBI を介して実行することはできません。マニュアルを見ると、SPL、ESQL/C などの構文も無効であることがわかります。

スクリプトを実行するために perl を使用する必要があるのか​​、それとも perl は単に SQL を生成する便利な方法なのかは明らかではありません。

前者で、純粋な perl メソッドが必要な場合は、INSERT ステートメントを準備し (テーブルが 1 つだけ含まれているように見えますか?)、ファイルをすする必要がありますsplit。準備されたインサート。

それ以外の場合は、perl を使用して SQL を生成しsystem、シェル スクリプトまたは DOS バッチ ファイルで直接、または両方をラップすることにより、DB-Access を介して実行できます。

システムコールバージョン

foreach (@files) {
    my $stmt = "LOAD FROM $_ INSERT INTO table;\n";
    system("echo $stmt | dbaccess $database")
            || die "Statement $stmt failed: $!\n";
}

バッチ スクリプト バージョンでは、すべての SQL を 1 つのスクリプトに書き込むことができます。つまり、次のようになります。

perl -e 'while(@ARGV){shift; print "LOAD FROM '$_' INSERT INTO table;\n"}' file1 [ file2 ... ] > loadfiles.sql
isql database loadfiles.sql

NB、ファイル名の引用符に関するコメントは、ファイル名にスペースまたはメタ文字が含まれている場合にのみ関連します。これは通常の問題です。

また、isql と dbaccess の動作における重要な違いの 1 つは、この方法で実行すると、dbaccess はエラーで停止せず、isql は停止することです。エラー時に dbaccess の処理を​​停止するには、環境で DBACCNOIGN=1 を設定します。

お役に立てば幸いです。

于 2009-10-03T06:58:19.070 に答える
1

少しグーグルで調べてみると、load の構文でファイル名が引用符で囲まれていることがわかりました。ステートメントを次のように変更するとどうなりますか。

load from '$_' insert into some_table

あなたのステートメントはプレースホルダーを使用していないので、DBI の引用機能を使用するのではなく、自分で引用符を付ける必要があります。

于 2009-10-02T19:29:19.060 に答える