Cup*_*ppM 5 sql t-sql sql-server triggers identity
对于具有标识字段的多个表,我们在这些视图上使用视图和替代触发器实现行级安全性方案.这是一个简化的示例结构:
-- Table
CREATE TABLE tblItem (
ItemId int identity(1,1) primary key,
Name varchar(20)
)
go
-- View
CREATE VIEW vwItem
AS
SELECT *
FROM tblItem
-- RLS Filtering Condition
go
-- Instead Of Insert Trigger
CREATE TRIGGER IO_vwItem_Insert ON vwItem
INSTEAD OF INSERT
AS BEGIN
-- RLS Security Checks on inserted Table
-- Insert Records Into Table
INSERT INTO tblItem (Name)
SELECT Name
FROM inserted;
END
go
Run Code Online (Sandbox Code Playgroud)
如果我想插入记录并获取其身份,在实现RLS而不是触发器之前,我使用了:
DECLARE @ItemId int;
INSERT INTO tblItem (Name)
VALUES ('MyName');
SELECT @ItemId = SCOPE_IDENTITY();
Run Code Online (Sandbox Code Playgroud)
使用触发器,SCOPE_IDENTITY()不再起作用 - 它返回NULL.我已经看到了使用OUTPUT子句来获取身份的建议,但我似乎无法让它以我需要的方式工作.如果我在视图插入上放置OUTPUT子句,则不会输入任何内容.
-- Nothing is added to @ItemIds
DECLARE @ItemIds TABLE (ItemId int);
INSERT INTO vwItem (Name)
OUTPUT INSERTED.ItemId INTO @ItemIds
VALUES ('MyName');
Run Code Online (Sandbox Code Playgroud)
如果我将OUTPUT子句放在INSERT语句的触发器中,则触发器返回表(我可以从SQL Management Studio中查看它).我似乎无法在调用代码中捕获它; 通过在该调用上使用OUTPUT子句或使用SELECT*FROM().
-- Modified Instead Of Insert Trigger w/ Output
CREATE TRIGGER IO_vwItem_Insert ON vwItem
INSTEAD OF INSERT
AS BEGIN
-- RLS Security Checks on inserted Table
-- Insert Records Into Table
INSERT INTO tblItem (Name)
OUTPUT INSERTED.ItemId
SELECT Name
FROM inserted;
END
go
-- Calling Code
INSERT INTO vwItem (Name)
VALUES ('MyName');
Run Code Online (Sandbox Code Playgroud)
我唯一能想到的就是使用IDENT_CURRENT()函数.由于这不在当前范围内运行,因此存在并发用户同时插入并弄乱它的问题.如果整个操作都包含在事务中,那会阻止并发问题吗?
BEGIN TRANSACTION
DECLARE @ItemId int;
INSERT INTO tblItem (Name)
VALUES ('MyName');
SELECT @ItemId = IDENT_CURRENT('tblItem');
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
有没有人对如何做得更好有任何建议?
我知道有人会读到这个并说"触发器是邪恶的,不要使用它们!" 虽然我感谢您的信念,但请不要提供"建议".
| 归档时间: |
|
| 查看次数: |
14825 次 |
| 最近记录: |