如何每隔一定的分钟间隔更新 sql table 列?
How to update a sql table column on every certain minutes interval?
在 SQL Table 中,我的列为 Start_Date、End_Date 和 IsActive。
在每次插入时,Start_Date 都有一个有效的日期时间条目,End_Date 为空,IsActive 为 0。
30 分钟后,我需要将 End_Date 更新为当前日期时间和 1 个 IsActive。这是在 SQL Express 中。我无法使用作业调度程序。我不想使用 Windows 任务计划程序。
触发器有插入或更新后的限制。有办法处理吗?
下面的示例使用服务代理激活的存储过程和对话计时器定期更新 table。收到 DialTimer 消息后,激活的 dbo.UpdateSqlTableOnTimer 进程更新 table 并启动一个新的计时器。 dbo.StartUpdateSqlTableOnTimer 进程启动初始计时器和 returns 对话句柄。如果需要,指定 dbo.StopUpdateSqlTableOnTimer 的句柄以停止计时器循环。
请注意,数据库必须启用服务代理。如果尚未启用,请使用 ALTER DATABASE
启用服务代理:
ALTER DATABASE YourDatabase
SET ENABLE_BROKER;
USE YourDatabase;
GO
CREATE PROC dbo.StartUpdateSqlTableOnTimer
--begin initial conversation and timer
AS
DECLARE @ConversationHandle uniqueidentifier;
BEGIN DIALOG CONVERSATION @ConversationHandle
FROM SERVICE UpdateSqlTableOnTimer
TO SERVICE 'UpdateSqlTableOnTimer', 'CURRENT DATABASE'
ON CONTRACT [DEFAULT]
WITH ENCRYPTION = OFF;
BEGIN CONVERSATION TIMER (@ConversationHandle)
TIMEOUT = 1800;
SELECT @ConversationHandle AS ConversationHandle;
GO
CREATE PROC dbo.StopUpdateSqlTableOnTimer
@ConversationHandle uniqueidentifier
--end conversation
AS
END CONVERSATION @ConversationHandle;
GO
CREATE PROC dbo.UpdateSqlTableOnTimer
AS
SET XACT_ABORT ON;
SET NOCOUNT ON;
DECLARE
@ConversationHandle uniqueidentifier
, @MessageTypeName sysname
, @EventNotificationDetails xml
, @EventLogMessage nvarchar(MAX);
BEGIN TRY
BEGIN TRAN;
RECEIVE TOP(1)
@ConversationHandle = conversation_handle
, @MessageTypeName = message_type_name
, @EventNotificationDetails = CAST(message_body AS xml)
FROM dbo.QueueForUpdateSqlTableOnTimer;
IF @@ROWCOUNT > 0
BEGIN
IF @MessageTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer'
BEGIN
--update IsActive and End_Date here
--start new timer
BEGIN CONVERSATION TIMER (@ConversationHandle)
TIMEOUT = 1800;
END
ELSE
BEGIN
IF @MessageTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
BEGIN
END CONVERSATION @ConversationHandle;
END
ELSE
BEGIN
END CONVERSATION @ConversationHandle WITH ERROR = 1 DESCRIPTION = 'Unexpected message type received';
END;
END;
END;
COMMIT;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH;
GO
--create queue with proc activation
CREATE QUEUE dbo.QueueForUpdateSqlTableOnTimer
WITH STATUS=ON,
ACTIVATION (
PROCEDURE_NAME = dbo.UpdateSqlTableOnTimer,
MAX_QUEUE_READERS = 1,
EXECUTE AS OWNER ) ;
GO
CREATE SERVICE UpdateSqlTableOnTimer
ON QUEUE dbo.QueueForUpdateSqlTableOnTimer
([DEFAULT]);
GO
EXEC dbo.StartUpdateSqlTableOnTimer;
GO
EXEC dbo.StopUpdateSqlTableOnTimer @ConversationHandle = '<specify value from dbo.StartUpdateSqlTableOnTimer>';
GO
在 SQL Table 中,我的列为 Start_Date、End_Date 和 IsActive。
在每次插入时,Start_Date 都有一个有效的日期时间条目,End_Date 为空,IsActive 为 0。
30 分钟后,我需要将 End_Date 更新为当前日期时间和 1 个 IsActive。这是在 SQL Express 中。我无法使用作业调度程序。我不想使用 Windows 任务计划程序。
触发器有插入或更新后的限制。有办法处理吗?
下面的示例使用服务代理激活的存储过程和对话计时器定期更新 table。收到 DialTimer 消息后,激活的 dbo.UpdateSqlTableOnTimer 进程更新 table 并启动一个新的计时器。 dbo.StartUpdateSqlTableOnTimer 进程启动初始计时器和 returns 对话句柄。如果需要,指定 dbo.StopUpdateSqlTableOnTimer 的句柄以停止计时器循环。
请注意,数据库必须启用服务代理。如果尚未启用,请使用 ALTER DATABASE
启用服务代理:
ALTER DATABASE YourDatabase
SET ENABLE_BROKER;
USE YourDatabase;
GO
CREATE PROC dbo.StartUpdateSqlTableOnTimer
--begin initial conversation and timer
AS
DECLARE @ConversationHandle uniqueidentifier;
BEGIN DIALOG CONVERSATION @ConversationHandle
FROM SERVICE UpdateSqlTableOnTimer
TO SERVICE 'UpdateSqlTableOnTimer', 'CURRENT DATABASE'
ON CONTRACT [DEFAULT]
WITH ENCRYPTION = OFF;
BEGIN CONVERSATION TIMER (@ConversationHandle)
TIMEOUT = 1800;
SELECT @ConversationHandle AS ConversationHandle;
GO
CREATE PROC dbo.StopUpdateSqlTableOnTimer
@ConversationHandle uniqueidentifier
--end conversation
AS
END CONVERSATION @ConversationHandle;
GO
CREATE PROC dbo.UpdateSqlTableOnTimer
AS
SET XACT_ABORT ON;
SET NOCOUNT ON;
DECLARE
@ConversationHandle uniqueidentifier
, @MessageTypeName sysname
, @EventNotificationDetails xml
, @EventLogMessage nvarchar(MAX);
BEGIN TRY
BEGIN TRAN;
RECEIVE TOP(1)
@ConversationHandle = conversation_handle
, @MessageTypeName = message_type_name
, @EventNotificationDetails = CAST(message_body AS xml)
FROM dbo.QueueForUpdateSqlTableOnTimer;
IF @@ROWCOUNT > 0
BEGIN
IF @MessageTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer'
BEGIN
--update IsActive and End_Date here
--start new timer
BEGIN CONVERSATION TIMER (@ConversationHandle)
TIMEOUT = 1800;
END
ELSE
BEGIN
IF @MessageTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
BEGIN
END CONVERSATION @ConversationHandle;
END
ELSE
BEGIN
END CONVERSATION @ConversationHandle WITH ERROR = 1 DESCRIPTION = 'Unexpected message type received';
END;
END;
END;
COMMIT;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH;
GO
--create queue with proc activation
CREATE QUEUE dbo.QueueForUpdateSqlTableOnTimer
WITH STATUS=ON,
ACTIVATION (
PROCEDURE_NAME = dbo.UpdateSqlTableOnTimer,
MAX_QUEUE_READERS = 1,
EXECUTE AS OWNER ) ;
GO
CREATE SERVICE UpdateSqlTableOnTimer
ON QUEUE dbo.QueueForUpdateSqlTableOnTimer
([DEFAULT]);
GO
EXEC dbo.StartUpdateSqlTableOnTimer;
GO
EXEC dbo.StopUpdateSqlTableOnTimer @ConversationHandle = '<specify value from dbo.StartUpdateSqlTableOnTimer>';
GO