【发布时间】:2021-08-05 05:41:48
【问题描述】:
我有一个案例,SQL Server 所有权链接似乎不起作用 - 还是我遗漏了什么?
我有两个架构:Schema1 和 Schema2。
在Schema1,我只有SELECT权限,而在Schema2,我只有EXEC权限。
我在Schema2 中调用了一个存储过程,它将一条记录插入到Schema1 的表中。
由于所有权链接,这可以正常工作(即使我在 Schema1 中没有 INSERT 权限)。
现在,当我调用另一个在插入之前关闭表中的标识列的存储过程时,我得到一个错误:
Msg 1088, Level 16, State 11, Procedure Schema2.AddRecordWithSpecificId, Line 7 [Batch Start Line 60]
Cannot find the object "Schema1.MyTable" because it does not exist or you do not have permissions.
如果我将ALTER 权限授予Schema1,它可以正常工作 - 但为什么有必要这样做?为什么在这种情况下模式链接不起作用?
重现问题的脚本:
CREATE DATABASE OwnershipChainingTest
GO
USE OwnershipChainingTest
GO
CREATE SCHEMA Schema1 AUTHORIZATION [dbo]
GO
CREATE SCHEMA Schema2 AUTHORIZATION [dbo]
GO
CREATE TABLE Schema1.MyTable
(
Id int IDENTITY(1,1) NOT NULL,
Title varchar(50) NOT NULL
)
GO
CREATE PROCEDURE Schema2.AddRecord
@title nvarchar(100)
AS
BEGIN
INSERT INTO Schema1.MyTable (Title)
VALUES (@title)
END
GO
CREATE PROCEDURE Schema2.AddRecordWithSpecificId
@id int,
@title nvarchar(100)
AS
BEGIN
SET IDENTITY_INSERT Schema1.MyTable ON
INSERT INTO Schema1.MyTable (Id, Title)
VALUES (@id, @title)
SET IDENTITY_INSERT Schema1.MyTable OFF
END
GO
CREATE USER MyUser WITHOUT LOGIN
GO
CREATE ROLE MyRole AUTHORIZATION [dbo]
GO
EXEC sp_addrolemember MyRole, MyUser
GO
-- With this it works: GRANT SELECT, ALTER ON Schema::Schema1 TO MyRole
GRANT SELECT ON Schema::Schema1 TO MyRole
GO
GRANT EXEC ON Schema::Schema2 TO MyRole
GO
EXEC AS user = 'MyUser'
EXEC Schema2.AddRecord 'hello1'
GO
-- This causes an error
EXEC Schema2.AddRecordWithSpecificId 42, 'hello2'
GO
REVERT;
--SELECT CURRENT_USER
SELECT * FROM Schema1.MyTable
USE MASTER
DROP DATABASE OwnershipChainingTest
GO
【问题讨论】:
-
错误是什么?
-
Msg 1088,级别 16,状态 11,过程 Schema2.AddRecordWithSpecificId,第 7 行 [批处理开始第 60 行] 找不到对象“Schema1.MyTable”,因为它不存在或您没有权限. @Nick.McDermaid
-
@ThomasBoelSigurdsson,我回答了您的问题,但请务必考虑不同用户同时执行
SET IDENTITY_INSERTproc 时的并发影响。 -
@DanGuzman 谢谢。这也是我的想法/恐惧——我只是在任何地方都找不到它的描述。这是并发含义的一个好点。但是,我确实需要能够不时指定一个 id,即使通常 id 将从标识列中提取。有没有办法从表外部的序列中绘制一个 id?例如。你能有一个像识别列这样的东西,你可以在特别的基础上从中提取一个值吗?
-
@ThomasBoelSigurdsson,我认为
SEQUENCE比IDENTITY更适合偶尔的临时值。CREATE SEQUENCE Schema1.MyTable_Sequence AS bigint START WITH 1;CREATE TABLE Schema1.MyTable (Id int NOT NULL CONSTRAINT DF_MyTable_Sequence DEFAULT NEXT VALUE FOR Schema1.MyTable_Sequence,...
标签: sql-server database-design