2

私のプログラムではトランザクションを使用していないので、すべてのデータベース操作がすぐにコミットされると考えていました。

テーブル内の値を探しているphpプログラムがあり、見つかった場合はIDを返します。見つからない場合は、新しい行を書き込みます。後でそれが繰り返され、挿入したばかりのデータが見つかるはずですが、見つからないため、重複エラーが発生します。

その挿入後に有効な結果が返されるように、mysql にデータを強制的に書き込むにはどうすればよいですか? テーブルをフラッシュしようとしましたが、結果は変わりませんでした。

詳細:

mysql の一般的な問題だと思っていましたが、Cakephp の Model Query の使用に関連しているようです。

コントローラーを使用して CSV ファイルを複数のテーブルに解析しているため、モデルをオンザフライでバインドし、クエリ呼び出しを使用してデータをテーブルに挿入します。私はアプリケーションの残りの部分に CakePHP を使用していますが、解析機能は一種の使い捨て機能であるため、エレガントにするために多くの時間を費やしませんでした。

インポート モデルには関連付けられたテーブルがないため、追跡モデルに手動でバインドします。

関連するクエリへのコードの言い換え:

    $this->Import->bindModel(array('hasOne' => array('Tracking')));

    $insert =<<<DONE
INSERT INTO tracking (id, created, employee_id, client_id, borrower_name, loan_number,
                  loan_amount, activity_id, program_id, rate_id, lock_period,
                  lo_price, investor_price,  committed_price, purchase_advice_price,
                  lock_type, investor_id, time_taken, notes,audited,audit_notes,
                  import_notes, import_error, uniqueness)
                  VALUES (NULL, '%s', %d,  %d,  '%s', '%s',
                          %.2f, %d, %d,  %d, %d,
                          %.5f, %.5f, %.5f, %.5f,
                          %d, %d, %d, '%s', %d, '%s',
                          '%s', %d, %d)
DONE;
while ($row = fgetscsv($fh))
    # Lots of processing deleted

    if (! $this->_exists($row))
    {
       $sql = vsprint($insert, $row);
       $this->Import->Tracking->query($sql); # This is where I'll get a duplicate error
    }
} # end of function

# I've created a unique index on columns that should be unique and I do the query on    
# them here.
private _exists($mydata)
{
       $find = "SELECT id FROM tracking WHERE created = '%s' AND employee_id = %d" AND
            activity_id = $d AND ...";
       $sql = sprintf($find, $mydata[0], $mydata[1]);
       return $this->Import->Tracking->query($sql);
}

そのため、問題は Cakephp であり、モデル クエリで何をしているようにも見えます。

おそらく、このコードを Cake からヤンクしてスタンドアロンの php プログラムを使用できますが、すでに Cakephp を使用していたので、そこにインポート モデルを投入することにしました。

追加コメント:選択は正しいですが、長いので逐語的に転記しませんでした。省略記号を使用してそれを示しました。mysqlセッションにコピー/貼り付けしてデータを選択できるため、機能します。2回目に実行すると、データが見つかります。

コントローラーを終了するまでコミットされない大きなトランザクションに Cakephp が全体をラップしている可能性があると、他の誰かに思われますか? 2回目の実行でそれらの行が見つかる理由を説明していませんか?

Cakephp にこれらの挿入をコミットさせる方法を理解する必要があると思います。または、これに Model->query を使用して別の方法で行うべきではないか、プロジェクトのこの部分に Cakephp を使用しないでください。

====

ありがとう!

4

5 に答える 5

1

CakePHP 2.5.5 では、将来の参考のために (自分自身でも、解決策を忘れて将来自分の答えを見つけたら... こんにちは!)、わかりました、この問題はクエリキャッシュが原因です。修正:

$this->Import->Tracking->query($sql, false);

falseパラメータを追加すると、クエリ キャッシュがオフになります。メソッドに関するコメントを読んでください http://api.cakephp.org/2.5/source-class-Model.html#3363-3366

于 2015-05-20T01:41:37.387 に答える
0

テーブルに制約がある場合UNIQUE(コードのコメントから、そうであることがわかります)、単に使用できますINSERT IGNORE

INSERT IGNORE INTO tracking (...)
VALUES (...)

SELECTこれは、前に行う必要性を明らかにしINSERTます。


考慮すべきもう 1 つのオプションは、CSV ファイルの処理方法を次のように変更することです。

  1. データのインポートに必要なすべての列 (できれば type VARCHAR) と auto_incremented id フィールドを含む、制約のないステージング テーブルを作成します。
  2. LOAD DATA INFILE最も効率的な方法でCSVファイルをステージングテーブルにロードするために使用します
  3. すべての SQL ツールを使用して、ステージング テーブル内のデータを簡単にクリーンアップ、正規化、変換、参照テーブルおよびファクト テーブルと比較して検証できるようになりました。
  4. スタギング テーブルからファクト テーブルにデータを挿入する
  5. ステージング テーブルを切り捨てる

p3-5 をストアド プロシージャにラップすることもできます。これにより、クライアント側のコードをさらに合理化できます。

于 2013-07-27T07:02:17.477 に答える
0

LAST_INSERT_ID() を探している可能性があります

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

于 2013-07-26T21:56:41.293 に答える
0

あなたの $find は有効な文字列ではありません:

   $find = "SELECT id FROM tracking WHERE created = "%s" AND employee_id = %d" AND activity_id = $d AND ...";
   //                                               ^ this is terminating the string

これを一重引用符で囲んでリテラル文字列にする必要があります。そのようです:

   $find = 'SELECT id FROM tracking WHERE created = "%s" AND employee_id = %d" AND activity_id = $d AND ...';

または、文字列内の引用符をエスケープします (ただし、この場合になぜそうするのかはわかりません)。

   $find = "SELECT id FROM tracking WHERE created = \"%s\" AND employee_id = \"%d\" AND activity_id = $d AND ...";
于 2013-07-26T23:01:31.533 に答える
0

私が遭遇したのは、CakePHP が Query メソッドで行うことだったと思います。その場でモデルへの関連付けを作成し、組み込みのモデル保存メソッドを使用するようにコントローラーを再コーディングしました。

コーディングが増えたとしても、それはより洗練されたソリューションでした。また、CakePHP の内部を掘り下げて、クエリ メソッドが何をしているかを理解する必要もありませんでした。

みんなのアイデアをありがとう!

于 2013-08-20T17:19:23.777 に答える