Я запускаю SQL Server 2008. Я написал код, который должен быть достаточно безопасным, чтобы предотвратить удаление или обновление любых записей, но было бы намного счастливее, если бы я мог сделать это в базе данных уровень. Можно ли пометить таблицу так, чтобы после того, как была вставлена строка, она никогда не может быть изменена или удалена?SQL Server предотвращает обновление или удаление всех записей
ответ
Редактировать в комментариях. Кажется, вы на самом деле ищете версию, которая действительно не должна выполняться с помощью триггеров, но это может быть связано с производительностью и намного большей кодировкой.
Наиболее подходящий метод борьбы с вашей проблемой. Поддержание транзакционных резервных копий каждые X # минут, чтобы вы могли откат, если он перепутался.
Однако sql-сервер имеет 2 метода отслеживания изменений, встроенных в них, которые вы можете исследовать.
- Изменить отслеживание - это просто указывает, была ли запись изменена и действительно полезна при синхронизации изменений с БД. В основном он увеличивает BIGINT для каждой строки для каждой операции, поэтому вам просто нужно проверить записи больше, чем предыдущий номер синхронизации.
- Change Data Capture - это будет захватывать вставку/обновление/удаление и состояние записи (строки).
Для вашего конкретного беспокойства Change Data Capture может быть правдоподобным и способ более прост в обслуживании, чем триггеры. Я не пробовал это сам, потому что для отслеживания изменений было достаточно, потому что для отслеживания изменений было достаточно, но вот ссылка на документацию Microsoft. https://msdn.microsoft.com/en-us/library/cc645937(v=sql.110).aspx
Если вы настаиваете на том, что триггеры здесь будут примером, вам нужно будет сохранить исходный первичный ключ для ссылочного целостности или вы можете не знать, какие изменения вызвали проблему
CREATE TABLE TblName (
PrimaryKeyID INT IDENTITY(1,1) NOT NULL PRIMARY KEY
,Col1 INT NULL
,Col2 INT NULL
,OriginalPrimaryKeyId INT NULL
,CreateDate DATETIME DEFAULT(GETDATE())
,UpdateDate DATETIME DEFAULT(GETDATE())
,IsLatestVersion BIT NOT NULL DEFAULT(1)
)
GO
CREATE TRIGGER dbo.TrigForInsertEnforceVersionColTblName ON dbo.TblName
FOR INSERT
AS
BEGIN
BEGIN TRY
IF (SELECT COUNT(*) FROM TblName WHERE IsLatestVersion <> 1 AND OriginalPrimaryKeyId IS NULL) > 0
BEGIN
;THROW 51000, 'Attempted to insert a record identified as Previous Version without referencing another record', 1
END
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
--this will mean the loss of some Primary Keys but it is better than an
--INSTEAD of INSERT because you wont have to handle the insert code
;THROW
END CATCH
END
GO
CREATE TRIGGER dbo.TriggerName ON dbo.TblName
INSTEAD OF UPDATE, DELETE
AS
BEGIN
BEGIN TRY
IF EXISTS (
SELECT *
FROM
TblName t
INNER JOIN inserted i
ON t.PrimaryKeyID = i.PrimaryKeyID
AND (t.OriginalPrimaryKeyId <> i.OriginalPrimaryKeyId
OR t.IsLatestVersion <> i.IsLatestVersion)
)
BEGIN
;THROW 51000, 'OriginalPrimaryKeyId Column or IsLatestVersion Column was attempted to be updated', 1
END
--don't have to test count can just run the update statement
IF ((SELECT COUNT(*) FROM inserted) > 0)
BEGIN
--It's an UPDATE Operations so insert new row but maintain original primary key
--so you know what the new row is a version of
INSERT INTO dbo.TblName (Col1, Col2, OriginalPrimaryKeyId)
SELECT
i.Col1
,i.Col2
,OriginalPrimaryKeyId = CASE
WHEN t.OriginalPrimaryKeyId IS NULL THEN t.PrimaryKeyID
ELSE t.OriginalPrimaryKeyId
END
FROM
inserted i
INNER JOIN TblName t
ON i.PrimaryKeyID = t.PrimaryKeyID
END
UPDATE t
SET IsLatestVersion = 0
,UpdateDate = GETDATE()
FROM
TblName t
INNER JOIN deleted d
ON t.PrimaryKeyID = d.PrimaryKeyID
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
;THROW
END CATCH
END
Permissions обсуждение:
для уровня строки ничего и блокировать все, включая владелец базы данных роль или администратор вы должны создать триггер. Но эти роли всегда могут удалить триггер и изменить таблицу. Может быть, просто права было бы достаточно, таких как
на всей роли, которая была бы лучше, если вы поставите пользователей в роли
GRANT INSERT ON SchemaName.TableName TO RoleName
DENY UPDATE ON SchemaName.TableName TO RoleName
DENY DELETE ON SchemaName.TableName TO RoleName
ИЛИ для конкретных пользователей те же команды просто изменить RoleName по имени пользователя
DENY UPDATE ON SchemaName.TableName TO UserName
Это даст возможность вставлять, но отменять возможность обновления или удаления записи.
Вы также можете запретить выполнение, изменять, и кучу еще здесь документации от Microsoft: https://msdn.microsoft.com/en-us/library/ms173724.aspx
Использование триггера вместо разрешений безопасности намного грязнее, и если кто-то с достаточным количеством разрешений хочет внести изменения, они по-прежнему может он просто замедлит их, но не сильно. Поэтому, если вы беспокоитесь об этой способности, убедитесь, что у вас хорошие резервные копии.
Я бы не слишком беспокоился о внесении изменений администратором db. моя озабоченность связана с тем, что код будет иметь ошибку, или кто-то напишет новый код и реализует что-то, что изменит запись и вызовет хаос. триггер кажется идеальным, но есть ли способ получить доступ к значениям. например, я хочу, чтобы 1 бит столбца был отключен, когда была сделана новая ревизия. это ведет к записи старой версии, но отключает ее –
@DanHastings, что было бы причиной для резервного копирования транзакций каждые x минут. Версии можно выполнять на уровне БД, но это будет иметь влияние на производительность, а также создаст сложность для разработчиков, которые знают, как писать код на основе правил медленного изменения размеров. Если желательно, чтобы управление версиями, обработка на уровне приложения может быть более уместной в какой-то момент, DBA и разработчик должны доверять друг другу :) Я покажу вам способ сделать это с помощью sql – Matt
- 1. SQL: Удаление повторяющихся записей в SQL Server
- 2. Обновление команды в GridVew обновление всех записей
- 3. Вставка/обновление массовых записей SQL Server
- 4. БД SQL Server - Удаление записей или установка флага IsDeleted?
- 5. Исправлено удаление записей базы данных SQL Server?
- 6. mysql предотвращает удаление записей, которые используются
- 7. sql server список всех похожих записей
- 8. Обновление миллионов записей в SQL Server 2012
- 9. Обновление записей в базе данных SQL Server
- 10. Обновление всех других записей
- 11. InitRow = true удаление всех записей
- 12. Powershell - Удаление всех повторяющихся записей
- 13. Удаление записей из всех таблиц
- 14. SQL-обновление предыдущих записей
- 15. Автоматическое обновление или удаление записей после x времени в coldfusion
- 16. Обновление записей из CVS-файла или удаление всей таблицы?
- 17. Удаление записей в SQL
- 18. SQL - Удаление других записей
- 19. Добавление/обновление/удаление записей календаря Exchange извне?
- 20. Удаление SQL Server 2012
- 21. Обновление функции Обновление всех записей вместо одного
- 22. Обновление записей SQL?
- 23. .Net Мониторинг базы данных SQL Server - вставка, обновление, удаление
- 24. SQL Обновление двух записей
- 25. Обновление записей в sql
- 26. Обновление записей в SQL
- 27. Обновление SQL записей
- 28. Обновление SQL Server
- 29. Эффективное удаление SQL Server 2005
- 30. Обновление SQL Server 6.5
Удаленный, кто ... вы? Другой пользователь?Это либо проблема с разрешениями, либо проблема с SQL-инъекцией в зависимости от того, как вы ее смотрите. – scsimon