请不要为此使用UI。这是一个混乱的混乱。
在我看来,您想要的是在数据库中为特定登录名创建用户,该用户仅具有从一个视图中进行选择的权限。因此,由于您已经创建了登录名:
USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO
此处的编辑是一个脚本示例,该脚本将导致您提到的错误。
首先,在unrelated_db中创建一些表:
CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO
现在创建一个相对受限的登录名:
USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO
现在创建一个将视图保存在其中的数据库,并将登录名添加为用户:
CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO
现在创建一个函数,该函数将引用另一个数据库中的表,以及另一个表的同义词:
CREATE FUNCTION dbo.checkbar()
RETURNS INT
AS
BEGIN
RETURN
(
SELECT TOP (1) bar
FROM unrelated_db.dbo.foo
ORDER BY bar
);
END
GO
CREATE SYNONYM dbo.foo FOR unrelated_db.dbo.foo;
GO
现在创建一个本地表:
CREATE TABLE dbo.PaymentDetails
(
PaymentID INT
);
GO
现在创建一个观点,即引用表,函数和同义词,并授予SELECT
到username
:
CREATE VIEW dbo.SomeView
AS
SELECT
p.PaymentID,
x = dbo.checkbar(), -- function that pulls from other DB
y = (SELECT bar FROM dbo.foo) -- synonym to other DB
FROM dbo.PaymentDetails AS p;
GO
GRANT SELECT ON dbo.SomeView TO username;
GO
现在尝试执行为,username
并从视图中仅选择本地列:
EXECUTE AS USER = 'username';
GO
-- even though I don't reference any of the columns
-- in the other DB, I am denied SELECT on the view:
SELECT PaymentID FROM dbo.SomeView;
GO
REVERT;
GO
结果:
消息916,级别14,状态1,第3
行在当前安全上下文下,服务器主体“用户名”无法访问数据库“ unrelated_db”。
现在将视图更改为不引用任何外部对象,然后SELECT
再次运行上面的命令,它可以工作:
ALTER VIEW dbo.SomeView
AS
SELECT
p.PaymentID
--x = dbo.checkbar(),
--y = (SELECT bar FROM dbo.foo)
FROM dbo.PaymentDetails AS p;
GO
如果没有向我们显示付款明细,帐户明细和MyView对象的脚本,也许您可以让我们知道该查询是否返回任何结果。您可以通过目录视图找到对各种对象的引用sys.sql_expression_dependencies
,但是这种视图不是完美的-我相信它取决于按顺序刷新的所有视图(例如,在视图引用其他视图或基础架构已更改的情况下)准确地说。
DECLARE
@dbname SYSNAME = N'unrelated_db',
@viewname SYSNAME = N'dbo.SomeView';
SELECT DISTINCT
[This object] =
OBJECT_SCHEMA_NAME([referencing_id])
+ '.' + OBJECT_NAME([referencing_id]),
[references this object] =
OBJECT_SCHEMA_NAME([referenced_id])
+ '.' + OBJECT_NAME([referenced_id]),
[and touches this database] = referenced_database_name,
[and is a(n)] = o.type_desc,
[if synonym, it references] = s.base_object_name
FROM sys.sql_expression_dependencies AS d
LEFT OUTER JOIN sys.objects AS o
ON o.[object_id] = d.referenced_id
LEFT OUTER JOIN sys.synonyms AS s
ON d.referenced_id = s.[object_id]
AND s.base_object_name LIKE '%[' + @dbname + ']%'
WHERE OBJECT_ID(@viewname) IN (
referenced_id,
referencing_id,
(SELECT referencing_id FROM sys.sql_expression_dependencies
WHERE referenced_database_name = @dbname)
) OR referenced_database_name = @dbname;
SQL Server不仅会尝试从中获得unrelated_db
乐趣,而且还需要从您要使用的视图中对该数据库进行一定的限制。不幸的是,如果我们看不到视图定义以及它所涉及的对象的更多详细信息,我们所能做的就是推测。我能想到的两个主要问题是使用三部分名称的同义词或函数,但是看到实际的脚本将为我们提供一个更好的主意,而不是猜测。:-)
您可能还需要检查sys.dm_sql_referenced_entities
,但是该函数在上面的示例中没有返回任何有用的信息。