对于具有标识字段几个表,我们使用的意见,而是对这些观点的触发器实现行级安全方案。 下面是一个简化的示例结构:
-- 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
如果我想插入一条记录,并得到其身份,执行RLS INSTEAD OF触发器之前,我使用:
DECLARE @ItemId int;
INSERT INTO tblItem (Name)
VALUES ('MyName');
SELECT @ItemId = SCOPE_IDENTITY();
随着扳机,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');
如果我把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');
我能想到的唯一的事情就是使用IDENT_CURRENT()函数。 因为这并不在当前范围内运行,有并发用户同时插入和搞乱它的问题。 如果整个操作被包裹在一个交易,将防止并发问题?
BEGIN TRANSACTION
DECLARE @ItemId int;
INSERT INTO tblItem (Name)
VALUES ('MyName');
SELECT @ItemId = IDENT_CURRENT('tblItem');
COMMIT TRANSACTION
有没有人对如何做到这一点更好什么建议吗?
我知道人们在那里谁将会阅读本说“触发器是恶,不使用它们!” 虽然我很欣赏你的信念,请不要说提供“建议”。