SQL 服务器 - 授予用户在他们自己的架构中创建 table 的权限,但不能在 dbo 架构中创建

SQL Server - Give user permission to create table in their own schema, but not in dbo schema

我不是 DBA,但被要求帮助为一些内部公司建立教学数据库 SQL 类。我正在使用 Azure SQL 服务器数据库,其中每个学生都需要能够为自己创建 tables、视图和存储过程,但不能看到任何其他学生的工作。由于成本限制,我无法为每个学生创建一个 Azure 数据库并用原始数据加载它,所以我试图在一个数据库中完成这一切。

这是我的想法:

我已经能够创建登录名、用户和模式,并授予对 dbo 模式的读取权限,但我无法让学生完全控制他们自己的模式。

我需要的建议是,我如何设置数据库让每个学生都有自己的模式和写访问权限,但对 dbo 模式有只读访问权限?似乎我可以锁定学生模式,但不能在没有对整个数据库的写访问权限的情况下授予他们对它的写访问权限。有没有办法把它们分开?

此外,关于在同一数据库中分离学生的环境,是否有更好的方法来实现我想要的效果?

这是我目前尝试过的方法:

USE MASTER 
CREATE LOGIN student1 WITH PASSWORD = 'T3mpSuperSecret!';     

USE class_DB 
CREATE USER student1 FOR LOGIN student1; 
CREATE SCHEMA st1 AUTHORIZATION student1; 
GRANT SELECT ON SCHEMA :: dbo TO student1 
GRANT CONTROL ON SCHEMA :: st1 TO student1 

然后我尝试 select 来自 dbo 的基础 table 之一进入新模式:

select * 
into st1.inventories
from dbo.inventories

我得到:

Msg 262, Level 14, State 1, Line 1
CREATE TABLE permission denied in database 'class_DB'.

看起来创建 table 权限是在数据库级别,而不是模式级别。有没有办法在架构级别授权创建 table 权限?

我希望这一切都有意义。同样,我不是 DBA,所以任何帮助将不胜感激。

谢谢!

授予 CREATE TABLE 和其他权限没有任何作用是 USER 也没有 ALTER 权限。因此,您只需要 GRANT USER CREATE TABLECREATE VIEW 等对其特定模式的权限,然后 SELECT dbo 架构。

这与 WITHOUT LOGIN 一起使用作为示例,因为我没有 LOGIN 对象,但这表明已授予并隐式拒绝了权限:

CREATE DATABASE SampleDB;
GO
USE SampleDB;
GO

CREATE TABLE dbo.SomeTable (SomeID int IDENTITY);

INSERT INTO dbo.SomeTable
DEFAULT VALUES;
GO

CREATE USER student1 WITHOUT LOGIN;
GO
CREATE SCHEMA st1 AUTHORIZATION student1;
GO
GRANT SELECT ON SCHEMA::dbo TO student1;
GRANT CREATE TABLE, CREATE VIEW, CREATE FUNCTION, CREATE PROCEDURE TO student1;
GO

CREATE USER student2 WITHOUT LOGIN;
GO
CREATE SCHEMA st2 AUTHORIZATION student2;
GO
GRANT SELECT ON SCHEMA::dbo TO student2;
GRANT CREATE TABLE, CREATE VIEW, CREATE FUNCTION, CREATE PROCEDURE TO student2;
GO

EXECUTE AS USER = 'student1';
GO

CREATE TABLE st1.TestTable (ID int);
INSERT INTO st1.TestTable
SELECT SomeID
FROM dbo.SomeTable;
GO

SELECT *
FROM st1.TestTable;
GO

REVERT;
GO

EXECUTE AS USER = 'student2';
GO

CREATE PROC st2.TestProc AS
BEGIN
    SELECT *
    FROM st1.TestTable;
END;
GO

EXEC st2.TestProc; --fails
GO
CREATE TABLE st1.TestTable (ID int); --fails too
GO

REVERT;
GO

USE master;
GO

DROP DATABASE SampleDB;