T-SQL'de Uyku Komutu mu?


364

Sadece bir süre uyku yapmak için bir T-SQL komutu yazmak için bir yolu var mı? Bir web hizmetini eşzamansız olarak yazıyorum ve eşzamansız kalıbın gerçekten daha ölçeklenebilir hale gelip gelmeyeceğini görmek için bazı testler yapabilmek istiyorum. Yavaş bir dış hizmet "alay etmek" için, yavaş çalışan bir komut dosyası ile bir SQL sunucusu aramak mümkün ama aslında bir sürü şey işlemek istiyorum.


19
Adil soru! Bunu bir ara kullanmak isteyebilirim. Tam bir kenara, DB'nin daha yavaş olmasını istediğimi ilk kez duydum;)
p.campbell

2
T-SQL'den eşzamansız bir hizmet çağırarak boggled.
jmucchiello

Yanıtlar:


616

Bak BEKLE komutu.

Örneğin

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

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

Bu komut size yüksek derecede hassasiyet sağlar, ancak GetTickCount'a bağlı olduğu için tipik bir makinede yalnızca 10ms - 16ms içinde doğrudur . Yani, örneğin, çağrı hiç beklemeye neden olmayacaktır.WAITFOR DELAY '00:00:00:001'


4
Herkes bir işlevi çalışmak için bunu almak için nasıl biliyor? (Muhtemelen doğru) alıyorum, ancak test uğruna geçersiz kılmak istiyorum) 'Bir fonksiyon içinde yan
etki yaratan

2
@monojohnny beklemek için bir SVF almak, Josh cevap aşağıda denedim ama işe yaramadı. Bunun yerine ben sadece böyle bir WHILE döngü oluşturmak: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 15:17

3
Ms - '00: 00: 00: 01 'için' 2: 00: 00: 00: 010 'değerine eşit olmayan 3 basamak kullandığınızdan emin olun. (MSSQL 2016'da test edilmiştir)
Nick

bir tabloyu engellemeniz gerekiyorsa BEGIN TRANSACTION ve END TRANSACTION'ı da deneyebilirsiniz
Richárd Baldauf

9
WAITFOR DELAY 'HH:MM:SS'

Bunun bekleyebileceği maksimum sürenin 23 saat, 59 dakika ve 59 saniye olduğuna inanıyorum.

İşte kullanımını göstermek için Skaler değerli bir işlev; Aşağıdaki işlev saniye olarak bir tamsayı parametresi alır ve bu parametre daha sonra SS: DD: SS'ye çevrilir ve EXEC sp_executesql @sqlcodesorgulama komutunu kullanarak yürütür . Aşağıdaki fonksiyon sadece gösteri içindir, gerçekten skaler değerli bir fonksiyon olarak amaca uygun olmadığını biliyorum! :-)

    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 saatten daha uzun bir süre ertelemek isterseniz, birkaç günlüğüne gitmek için bir @Days parametresi kullanmanızı ve yürütülebilir işlevi bir döngü içine sarmanızı öneririm ... ör.

    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 bu Only functions and some extended stored procedures can be executed from within a function. MS Docs gibi Saklanan Procs kullanarak bir örnek sağlar - bu yaklaşım geçersiz gibi görünüyor
SliverNinja - MSFT

5

Ayrıca "WAITFOR" bir "ZAMAN" olabilir:

    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
Neden PRINTyerine kullanmıyorsunuz RAISERROR?
slartidan

4
Çünkü aksi takdirde tüm bekleme bitene kadar hiçbir şey göremezsiniz. RAISERROR size NOWAIT seçeneğini sunar, böylece arabellek dolduğunda veya toplu işlem tamamlandıktan sonra (gerçekte) ifadeleri gerçek zamanlı olarak yazdırır.
Jeremy Giaco

0

İşte CommandTimeout ile test etmek için çok basit bir C # kodu parçası. 2 saniye bekleyecek yeni bir komut oluşturur. CommandTimeout'u 1 saniyeye ayarlayın ve çalıştırırken bir istisna göreceksiniz. CommandTimeout değerini 0 veya 2'den yüksek bir değere ayarlamak iyi çalışır. Bu arada, varsayılan CommandTimeout 30 saniyedir.

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
Eğer c # iseniz muhtemelen aynı şeyi yapan Thread.currentThread.sleep (60000) VEYA Thread.sleep (60000) kullanmalısınız. Bu şekilde gecikmeniz uygulamanızda tecrit edilir. Ardından sonraki veritabanı mantığınızı çağırın.
Eylem Dan

2
@ActionDan Thread.Sleep kullanarak CommandTimeout egzersiz yardımcı olmaz, öyle değil. Bir örnek olarak, kutuda yazılanları yapar.
Richard Hauer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.