T-SQL 中的睡眠命令?

发布于 2024-07-15 12:49:28 字数 137 浏览 8 评论 0原文

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

Is there to way write a T-SQL command to just make it sleep for a period of time? I am writing a web service asynchronously and I want to be able to run some tests to see if the asynchronous pattern is really going to make it more scalable. In order to "mock" an external service that is slow, I want to be able to call a SQL server with a script that runs slowly, but isn't actually processing a ton of stuff.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

聆听风音 2024-07-22 12:49:28

查看 WAITFOR 命令。

例如,

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

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

此命令允许您实现高精度,但在典型计算机上仅在 10ms - 16ms 内准确,因为它依赖于 GetTickCount。 因此,例如,调用 WAITFOR DELAY '00:00:00:001' 可能会导致根本不等待。

Look at the WAITFOR command.

E.g.

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

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

This command allows you a high degree of precision but is only accurate within 10ms - 16ms on a typical machine as it relies on GetTickCount. So, for example, the call WAITFOR DELAY '00:00:00:001' is likely to result in no wait at all.

雪若未夕 2024-07-22 12:49:28
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
WAITFOR DELAY 'HH:MM:SS'

I believe the maximum time this can wait for is 23 hours, 59 minutes and 59 seconds.

Here's a Scalar-valued function to show it's use; the below function will take an integer parameter of seconds, which it then translates into HH:MM:SS and executes it using the EXEC sp_executesql @sqlcode command to query. Below function is for demonstration only, i know it's not fit for purpose really as a scalar-valued function! :-)

    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

IF you wish to delay longer than 24 hours, I suggest you use a @Days parameter to go for a number of days and wrap the function executable inside a loop... e.g..

    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
坏尐絯 2024-07-22 12:49:28

您还可以“等待”一个“时间”:

    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

You can also "WAITFOR" a "TIME":

    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
皇甫轩 2024-07-22 12:49:28

这是一段非常简单的 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();
        }
      }
    }
  }
}

Here is a very simple piece of C# code to test the CommandTimeout with.
It creates a new command which will wait for 2 seconds.
Set the CommandTimeout to 1 second and you will see an exception when running it.
Setting the CommandTimeout to either 0 or something higher than 2 will run fine.
By the way, the default CommandTimeout is 30 seconds.

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();
        }
      }
    }
  }
}
空心空情空意 2024-07-22 12:49:28

这是一个很好的解决方案。

CREATE OR ALTER FUNCTION [dbo].[Sleep](@seconds INT)
RETURNS INT AS
BEGIN
    DECLARE @startTime DATETIME2(7) = SYSDATETIME();
    DECLARE @endTime DATETIME2(7) = DATEADD(SECOND, @seconds, @startTime);
    WHILE (SYSDATETIME() < @endTime)
        SET @startTime = @startTime;
    RETURN @seconds;
END

GO
CREATE OR ALTER VIEW dbo.SlowView AS
SELECT 
    [dbo].[Sleep](5) AS DELAY,
    NEWID() AS VALUE

GO
SELECT * FROM SlowView

This is a good solution.

CREATE OR ALTER FUNCTION [dbo].[Sleep](@seconds INT)
RETURNS INT AS
BEGIN
    DECLARE @startTime DATETIME2(7) = SYSDATETIME();
    DECLARE @endTime DATETIME2(7) = DATEADD(SECOND, @seconds, @startTime);
    WHILE (SYSDATETIME() < @endTime)
        SET @startTime = @startTime;
    RETURN @seconds;
END

GO
CREATE OR ALTER VIEW dbo.SlowView AS
SELECT 
    [dbo].[Sleep](5) AS DELAY,
    NEWID() AS VALUE

GO
SELECT * FROM SlowView
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文