Comando do sono em t-sql?
-
21-08-2019 - |
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.
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();
}
}
}
}
}