是否可以对用户(或用户组)在单个数据库中可以使用的物理磁盘空间量设置限制?例如,是否有某种方法可以将模式与文件组相关联,然后为文件组设置最大大小?实际的数据库上会有其他表,因此希望有其他不受限制的文件组。
Aar*_*and 10
如果您的用户在他们自己的架构中拥有创建权限,那么您可以设置一个 DDL 触发器来捕获发生在与您关联的文件组不同的文件组上的表创建。您无法阻止创建该表,但您可以将其回滚并返回错误消息。
首先,让我们向现有数据库添加一个文件组和一个最大大小的文件:
USE [master];
GO
ALTER DATABASE floob ADD FILEGROUP SomeUser;
GO
ALTER DATABASE floob ADD FILE
(
NAME = SomeUser,
FILENAME = 'C:\...wherever...\floob_SomeUser.mdf',
MAXSIZE = 20MB -- your quota, this part is important!
) TO FILEGROUP SomeUser; -- this part is also important!
GO
Run Code Online (Sandbox Code Playgroud)
现在让我们创建一个架构和一个可以控制该架构的登录名:
CREATE SCHEMA SomeUser;
GO
CREATE LOGIN SomeUser WITH PASSWORD = 'foo', CHECK_POLICY = OFF;
GO
USE floob;
GO
CREATE USER SomeUser FROM LOGIN [SomeUser] WITH DEFAULT_SCHEMA = SomeUser;
GO
GRANT CONTROL ON SCHEMA::SomeUser TO dbo;
GRANT CREATE TABLE TO SomeUser;
GO
Run Code Online (Sandbox Code Playgroud)
首先,通过这些设置,该用户无法在 dbo 或除他们自己以外的任何其他架构中创建表,这意味着默认情况下他们只能在其有限的文件 [组] 上创建表。如果您以此用户身份连接到数据库 floob 并尝试在 dbo 中创建一个表:
CREATE TABLE dbo.foo(id INT);
Run Code Online (Sandbox Code Playgroud)
您收到此错误:
消息 2760,级别 16,状态 1,第 1 行
指定的架构名称“dbo”不存在或您无权使用它。
并且由于该用户的 default_schema,不指定 SomeUser 架构仍然会以在 SomeUser 中创建的表结束(尽管您确实应该在这里推动最佳实践,尤其是在这种情况下,并且在创建或引用对象时始终指定架构名称)。
现在我们可以创建一个像这样的触发器,它会在没有指定文件组的情况下回滚整个批处理:
CREATE TRIGGER EnsureFilegroup
ON DATABASE
FOR CREATE_TABLE
AS
BEGIN
DECLARE @e XML = EVENTDATA();
IF @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)') = N'SomeUser'
AND NOT EXISTS (SELECT 1 FROM sys.indexes AS i INNER JOIN sys.data_spaces AS d
ON i.data_space_id = d.data_space_id
WHERE d.name = N'SomeUser'
AND i.[object_id] = OBJECT_ID(
QUOTENAME(@e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)'))
+ '.' + QUOTENAME(@e.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(128)')))
AND i.index_id IN (0,1))
BEGIN
RAISERROR('You must place your objects on the SomeUser filegroup.', 11, 1);
ROLLBACK TRANSACTION;
END
END
GO
Run Code Online (Sandbox Code Playgroud)
保持用户、模式和文件组名称相同特别方便,这样可以更容易地将其作为程序化。您可以首先检查正在使用的架构是否不是您的“无限制”架构之一,然后继续检查将架构名称与文件组名称进行比较。如果不匹配,则该用户有权访问错误的架构并尝试在错误的位置创建对象,并且将引发错误:
ALTER TRIGGER EnsureFilegroup
ON DATABASE
FOR CREATE_TABLE
AS
BEGIN
DECLARE @e XML = EVENTDATA();
IF @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)') <> N'dbo'
-- or NOT IN (N'dbo', N'other unlimited schemas')
BEGIN
IF NOT EXISTS (SELECT 1 FROM sys.indexes AS i INNER JOIN sys.data_spaces AS d
ON i.data_space_id = d.data_space_id
WHERE d.name = @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)')
AND i.[object_id] = OBJECT_ID(
QUOTENAME(@e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)'))
+ '.' + QUOTENAME(@e.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(128)')))
AND i.index_id IN (0,1))
BEGIN
RAISERROR('You must place your objects on your own filegroup.', 11, 1);
ROLLBACK TRANSACTION;
END
END
END
GO
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1165 次 |
最近记录: |