锁定整个表存储过程

时间:2014-03-27 08:13:15

标签: sql sql-server tsql

伙计我有一个存储过程,只有当最后插入的值不同时,才会在表中插入一个新值。

CREATE PROCEDURE [dbo].[PutData]
    @date datetime,
    @value float
AS
    IF NOT EXISTS(SELECT * FROM Sensor1 WHERE SensorTime <= @date AND SensorTime = (SELECT MAX(SensorTime) FROM Sensor1) AND SensorValue = @value)
        INSERT INTO Sensor1 (SensorTime, SensorValue) VALUES (@date, @value)
RETURN 0

现在,由于我是以高频率(比如每10毫秒)执行此操作,IF NOT EXISTS (SELECT)语句通常会获取旧数据,因此我得到重复数据。是否可以在存储过程中锁定整个表,以确保SELECT语句始终接收最新数据?

2 个答案:

答案 0 :(得分:0)

根据海报对问题的评论,c#代码从传感器接收值。代码只有在与前一个值不同时才会插入值。

为什么不在代码中存储插入的最后一个值,而只是在新值不同的情况下调用该过程?然后程序不需要检查数据库中是否存在该值;它可以简单地插入。这会更有效率。

答案 1 :(得分:0)

你可以这样写:

CREATE PROCEDURE [dbo].[PutData]
    @date datetime,
    @value float
AS

    BEGIN TRANSACTION

        INSERT INTO Sensor1 (SensorTime, SensorValue) 
        SELECT SensorTime = @date, 
               SensorValue = @value
         WHERE NOT EXISTS(SELECT * 
                            FROM Sensor1 WITH (UPDLOCK, HOLDLOCK)
                           WHERE SensorValue = @value
                             AND SensorTime <= @date 
                             AND SensorTime = (SELECT MAX(SensorTime) FROM Sensor1) )

    COMMIT TRANSACTION

RETURN 0

稍微思考一下,你也可以这样写:

CREATE PROCEDURE [dbo].[PutData]
    @date datetime,
    @value float
AS

    BEGIN TRANSACTION

        INSERT INTO Sensor1 (SensorTime, SensorValue) 
        SELECT SensorTime = @date, 
               SensorValue = @value
          FROM (SELECT TOP 1 SensorValue, SensorTime
                  FROM Sensor1 WITH (UPDLOCK, HOLDLOCK)
                 ORDER BY SensorTime DESC) last_value
         WHERE last_value.SensorTime <= @date 
           AND last_value.SensorValue <> @value

    COMMIT TRANSACTION

RETURN 0

假设您在SensorTime上有一个唯一索引(PK?),实际上这应该非常快。