T-SQLのスリープコマンド?


364

一定期間スリープさせるだけのT-SQLコマンドを作成する方法はありますか?私は非同期でWebサービスを作成しており、非同期パターンが実際にそれをよりスケーラブルにするかどうかを確認するためにいくつかのテストを実行できるようにしたいと考えています。遅い外部サービスを「モック」するために、実行速度が遅いが実際には大量のものを処理していないスクリプトでSQLサーバーを呼び出すことができるようにしたいと思います。


19
公正な質問!いつかこれを使いたいかもしれません。余談ですが、これは、DBを遅くしたいと思ったのは初めてです;)
p.campbell 2009年

2
T-SQLから非同期サービスを呼び出すことに戸惑っています。
jmucchiello

回答:


616

WAITFORコマンドを見てください。

例えば

-- wait for 1 minute
WAITFOR DELAY '00:01'

-- wait for 1 second
WAITFOR DELAY '00:00:01'

このコマンドは高度精度を可能にしますが、GetTickCountに依存しているため、通常のマシンでは10ms〜16ms のみ正確です。したがって、たとえば、呼び出しWAITFOR DELAY '00:00:00:001'はまったく待機しない可能性があります。


4
これを関数から機能させる方法を誰かが知っていますか?(おそらく正しく)取得しますが、テストのためにオーバーライドしたいと思います)「関数内での副作用演算子 'WAITFOR'の無効な使用....
monojohnny

2
@monojohnnyにSVFを待機させるには、以下のJoshの答えを試しましたが、うまくいきませんでした。代わりに、私はちょうどこのようなWHILEループを作成しますCREATE FUNCTION [dbo].[ForcedTimeout](@seconds int) returns int as BEGIN DECLARE @endTime datetime2(0) = DATEADD(SECOND, @seconds, GETDATE()); WHILE (GETDATE() < @endTime ) BEGIN SET @endTime = @endTime; -- do nothing, but SQL requires a statement. END
GilesDMiddleton

3
msには必ず3桁を使用してください。「00:00:00:01」が「00:00:00:010」と等しくない場合は、2番目を使用してください。(MSSQL 2016でテスト済み)
Nick

また、あなたがテーブルをブロックする必要がある場合TRANSACTIONとEND BEGIN TRANSACTIONを試すことができます
リチャードBaldauf

9
WAITFOR DELAY 'HH:MM:SS'

これが待機できる最大時間は23時間59分59秒だと思います。

以下は、その使用法を示すスカラー値関数です。以下の関数は秒の整数パラメーターを受け取り、それをHH:MM:SSに変換しEXEC sp_executesql @sqlcode、クエリを実行するコマンドを使用して実行します。以下の関数はデモンストレーションのみを目的としています。スカラー値の関数としての目的には適していません。:-)

    CREATE FUNCTION [dbo].[ufn_DelayFor_MaxTimeIs24Hours]
    (
    @sec int
    )
    RETURNS
    nvarchar(4)
    AS
    BEGIN


    declare @hours int = @sec / 60 / 60
    declare @mins int = (@sec / 60) - (@hours * 60)
    declare @secs int = (@sec - ((@hours * 60) * 60)) - (@mins * 60)


    IF @hours > 23 
    BEGIN
    select @hours = 23
    select @mins = 59
    select @secs = 59
    -- 'maximum wait time is 23 hours, 59 minutes and 59 seconds.'
    END


    declare @sql nvarchar(24) = 'WAITFOR DELAY '+char(39)+cast(@hours as nvarchar(2))+':'+CAST(@mins as nvarchar(2))+':'+CAST(@secs as nvarchar(2))+char(39)


    exec sp_executesql @sql

    return ''
    END

24時間を超えて遅延させたい場合は、@ Daysパラメータを使用して何日か移動し、関数の実行可能ファイルをループ内にラップすることをお勧めします。

    Declare @Days int = 5
    Declare @CurrentDay int = 1

    WHILE @CurrentDay <= @Days
    BEGIN

    --24 hours, function will run for 23 hours, 59 minutes, 59 seconds per run.
    [ufn_DelayFor_MaxTimeIs24Hours] 86400

    SELECT @CurrentDay = @CurrentDay + 1
    END

SQL AzureはこのOnly functions and some extended stored procedures can be executed from within a function. MSドキュメントが好きではありません。ストアドプロシージャを使用した例を提供します
SliverNinja-MSFT

5

「時間」を「待機」することもできます。

    RAISERROR('Im about to wait for a certain time...', 0, 1) WITH NOWAIT
    WAITFOR TIME '16:43:30.000'
    RAISERROR('I waited!', 0, 1) WITH NOWAIT

2
PRINT代わりに使用しないのはなぜRAISERRORですか?
slartidan 2016年

4
それ以外の場合は、全体の待機が終了するまで何も表示されません。RAISERRORはNOWAITオプションを提供するため、バッファーがいっぱいになったときやバッチが完了した後ではなく、ステートメントを(本質的に)リアルタイムで表示します。
Jeremy Giaco

0

以下は、CommandTimeoutをテストするための非常に単純なC#コードです。2秒間待機する新しいコマンドを作成します。CommandTimeoutを1秒に設定すると、実行時に例外が表示されます。CommandTimeoutを0または2より大きい値に設定すると問題なく動作します。ちなみに、デフォルトのCommandTimeoutは30秒です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.SqlClient;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
      var builder = new SqlConnectionStringBuilder();
      builder.DataSource = "localhost";
      builder.IntegratedSecurity = true;
      builder.InitialCatalog = "master";

      var connectionString = builder.ConnectionString;

      using (var connection = new SqlConnection(connectionString))
      {
        connection.Open();

        using (var command = connection.CreateCommand())
        {
          command.CommandText = "WAITFOR DELAY '00:00:02'";
          command.CommandTimeout = 1;

          command.ExecuteNonQuery();
        }
      }
    }
  }
}

2
C#を使用している場合は、おそらく同じことを行うThread.currentThread.sleep(60000)またはThread.sleep(60000)を使用する必要があります。こうすることで、遅延がアプリケーションから切り離されます。その後、後続のデータベースロジックを呼び出します。
アクションダン

2
ただし、Thread.Sleepを使用した@ActionDanは、CommandTimeoutの実行には役立ちません。不自然な例として、ボックスに書かれていることを行います。
Richard Hauer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.