SQL Server 2005 - установка столбца только для чтения - PullRequest
6 голосов
/ 20 января 2010

У меня есть поле «InsertTime» в таблице в базе данных SQL Server 2005, которое по умолчанию равно «getDate ()», когда запись впервые вставляется в базу данных.Я хочу убедиться, что этот столбец не обновляется снова.

Может ли этот столбец быть установлен только для чтения или есть лучший способ сделать это без написания всего sql для разработчиков?

Ответы [ 6 ]

4 голосов
/ 20 января 2010

Вы можете реализовать поле «только для чтения», создав триггер UPDATE, который проверяет наличие обновлений в этом столбце и затем откатывает их обратно.

IF EXISTS (SELECT name FROM sys.objects
      WHERE name = 'ReadOnlyInsertTime_tr' AND type = 'TR')
   DROP TRIGGER dbo.ReadOnlyInsertTime_tr;
GO

CREATE TRIGGER ReadOnlyInsertTime_tr
ON dbo.MyTable
AFTER UPDATE 
AS 
IF (UPDATE(InsertTime))
BEGIN
ROLLBACK
-- Raise an informative error
-- RAISERROR (50009, 16, 10)
END;
GO
2 голосов
/ 07 сентября 2012

Другой подход заключается в воссоздании исходного значения InsertDate. При обновлении строки исходная строка перемещается в (логическую) «удаленную» таблицу. Итак ...

ALTER TRIGGER trgDocuments
ON dbo.Documents
FOR INSERT, UPDATE
AS

-- For new records set the created date and the updated date to Now
UPDATE Documents SET DateCreated = GetDate(), DateUpdated = GetDate() Where DocumentId in (SELECT DocumentId From inserted)

-- For updated records set the created date to the original created date and the updated date to Now
UPDATE Documents SET DateCreated = (SELECT DateCreated FROM deleted d WHERE DocumentId = d.DocumentId) Where DocumentId in (SELECT DocumentId From deleted)
UPDATE Documents SET DateUpdated = GetDate() Where DocumentId in (SELECT DocumentId From deleted)
1 голос
/ 21 января 2010

Напишите хранимую процедуру для обновления в этой таблице и убедитесь, что она не касается поля InsertTime. Затем настройте разрешения всех ваших пользователей, чтобы они сами не могли выполнить необработанное обновление для этой таблицы, но могли вызвать хранимую процедуру.

1 голос
/ 20 января 2010

Вместо триггера также можно выполнить эту работу.

CREATE TRIGGER [dbo].[MyTableUpdateTrigger] 
ON [dbo].[MyTable]
INSTEAD OF UPDATE
AS
BEGIN
   SET NOCOUNT ON

   UPDATE MyTable
     SET Column1 = Inserted.Column1
          ,Column2 = Inserted.Column2
          -- Don't set this for the "InsertTime" field.
    FROM Inserted
     INNER JOIN MyTable
     ON Inserted.TheKey = MyTable.TheKey
END 
0 голосов
/ 26 марта 2015

Использование вычисляемого столбца - одно из решений, описанных в этом сообщении: Вычисляемый столбец с текущим значением даты / времени?

0 голосов
/ 10 февраля 2014

Недавно я реализовал очень похожее решение для этого, и мне пришлось преодолеть ряд препятствий, поэтому я публикую здесь решение, надеясь, что оно поможет.

То, что я хотел сделать, это иметь RecordCreatedи столбец LastModified, который управлялся базой данных, а не пользовательским агентом.В этом случае RecordCreated будет датой и временем, когда строка была впервые вставлена, а LastModified будет последним обновлением строки.Я также хотел запретить пользователю изменять эти столбцы напрямую.Вот что я сделал:

Добавил два столбца в мою таблицу как обнуляемые столбцы SMALLDATETIME:

RecordCreated SMALLDATETIME,
LastModified SMALLDATETIME

Создал триггер AFTER для таблицы:

CREATE TRIGGER dbo.WidgetProductionTrigger ON dbo.WidgetProduction AFTER INSERT, UPDATE AS BEGIN

инициировать сначала проверяет, пытался ли пользователь вставить / изменить значения моих столбцов.Я столкнулся с проблемой с функцией UPDATE (), всегда возвращающей true, поэтому потребовалась небольшая дополнительная логика:

DECLARE @RecordCreated SMALLDATETIME;
SELECT @RecordCreated = RecordCreated FROM INSERTED;
IF UPDATE(RecordCreated) AND NOT @RecordCreated IS NULL BEGIN
    RAISERROR('RecordCreated is not user maintainable.', 16, 1);
    ROLLBACK TRANSACTION;
    RETURN;
END;
DECLARE @LastModified SMALLDATETIME;
SELECT @LastModified = LastModified FROM INSERTED;
IF UPDATE(LastModified) AND NOT @LastModified IS NULL BEGIN
    RAISERROR('LastModified is not user maintainable.', 16, 1);
    ROLLBACK TRANSACTION;
    RETURN;
END;

Далее, у меня есть логика для добавления необходимых значений в столбцы после каждой вставки или обновления.Я проверяю, вставляется или обновляется запись, и выполняю соответствующую логику:

IF EXISTS ( SELECT * FROM DELETED ) BEGIN
    UPDATE dbo.WidgetProduction SET
        LastModified = CAST(GETDATE() AS SMALLDATETIME)
    WHERE ProductionRecordID IN (SELECT ProductionRecordID FROM INSERTED);
END ELSE BEGIN
    UPDATE dbo.WidgetProduction SET
        RecordCreated = CAST(GETDATE() AS SMALLDATETIME),
        LastModified = CAST(GETDATE() AS SMALLDATETIME)
    WHERE ProductionRecordID IN (SELECT ProductionRecordID FROM INSERTED);
END;

Это решение работает точно так, как ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...