SQL Server触发器锁表

时间:2018-05-19 16:03:18

标签: sql sql-server triggers

我不太擅长编写SQL,但是我试图在INSERT之后实现一个触发器。

触发器将触发,但是,这个特定的SELECT语句变得越复杂,它似乎锁定了表。如果我简化语句只有几个参数它运行正常。

如果我从SSMS运行SELECT语句,它可以工作,如果我在VB.net应用程序中从Visual Studio运行它,它也可以工作。我尝试过增加命令超时但仍然失败。表中只有几行数据。

非常感谢任何见解。如果需要更多细节,请告诉我。这是一个工资单时钟表,我在插入记录时触发,然后抓住前几天的时钟输出日期(这样我就可以比较前几天的工资单小时数和前几天的工作时间)。

我忘了提到我在我创建的视图上运行SELECT语句,其中包含来自本机应用程序的两个表。

SELECT TOP 1
    @LastDateClockOut = datEvent
FROM 
    MyTable.dbo.TimeMTSView
WHERE 
    datEvent < @Today 
    AND strUniqueID = @nUser 
    AND blnEventType = 0 
    AND lngClassificationID = 0
ORDER BY 
    datEvent DESC;

以下是整个触发器:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[trgAfterInsert] 
ON [dbo].[tblTimes]
AFTER INSERT
AS
    DECLARE @trg_lngClassificationID int;

    SELECT @trg_lngClassificationID = i.lngClassificationID 
    FROM inserted i;

    IF (@trg_lngClassificationID = 0) --If the date Classification is 0 this means it is NORMAL time as opposed to VACATION or HOLIDAY

    DECLARE @trg_lngID int;
    DECLARE @trg_lngEmployeeID varchar(20);
    DECLARE @trg_blnEventType bit;
    DECLARE @blnEventChar nvarchar(1);
    DECLARE @trg_datEvent datetime;
    DECLARE @nUser varchar(255);
    DECLARE @cmd varchar(255);
    DECLARE @Today varchar(255);
    DECLARE @LastDateClockOut datetime;
    DECLARE @strLastClock varchar(255);

    SELECT @trg_lngID = i.lngID FROM inserted i;
    SELECT @trg_lngEmployeeID = i.lngEmployeeID FROM inserted i;
    SELECT @trg_blnEventType = i.blnEventType FROM inserted i;
    SELECT @trg_datEvent = i.datEvent FROM inserted i;

    SELECT @nUser = strUniqueID 
    FROM dbo.tblEmployees 
    WHERE lngID = @trg_lngEmployeeID AND blnDeleted = 0

    SELECT @blnEventChar = CONVERT(NVARCHAR, @trg_blnEventType);
    SELECT @Today = CONVERT(VARCHAR, GetDate(), 103);

    SELECT TOP 1 @LastDateClockOut = datEvent 
    FROM MyTable.dbo.TimeMTSView 
    WHERE datEvent < @Today 
      AND strUniqueID = @nUser 
      AND blnEventType = 0 
      AND lngClassificationID = 0 
    ORDER BY datEvent DESC --This is what fails

    SELECT @strLastClock = CONVERT(VARCHAR, @LastDateClockOut, 103);

    -- Grab the path to the TimeMTSTrigger.exe written out by the application itself to a log file:
    DECLARE @FileContents  VARCHAR(MAX)

    SELECT @FileContents = BulkColumn
    FROM OPENROWSET(BULK'C:\MTSPath\MTSPath.sql', SINGLE_BLOB) x;

    SET @cmd = 'Start ' + @FileContents + ' ' + @nUser + ' ' + @blnEventChar + ' ' + @strLastClock
    EXEC xp_cmdshell @cmd

1 个答案:

答案 0 :(得分:0)

我能够通过不在我在单独数据库中创建的View上运行SELECT语句来解决这个问题。

View结合了TIMECLOCKMTS数据库中的两个表,以便更轻松地获取数据。但是,View上的SELECT语句不能在SQL Trigger或exe本身中运行,它们都会挂起并超时。

通过从Trigger和EXE中删除View并仅在Trigger的数据库中引用表,这完全可以运行:

USE [TIMECLOCKMTS]
GO
/****** Object:  Trigger [dbo].[trgAfterInsert]    Script Date: 5/19/2018 2:22:34 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[trgAfterInsert] ON [dbo].[tblTimes]
AFTER INSERT
AS

declare @trg_lngClassificationID int;
SELECT @trg_lngClassificationID=i.lngClassificationID from inserted i;

IF (@trg_lngClassificationID = 0) --If the date Classification is 0 this means it is NORMAL time as opposed to VACATION or HOLIDAY
declare @trg_lngID int;
declare @trg_lngEmployeeID varchar(20);
declare @trg_blnEventType bit;
declare @blnEventChar nvarchar(1);
declare @trg_datEvent datetime;
declare @nUser varchar(255);
declare @cmd varchar(255);
declare @Today varchar(255);
declare @LastDateClockOut datetime;

SELECT @trg_lngID=i.lngID from inserted i;
SELECT @trg_lngEmployeeID=i.lngEmployeeID from inserted i;
SELECT @trg_blnEventType=i.blnEventType from inserted i;
SELECT @trg_datEvent=i.datEvent from inserted i;
SELECT @nUser = strUniqueID FROM dbo.tblEmployees WHERE lngID = @trg_lngEmployeeID AND blnDeleted = 0
SELECT @blnEventChar = CONVERT(NVARCHAR, @trg_blnEventType);

--Grab the path to the TimeMTSTrigger.exe written out by the application itself to a log file:
DECLARE @FileContents  VARCHAR(MAX)
SELECT @FileContents=BulkColumn
FROM   OPENROWSET(BULK'C:\MTSPath\MTSPath.sql',SINGLE_BLOB) x;

SET @cmd = 'Start ' + @FileContents + ' ' + @nUser + ' ' + @blnEventChar + ' ' + @trg_lngEmployeeID
EXEC xp_cmdshell @cmd