我正在運行SQL Server 2008.我編寫的代碼應該是非常安全的,以防止刪除或更新任何記錄,但如果我可以在數據庫執行此操作會更快樂水平。是否可以標記一張表,以便一旦插入一行就永遠不會被修改或刪除?SQL Server阻止所有記錄被更新或刪除
回答
按照評論編輯。看起來你實際上是在尋找版本控制,它不應該通過觸發器來完成,但它可以帶來性能影響和更多的編碼。
最合適的方法來打擊您的疑慮。每隔X分鐘維護一次事務備份,這樣您可以在回滾時回滾。
但是,sql-server確實有2個內置的變更追蹤方法可供您探索。
- 更改跟蹤 - 它只是簡單地標識記錄是否被修改,並且在將更改同步到數據庫時非常有用。基本上,對於每個操作,每增加一個BIGINT行,所以你只需要檢查大於先前同步數的記錄。
- 更改數據捕獲 - 這將捕獲插入/更新/刪除以及記錄(行)的狀態。
對於您的情況特別令人擔憂變化數據捕捉可能是可行的和更多的方式易於維護比觸發器。我沒有自己嘗試過,因爲更改跟蹤足以滿足我的需求,但是這裏有一個鏈接到微軟的文檔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
權限討論:
對於任何行級和阻止每個人,包括數據庫所有者的角色,或者你需要創建一個觸發管理員。但是這些角色總是可以刪除觸發器並修改表格。也許簡單的權限就足夠了,如
對整個角色,如果你把用戶的角色
GRANT INSERT ON SchemaName.TableName TO RoleName
DENY UPDATE ON SchemaName.TableName TO RoleName
DENY DELETE ON SchemaName.TableName TO RoleName
或特定用戶相同的命令只是更改角色名,以用戶名這將是最
DENY UPDATE ON SchemaName.TableName TO UserName
這將授予插入但撤消更新或刪除記錄的能力。
您也可以拒絕執行,修改,和一幫更這裏是微軟的文檔:https://msdn.microsoft.com/en-us/library/ms173724.aspx
使用觸發器,而不是安全權限是很多混亂,如果有人有足夠的權限,要做出改變,他們仍然它可能會減緩他們的速度,但不會太大。所以如果你擔心這種能力,確保你有很好的備份。
我不會太擔心數據庫管理員進行更改。我更擔心的是代碼會有bug,或者有人會編寫一些新代碼並實現一些能夠修改記錄並導致混亂的東西。觸發似乎是完美的,但有沒有辦法獲得價值。例如,我希望允許在創建新版本時禁用1位列。這會保留舊版本的記錄,但會將其禁用 –
@DanHastings,這將成爲每x分鐘進行一次事務備份的原因。版本控制可以在數據庫級別完成,但會對性能產生影響,並且還會爲知道如何根據漸變維度規則編寫代碼的開發人員帶來複雜性。如果需要版本控制,那麼在應用程序級別處理它可能更適合於某些時候,DBA和開發人員需要相互信任:)我將向您展示一種使用SQL執行此操作的方法,儘管 – Matt
- 1. 刪除或更新SQL記錄
- 2. 從CVS文件更新記錄或刪除所有表?
- 3. VB.NET LINQ to SQL刪除所有記錄
- 4. 更新記錄 - SQL SERVER
- 5. SQL Server:更新包含URL的記錄以刪除querystrings
- 6. 觸發記錄插入/更新/刪除的值SQL Server 2016
- 7. 觸發記錄插入/更新/刪除的值SQL Server 2012
- 8. SQL Server中執行所有子記錄的刪除父
- 9. 爲什麼我無法更新或刪除SQL Server中的某些記錄?
- 10. 更新和刪除記錄
- 11. 從臨時表中刪除記錄時將被刪除的所有記錄
- 12. 刪除所有舊記錄
- 13. 級聯刪除或添加記錄(插入,更新,刪除)
- 14. Postgres pg_try_advisory_lock阻止所有記錄
- 15. 如何防止子記錄被刪除
- 16. 更新所有記錄,除非值=「ABC」
- 17. 刪除重複記錄的SQL Server
- 18. SQL Server不會刪除記錄
- 19. 刪除重複記錄在SQL Server
- 20. 不能從SQL Server CE刪除記錄
- 21. SQL Server 2014 - 如何刪除空記錄
- 22. 刪除SQL Server中的重複記錄?
- 23. SQL Server的SQL語句 - 更新記錄
- 24. 如何在SQL Server 2008中刪除所有詳細記錄時自動刪除主記錄?
- 25. DispatcherTimer阻止UI被更新?
- 26. 如何刪除父記錄時刪除所有子記錄?
- 27. SQL服務器選擇查詢顯示所有記錄被插入的最新記錄整理或更新
- 28. 如何刪除所有重複的記錄,但除了一個在SQL Server
- 29. 如何查找插入,更新或刪除記錄的所有存儲過程?
- 30. PL/SQL更新除最大值外的所有記錄
刪除誰......你?另一位用戶?這可能是權限問題和/或SQL注入問題,具體取決於您查看的方式。 – scsimon