T-SQL中的睡眠命令?


364

是否有办法编写T-SQL命令使其仅睡眠一段时间?我正在异步编写Web服务,并且希望能够运行一些测试以查看异步模式是否真的会使其更具扩展性。为了“模拟”速度很慢的外部服务,我希望能够使用运行缓慢但实际上没有处理大量东西的脚本来调用SQL Server。


19
公平的问题!我可能想在某个时候使用它。
顺便说一句

2
我为从T-SQL调用异步服务而感到困惑。
jmucchiello,2009年

Answers:


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,2013年

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
确保您使用3位数字表示毫秒-'00:00:00:01'不等于'00:00:00:010'请使用第二位。(在MSSQL 2016上测试)
尼克

你也可以尝试BEGIN TRANSACTION和END TRANSACTION如果你需要阻止表
理查德·巴尔道夫

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 Docs提供了一个使用存储的
Procs

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

4
因为否则,直到整个等待完成后您什么都看不到。RAISERROR为您提供NOWAIT选项,因此它将实时(基本上)向您显示打印语句,而不是在缓冲区已满或批处理完成后显示。
Jeremy Giaco '18

0

这是一段非常简单的C#代码,用于测试CommandTimeout。它创建一个新命令,将等待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
@ActionDan使用Thread.Sleep并不能帮助执行CommandTimeout。作为一个人为的例子,它完成了包装盒上写的内容。
理查德·豪尔,2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.