web-dev-qa-db-ja.com

条件付きでINSERT OR SQLiteの行を置き換える方法は?

_on_conditionを挿入または置換したいと思います。条件が満たされない場合は、挿入または交換しないでください。これは可能ですか?

私のプロジェクトでは、現在2つのデータ収集プロセスがあります。 1つは高速ですが、すべてをキャッチするわけではありません。もう1つは遅いですが、すべてをキャッチします。高速プロセスにより、ほぼリアルタイムでデータを取得できます。遅いものでは、一日の終わりにバッチプロセスを使用してデータを取得します。

私の問題はこれです:時々、速いプロセスは遅いプロセスの前にレコードを「完了する」(つまり、更新する必要がない)、そして夜のバッチプロセスの後半に、「完了」レコードはに置き換えられます遅いプロセスのバルクデータで見つかった古い「保留中」のレコード。

私が欲しいのは、次の擬似コードのような条件チェックです。

If(record_is_not_complete or does_not_exist) 
{ INSERT or REPLACE; }
Else 
{ do_nothing and move_to_the_next; }

標準のINSERT OR REPLACEの例から始める場合:

INSERT OR REPLACE INTO UserProgress (id, status, level) 
  VALUES (1, 'COMPLETE', 5);

これにより、UserProgressテーブルにエントリ[1、COMPLETE、5]の行が表示されます。

次の場合:

INSERT OR REPLACE INTO UserProgress (id, status, level) 
  VALUES (1, 'PENDING', 4);

すでにCOMPLETEレコードがあるので、これをスキップしたいと思います。

これは重複した質問だと確信しています。しかし、それは本当にですか?この質問に対する答えはたくさんありますが、どれが最善のアプローチかわかりません。私が見つけたこれらすべての例を見てください:

CASEステートメントを追加しようと試みることができます。IF-THEN-ELSEステートメントと同等であると言われています。 この例で行われているように。

SELECTCOALESCEまたはVALUESステートメントを使用してみることができます。 この例で行われているように。

SELECT WHEREステートメントを使用することもできます。 この例で行われているように。

LEFT JOINステートメントの使用を試みることができます。 この例で行われているように。

これはSQLiteに最適です。同じ猫の皮を剥ぐ方法は複数あるようです。私は初心者なので、今は混乱しています。どのアプローチを使用すべきかは明確ではありません。

1つのSQLステートメントで実行できるソリューションを探しています。

*更新*

2つのトランザクションソリューションを見つけました。私はまだ単一のトランザクションソリューションを探しています。

これは機能しますが、2つのトランザクションを使用します。

 public void Create(IEnumerable<UserProgress> items)
        {
            var sbFields = new StringBuilder();
            sbFields.Append("ID,");
            sbFields.Append("STATUS,");
            sbFields.Append("LEVEL,");

            int numAppended = 3;

            var sbParams = new StringBuilder();
            for (int i = 1; i <= numAppended; i++)
            {
                sbParams.Append("@param");
                sbParams.Append(i);

                if (i < numAppended)
                {
                    sbParams.Append(", ");
                }
            }

            // attempting this solution: https://stackoverflow.com/questions/2251699/sqlite-insert-or-replace-into-vs-update-where

            // first insert the new stuff.
            using (var command = new SQLiteCommand(Db))
            {               

                command.CommandText = "INSERT OR IGNORE INTO USERPROGRESS (" + sbFields + ") VALUES(" + sbParams + ")";

                command.CommandType = CommandType.Text;

                using (var transaction = Db.BeginTransaction())
                {
                    foreach (var user in items)
                    {
                        command.Parameters.Add(new SQLiteParameter("@param1", user.Id));
                        command.Parameters.Add(new SQLiteParameter("@param2", user.Status));
                        command.Parameters.Add(new SQLiteParameter("@param3", user.Level));

                        command.ExecuteNonQuery();
                    }

                    transaction.Commit();
                }
            }

            using (var command = new SQLiteCommand(Db))
            {
                string parameterized = "";

                for (int i = 1; i <= 3; i++)
                {
                    parameterized += _columnNames[i - 1] + "=" + "@param" + i;

                    if (i != 3)
                        parameterized += ",";
                }

                command.CommandText = "UPDATE USERPROGRESS SET " + parameterized + " WHERE ID=@param1 AND STATUS !='COMPLETE'";

                command.CommandType = CommandType.Text;

                using (var transaction = Db.BeginTransaction())
                {
                    foreach (var user in items)
                    {
                        command.Parameters.Add(new SQLiteParameter("@param1", user.Id));
                        command.Parameters.Add(new SQLiteParameter("@param2", user.Status));
                        command.Parameters.Add(new SQLiteParameter("@param3", user.Level));

                        command.ExecuteNonQuery();
                    }

                    transaction.Commit();
                }
            }
        }
13
sapbucket

[〜#〜] sql [〜#〜]

INSERT OR REPLACE INTO UserProgress (id, status, level) SELECTid value, 'ステータス値',レベル値WHERE NOT EXISTS (SELECT * FROM UserProgress WHERE id =id valueAND status = 'COMPLETE');

(ここでid valueステータス値およびレベル値必要に応じて挿入されます)

デモ

http://www.sqlfiddle.com/#!5/a9b82d/1

説明

EXISTS部分は、ステータス値が'COMPLETE'である同じidを持つ既存の行がテーブルにあるかどうかを確認するために使用されます。この条件が一致した場合、何も実行されません(WHERE NOTのため)。それ以外の場合、指定されたidの行は、存在しない場合はINSERTされるか、存在する場合は指定された値で更新されます(INSERT OR REPLACEのため)。

16
Steve Chambers

IFステートメントには、IF-THEN、IF-THEN-ELSE、およびIF-THEN-ELSIFの3つの形式があります。

SQLiteでIfステートメントを使用する構文は次のとおりです。

IF expr THEN statement-list
[ELSIF expr THEN statement-list ]*
[ELSE statement-list]
END IF

リンク: https://www.sqliteconcepts.org/pl_if.html

2
5377037