私は単純なメッセージングプログラムを書いています。メッセージのテーブルがあります。メッセージのテーブルはユーザーが要求し、そのユーザーによって処理されます。どのユーザーが特定のメッセージを要求するかは予期されていないので、私が持っているすべての利用可能なメッセージのうち最初のものを選択し、そのメッセージを私が持っているテイクとしてマークするクエリが必要です。問題は、同時に2人のユーザーが同じメッセージを主張することを希望しないため、2つのステートメントを連続して実行し、プログラムに戻って次のプログラムを実行する必要はありません。文の間。セミコロンで区切って2つの連続した文を実行することができますが、最初の問合せで戻されたデータを2番目の問合せの一部として使用したいと考えています。変数は完璧ですが、私が知っている限り、SQLには存在しません。クエリ間に状態を保存する方法はありますか?状態が連続したSQLステートメント
答えて
取引がle dorfierが言うように、行くには良い方法ですが、alernativesがあります:あなたが最初の更新を行うことができ
、すなわち、ユーザIDまたは同様のメッセージにタグを付けるには。あなたは、SQL風味youreの使用に言及いけないが、MySQLで、私はそれがこのようなものに見えると思う:
WITH q AS (
SELECT TOP 1
FROM message m
WHERE user_id = 0
)
UPDATE q
SET user_id = 1
:MS SQLで
UPDATE message
SET user_id = ...
WHERE user_id = 0 -- Ensures no two users gets the same message
LIMIT 1
を、それはの線に沿って何かだろう
/B
クエリ間に状態を保存する方法はありますか?
いいえ、SQLは手続き型言語ではありません。 2つのクエリを1つのクエリとして書き直すことができます(必ずしも可能ではなく、可能であっても価値がないことが多い)か、手続き型言語でそれらを結合します。多くのSQLサーバーは、このための組み込み言語(「ストアドプロシージャ」)を提供していますが、アプリケーションで実行することもできます。
問題は、私は、同じメッセージを請求すると同時に、
使用のロックを、それを使用して2人のユーザーを望んでいないこと、です。私はあなたが使用しているSQLサーバを知っていませんが、利用可能であれば、あなたが望むものであるようにSELECT ... FOR UPDATE
という音を使用しています。
これはBEGIN TRANとCOMMIT TRANのためのものです。保護したいステートメントをトランザクション内に配置します。
おそらく一時テーブルを使用できます。
SQL自体には変数はありませんが、ほとんどすべてのRDBMS SQL拡張機能が(ほとんどの場合)?しかし、私はそれだけであなたの問題を解決する方法は本当によく分かりません。
前述のように、トランザクションは、関連のない2つのステートメントをまとめてトリック効果的にグループ化します。 の場合、デフォルトの取引レベルはとなります。 (Most?)RDBMSサーバーのデフォルト・トランザクション・レベルはREAD COMMITTEDです。これは、ユーザー2がユーザー1が読み取ったのと同じ行を読み取ることを妨げません。そのためには、REPEATABLE READまたはSERIALIZABLEを使用する必要があります。
これは古典的な並行性の問題です。一般に、それを処理する2つの方法は、悲観的なロックまたは楽観的なチェックです。REPEATABLE READトランザクションは悲観的なものになり(必要であるかどうかにかかわらずロッキング経費がかかる)、@@ ROWCOUNTをチェックすることは楽観的です(@@ ROWCOUNT = 0のときにはうまくいくと思います)。
通常、楽観的(ロックは高価です)を使用し、タイムスタンプまたはフィールドの組み合わせを使用して、私たちが思ったデータを変更していることを確認します。したがって、私の提案は、rowversionまたはtimestampフィールドをインクルードし、それをUPDATEステートメントに渡すことです。次に、@@ ROWCOUNTをチェックして、レコードを更新したかどうかを確認します。あなたがしなかったなら、戻って別のメッセージを選んでください。擬似コードで:
int messageId, byte[] rowVersion = DB.Select(
"SELECT TOP 1
MessageId, RowVersion
FROM Messages
WHERE
User IS NULL";
int rowsAffected = DB.Update(
"UPDATE Messages SET
User = @myUserId
WHERE
MessageId = @messageId
AND RowVersion = @rowVersion",
myUserId, messageId, rowVersion
);
if (rowsAffected = 0)
throw new ConcurrencyException("The message was taken by someone else");
あなたの特定のステートメントに応じて、あなただけのWHEREあなたのUPDATEステートメントで句「ユーザーIDがNULL IS」繰り返して逃げることができるかもしれません。これはBrimstedtのソリューションに似ていますが、でも、行が実際に更新されたかどうかを確認するには、@@ ROWCOUNTを確認する必要があります。
- 1. JavaRXは、私が2つの連続して更新状態持つ二つの連続して更新状態
- 2. マージする方法連続した重複状態の行 - Sql Server
- 3. afterUpdateイベントフック、トランザクション、および連続したリクエストの古い状態
- 4. 連続した状態を構築するとき
- 5. 接続状態が102
- 6. 休止状態が持続しない
- 7. デバイスイーサネット接続状態
- 8. HttpWebRequestとHttpWebResponse:連続したクエリのログイン要求の状態を維持する
- 9. C#連続使用ステートメント
- 10. エリクサー/ OTP連続バックグラウンドジョブと状態の参照
- 11. 選択し、SQLテーブルから参加を(Selectステートメント+コードを休止状態)
- 12. バウンスが解除され、連続的な状態遷移が発生する
- 13. BACKUP LOG NORECOVERY後の状態でSQL Serverデータベースがスタックした
- 14. JavaのJDBC接続状態
- 15. php - 継続状態のパフォーマンス
- 16. 接続状態MySql Connector/NET
- 17. SQL GROUP BY:連続した間隔?
- 18. SQL連続した日付範囲
- 19. SQL上で連続したボーカルをクエリ
- 20. SQL回数連続した行
- 21. エラー:-601 SQL状態38000
- 22. SQLのASP.NETセッション状態
- 23. エラーSQLの状態:42P01ポストグル
- 24. SQLセッション状態&Javascriptのエラー
- 25. 休止状態:休止状態の接続を変更する
- 26. SQLセッション状態サーバーの動的接続文字列
- 27. setTimeoutを連続的に使用して状態をreactjsで変更する
- 28. 3つの状態とYiiのSQL文の状態
- 29. SQL Serverアクティブ状態のスリープ状態のプロセス?
- 30. SQL Server 2008 R2 ODBCエラー:SQL状態HTY00