Pergunta

Existe uma maneira de escrever um comando t-sql para apenas dormir por um período de tempo? Estou escrevendo um serviço da web de forma assíncrona e quero poder executar alguns testes para ver se o padrão assíncrono realmente o tornará mais escalável. Para "zombar" de um serviço externo lento, quero poder chamar um servidor SQL com um script que funciona devagar, mas na verdade não está processando muitas coisas.

Foi útil?

Solução

olhe para a ESPERAR POR comando

Por exemplo.

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

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

Este comando permite um alto grau de precisão, mas é apenas preciso dentro de 10ms - 16ms em uma máquina típica como se depende de GetTickCount. Então, por exemplo, a chamada WAITFOR DELAY '00:00:00:001' É provável que não resulte em nenhuma espera.

Outras dicas

WAITFOR DELAY 'HH:MM:SS'

Acredito que o tempo máximo que isso pode esperar é de 23 horas, 59 minutos e 59 segundos.

Aqui está uma função de valor escalar para mostrar seu uso; A função abaixo terá um parâmetro inteiro de segundos, que ela se traduz em Hh: MM: SS e o executa usando o EXEC sp_executesql @sqlcode comando para consultar. Abaixo da função é apenas para demonstração, sei que não é adequado para o propósito realmente como uma função de valor escalar! :-)

    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

Se você deseja atrasar mais de 24 horas, sugiro que você use um parâmetro @Days para procurar vários dias e envolver a função executável dentro de um loop ... por exemplo.

    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

Você também pode "esperar" um "horário":

    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

Aqui está uma peça muito simples do código C# para testar o CommandTimeout. Ele cria um novo comando que aguarda 2 segundos. Defina o CommandTimeout como 1 segundo e você verá uma exceção ao executá -lo. Definir o CommandTimeout para 0 ou algo maior que 2 funcionará bem. A propósito, o comando padrão padrão é de 30 segundos.

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();
        }
      }
    }
  }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top