0

これは私が今まで書いた中で最も醜いものですが、それ以外の方法がわかりません。問題は、反復を使用して別の場所から抽出された情報に依存するデータベースに SQL クエリを送信する必要があることです。

EG: ネストされた for ループを使用してデータを抽出できますが、SQL の挿入クエリを作成するには、行全体を元に戻す必要があります。セルのデータを一時的に変数に格納してそのようにしようとしましたが、それも見栄えが悪く、うまくいきませんでした。

ここに私が今使っているコードがあります:

怒らないでください。私はそれがひどいことを知っています。もっと上手になりたい。ちなみに、この行 (98 行目) は 1000 文字を超えるため、キロラインと呼んでいます。

$res1 = pg_query("INSERT INTO Project_Time_Sheet VALUES ('" . 
    $objWorksheet->getCellByColumnAndRow(0, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(1, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(2, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(3, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(4, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(5, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(6, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(7, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(8, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(9, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(10, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(11, $row)->getFormattedValue() . "', '" . 
    $objWorksheet->getCellByColumnAndRow(12, $row)->getFormattedValue() . "')");

これを行うためのより良い/よりエレガントな/愚かではない方法を教えてください。

4

4 に答える 4

3

そこで、このステートメントのアセンブリを直接改善してみます。これはあなたの質問に完全に答えるものではないかもしれませんが、少なくとも正しい道に進むはずです.

$res1 = pg_query("INSERT INTO Project_Time_Sheet VALUES ('" . $objWorksheet->getCellByColumnAndRow(0, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(1, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(2, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(3, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(4, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(5, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(6, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(7, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(8, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(9, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(10, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(11, $row)->getFormattedValue() . "', '" 
    . $objWorksheet->getCellByColumnAndRow(12, $row)->getFormattedValue() . "')");

さて、それは良く見えませんか?いいえ?もう少し恐ろしい?ごめん。

前提: 常に最初のパラメーターとして数値を呼び出します。常にgetCellByColumnAndRow1 で始まり、任意の時点で終了する可能性があります。そのようなSQLを構築する代わりに、ループを使用して最初にデータを収集します...

$max = 12;
$values = array();
foreach(range(1, $max) as $index)
    $values[] = "'" . $objWorksheet->getCellByColumnAndRow($index, $row)->getFormattedValue() . "'";

これで、アレイを接着することができます。

$sql = 'INSERT INTO Project_Time_Sheet VALUES(' . join(', ', $values) .')';

うーん。 getFormattedValueSQLセーフですよね?そうじゃなかったら?

まだまだ改良の余地ありです。PostgreSQL は準備済みステートメントをサポートしています。ここでそれらを使用するのが賢明かもしれません。

繰り返しますが、物事は適度に動的であるとやみくもに仮定しましょう。PHP の PG 拡張機能は非標準のプレースホルダーを使用しているため、私たちの生活はより困難になっています。データ収集に小さな変更を加えてみましょう。

$max = 12;
$values = array();
foreach(range(1, $max) as $index)
    $values[ '$' . $index ] = "'" . $objWorksheet->getCellByColumnAndRow($index, $row)->getFormattedValue() . "'";

PG のプリペアド ステートメント プレースホルダーを使用して、配列にキーが付けられるようになりました。

値の代わりにキーを使用して SQL を再構築します。

$sql = 'INSERT INTO Project_Time_Sheet VALUES(' . join(', ', array_keys($values)) .')';

$sql今のように見えます

INSERT INTO Project_Time_Sheet VALUES($1, $2, $3 ...);

準備して実行しよう!

$sth = pg_prepare($dbh, '', $sql);
$res = pg_execute($dbh, '', array_values($values));

プリペアド ステートメントでは、次の 2 つのことが得られます。

  1. SQL インジェクションに対する保護を追加し、
  2. ループで使用すると、パフォーマンスが向上する可能性があります。一度準備すれば、複数回実行できます。
于 2012-12-11T09:59:24.260 に答える
1

イテレーションを使用して複数のエントリを追加することは奇妙な要件ではなく、それ自体が醜いとは言えません。ただし、パラメータをエスケープしないため、セキュリティに問題があるようです。

プリペアドステートメントは実際にあなたが探しているものだと思います。それ以外の場合は、を使用しpg_query_paramsて少しクリーンにすることもできます(そしてはるかに安全です!):

<?php
$statement = "INSERT INTO Project_Time_Sheet VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13 );";

pg_query_params( 
    $connection, 
    $statement, 
    array(
        $objWorksheet->getCellByColumnAndRow(0, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(1, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(2, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(3, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(4, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(5, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(6, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(7, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(8, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(9, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(10, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(11, $row)->getFormattedValue(),
        $objWorksheet->getCellByColumnAndRow(12, $row)->getFormattedValue()
    )
);

値が増加するにつれて、代わりに小さなループが必要になる場合があります。

<?php
$statement = "INSERT INTO Project_Time_Sheet VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13 );";

for($i = 0; $i <= 12; $i++) {
    $values[] = $objWorksheet->getCellByColumnAndRow($i, $row)->getFormattedValue();
}


pg_query_params( $connection, $statement, $values );

しかし、私はこれが少し「においがする」ことを認めなければなりません。データベースを十分に正規化していないか、状況に応じてデータベースを正規化していない可能性がありますが、スキーマをもう一度確認してください。小さな間違いを犯した可能性があります。

于 2012-12-11T10:00:34.820 に答える
1

個人的には、配列とループを使用してそれを行います。

$values = array();
foreach (range(0, 12) as $i)
{
    $values[] = "'" . $objWorksheet->getCellByColumnAndRow($i, $row)->getFormattedValue() . "'";
}
$values = implode(', ', $values);
$sql = "INSERT INTO Project_Time_Sheet VALUES ({$values})";
于 2012-12-11T09:58:43.157 に答える
0

ループでクエリを完了してみませんか?例えば:

$query="INSERT INTO Project_Time_Sheet VALUES ('"; 
for($x=0; $x<$max;$x++){
    $query.=objWorksheet->getCellByColumnAndRow(0, $row)->getFormattedValue()."'";
    if($x<($max-1)){
          $query.=", '";
    }
}

$query.="');"
于 2012-12-11T10:01:52.910 に答える