为了便于讨论,让我们创建新的 LOGIN、新的 SCHEMA 和新的用户。
use master
GO
CREATE LOGIN SO_Login WITH PASSWORD = 'Dont1Use2This3In4Production'
GO
Use AdventureWorks2019
GO
CREATE SCHEMA SO_Schema
GO
CREATE USER SO_User FOR LOGIN SO_Login;
GO
理论上,你可以得到你正在寻找的东西,只需有一个允许在特定模式上创建 TABLE 的规则。比如:GRANT CREATE TABLE ON SCHEMA::SO_Schema TO public;
在这种情况下,我们可以为每个人提供在架构上创建 TABLE 的选项,并在 CREATE TABLE 上使用简单的 DDL 触发器,以便为创建表的用户添加 SELECT、DELETE、INSERT、UPDATE 等权限。
很遗憾,GRANT CREATE TABLE ON SCHEMA 不受支持。
要创建 TABLE,您需要在数据库中拥有 CREATE TABLE 权限,并在其中创建表的 SCHEMA 上拥有 ALTER 权限。
https://docs.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql?view=sql-server-ver15#permissions-1
这使任务更加复杂,并且在大多数情况下可能不推荐,因为您需要提供比您真正希望用户拥有的权限更多的权限...
如果您仍然想完成这项工作(反对建议),那么您需要在数据库上 GRANT ALTER ON SCHEMA 和 GRANT CREATE TABLE 给所有人 - 都意味着“公共”
use AdventureWorks2019
GO
GRANT ALTER ON SCHEMA::SO_Schema TO public;
GO
GRANT CREATE TABLE TO public;
GO
接下来,您将需要拒绝不常见的权限,因为上述内容将为所有用户提供比您想要的更多的权力!
这可以通过在 DATABASE 上为任何 DDL_DATABASE_LEVEL_EVENTS 创建 DDL TRIGGER 来完成
https://docs.microsoft.com/en-us/sql/relational-databases/triggers/ddl-event-groups?view=sql-server-ver15
在 TRIGGER 中,您应该检查事件是什么。如果它不是 CREATE_SCHEMA 或执行事件的 USER 不应该 CREATE SCHEMA 那么你ROLLBACK TRANSACTION;。
注意!由于您不想在每次新用户需要创建 TABLE 时更改触发器并将 USER 名称添加到可以创建 TABLE 的硬编码用户列表中,所以最好创建新角色并将您需要的每个用户添加到此角色
CREATE ROLE ModifyTable;
GO
在这种情况下,您基于类似上述ModifyTable 的角色,您可以仅将 GRANT ALTER ON SCHEMA 和 GRANT CREATE TABLE 授予 ROLE ModifyTable 而不是 public
此外,在同一个 TRIGGER 中,如果 USER 是应该能够创建表的人之一,那么您应该授予他对他刚刚创建的表的 INSERT、DELETE、UPDATE、SELECT 权限。
请记住,如果您忘记拒绝此 USER 或所有其他人的权限,那么您可能会遇到安全问题 - 这就是不推荐此过程的原因。
您最好的选择是重新设计系统,这样您就不需要这种精确的招聘。所以...您可以按照我在此处的说明进行操作,但在大多数情况下不建议这样做。
一个更好的方法是不允许用户创建表,除了你可以信任的所有表。您应该直接或使用您控制的应用程序为您的用户创建表,并授予他们使用他们需要的特定表的权限。不建议将 ALTER SCHEMA 权限授予简单用户!
对架构具有 ALTER 权限的用户可以创建架构所有者拥有的过程、同义词和视图。这些对象将有权(通过所有权链接)访问模式所有者拥有的其他模式中的信息。如果架构的所有者还拥有其他架构,则应尽可能避免授予架构的 ALTER 权限。
https://docs.microsoft.com/en-us/sql/t-sql/statements/grant-schema-permissions-transact-sql?view=sql-server-ver15