只有 db_datareader 的数据库显示索引的无效属性

IT *_*her 6 index sql-server ssms sql-server-2008-r2

如果SQL Server数据库的用户只有public在同意server roles且仅用于特定的数据库db_datareader,并public随后试图允许script index as CREATE To在SSMS选项,生成的脚本不正确。

我的意思是,如果索引具有过滤条件,则不会显示该过滤条件

所以对于拥有所有者权限的用户script index as CREATE To将显示

USE [test]
GO

/****** Object:  Index [filtered]    Script Date: 12/30/2013 18:54:19 ******/
CREATE NONCLUSTERED INDEX [filtered] ON [dbo].[Table_1] 
(
    [b] ASC
)
WHERE ([Table_1].[b] IS NULL)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

对于只有db_datareader权限的用户script index as CREATE To将显示

USE [test]
GO

/****** Object:  Index [filtered]    Script Date: 12/30/2013 18:55:13 ******/
CREATE NONCLUSTERED INDEX [filtered] ON [dbo].[Table_1] 
(
    [b] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

如果db_datareader不允许用户查看索引的脚本并显示拒绝访问错误,那将是可以的。但它显示无效的脚本。此外,如果检查索引属性,则仅不显示过滤条件并显示索引的其他属性。为什么会发生这种情况?

Edw*_*and 6

这是设计使然。

我可以理解为什么能够看到部分元数据会令人困惑。但是,数据角色 db_datareader 背后的想法是授予用户对用户数据和列信息的读取访问权限。(如果您也无权访问列名,则无法创建 SELECT 语句。)

因此,考虑到这一点,仅显示包含列信息的索引定义部分将完全在 datareader 权限的范围内。

然而,过滤的索引子句被认为是非列信息,因此您需要更多权限才能看到定义的这一部分。

您需要对该对象的 VIEW DEFINITION 权限,或 VIEW ANY DEFINITION 才能看到额外的元数据位。

我认为如果他们在您生成“不完整”的 CREATE 脚本时发出警告会很好。

你可以自己测试一下:

--create a database
CREATE DATABASE [testdb]
go

--change context to new database
USE [testdb]
GO

--create table
CREATE TABLE [testtable] ( col1 int, col2 int)
GO

--create filtered index
CREATE INDEX [fix_testtable_col1] ON [testtable](col1) WHERE col1 is not null
GO

--create a login
CREATE LOGIN [testlogin] WITH   PASSWORD=N'test', 
                                CHECK_EXPIRATION=OFF, 
                                CHECK_POLICY=OFF

--create a user in your database
CREATE USER [testlogin] FOR LOGIN [testlogin]

--add the user to the data reader role
EXEC sp_addrolemember N'db_datareader', N'testlogin'


--Change your execution contect to the new user with just datareader rights.
EXECUTE AS LOGIN='testlogin'

--try and view the filter definition of the index. It will not show the definition.
SELECT  name,
        has_filter, 
        filter_definition 
FROM sys.indexes
WHERE name='fix_testtable_col1'

--go back to being you
REVERT

--try and view the filter definition of the index. It will succeed.
SELECT  name,
        has_filter, 
        filter_definition 
FROM sys.indexes
WHERE name='fix_testtable_col1'

--give the user VIEW DEFINITION rights
GRANT VIEW DEFINITION ON OBJECT::testTable to testlogin

--switch context once again
EXECUTE AS LOGIN='testlogin'

--try and view the filter definition of the index. this time it will work.
SELECT  name,
        has_filter, 
        filter_definition 
FROM sys.indexes
WHERE name='fix_testtable_col1'


--don't forget to switch back to being you.
REVERT
Run Code Online (Sandbox Code Playgroud)