Czy istnieje sposób, aby napisać polecenie T-SQL, aby po prostu spać przez pewien okres czasu? Piszę usługę internetową asynchronicznie i chcę mieć możliwość uruchomienia niektórych testów, aby przekonać się, czy asynchroniczny wzorzec rzeczywiście zwiększy skalowalność. Aby "pozorować" zewnętrzną usługę, która jest wolna, chcę mieć możliwość wywoływania serwera SQL za pomocą skryptu działającego powoli, ale w rzeczywistości nie przetwarzającego wielu rzeczy.Polecenie uśpienia w T-SQL?
Odpowiedz
spojrzenie na rozkaz WAITFOR
Eg.
-- wait for 1 minute
WAITFOR DELAY '00:01'
-- wait for 1 second
WAITFOR DELAY '00:00:01'
Komenda ta pozwala na wysoki stopień precyzji, ale jest only accurate within 10ms - 16ms na typowym komputerze, gdyż opiera się na GetTickCount. Na przykład wywołanie WAITFOR DELAY '00:00:00:001'
prawdopodobnie nie spowoduje żadnego oczekiwania.
Ktoś wie, jak uruchomić to z funkcji? Dostaję (poprawnie prawdopodobnie), ale ze względu na testy chciałbym przesłonić) "Niepoprawne użycie operatora powodującego efekt uboczny 'WAITFOR' w funkcji .... – monojohnny
@monojohnny, aby SVF czekać, ja ' próbowałem odpowiedzi Josha poniżej, ale to nie zadziałało. Zamiast tego po prostu tworzę pętlę WHILE w następujący sposób: 'CREATE FUNCTION [dbo]. [ForcedTimeout] (@ seconds int) zwraca int jako BEGIN DECLARE @endTime datetime2 (0) = DATEADD (SECOND, @seconds, GETDATE()) ; WHILE (GETDATE() <@endTime) BEGIN \t SET @endTime = @endTime; - nic nie rób, ale SQL wymaga instrukcji. END' – GilesDMiddleton
Upewnij się, że używasz 3 cyfr dla ms - '00: 00: 00: 01 'nie jest równe '00: 00: 00: 010' użyj sekundy. (testowane na MSSQL 2016) – Nick
Oto bardzo prosty fragment kodu C# do przetestowania CommandTimeout. Tworzy nowe polecenie, które będzie czekać przez 2 sekundy. Ustaw parametr CommandTimeout na 1 sekundę i zobaczysz wyjątek podczas jego uruchamiania. Ustawienie parametru CommandTimeout na 0 lub coś wyższego niż 2 będzie działać poprawnie. Nawiasem mówiąc, domyślny parametr CommandTimeout wynosi 30 sekund.
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();
}
}
}
}
}
Jeśli jesteś w C# powinieneś prawdopodobnie użyć Thread.currentThread.sleep (60000) LUB Thread.sleep (60000), który robi to samo. W ten sposób Twoje opóźnienie jest odizolowane od twojej aplikacji.Następnie wywołaj późniejszą logikę bazy danych. –
@ActionDan Korzystanie z Thread.Sleep nie pomoże jednak w zarządzaniu czasem CommandTimeout. Jako wymyślny przykład robi to, co jest napisane na pudełku. –
WAITFOR DELAY 'HH:MM:SS'
wierzę, maksymalny czas może czekać do 23 godzin, 59 minut i 59 sekund.
Oto funkcja ceniona przez Skalar, aby pokazać jej użycie; poniższa funkcja przyjmie całkowity parametr sekund, który następnie przetłumaczy na HH: MM: SS i wykona go przy pomocy polecenia EXEC sp_executesql @sqlcode
do zapytania. Poniższa funkcja służy tylko do celów demonstracyjnych, wiem, że nie nadaje się do celu tak naprawdę jako funkcja o wartościach skalarnych! :-)
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
Jeśli chcesz, aby opóźnić dłużej niż 24 godzin, proponuję użyć @dni parametr, aby przejść przez kilka dni i zawinąć funkcji wykonywalnego wewnątrz pętli ... np.
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 ** nie podoba to 'Tylko funkcje i niektóre rozszerzone procedury przechowywane mogą być wykonywane z poziomu funkcji. [Dokumenty MS dostarczają przykład przy użyciu Stored Procs] (https://docs.microsoft.com/ en-us/sql/t-sql/language-elements/waitfor-transact-sql # examples) - wygląda na to, że to podejście jest nieprawidłowe. – SliverNinja
można również "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
Dlaczego nie używać polecenia "PRINT" zamiast "RAISERROR"? – slartidan
Fair pytanie! Może kiedyś z tego skorzystam. Na marginesie, po raz pierwszy słyszałem o tym, że chcę, żeby DB działał wolniej;) –
Jestem zdumiony, wywołując usługę asynchroniczną z T-SQL. – jmucchiello