Nie używaj do tego interfejsu użytkownika. To mylący bałagan.
Wydaje mi się, że chcesz utworzyć użytkownika w bazie danych dla określonego loginu, który ma uprawnienia tylko do wyboru z jednego widoku. Skoro masz już utworzone dane logowania:
USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO
EDYCJA tutaj jest przykładem skryptu, który doprowadzi do wspomnianego błędu.
Najpierw utwórz tabelę w unrelated_db:
CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO
Teraz utwórz względnie ograniczony login:
USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO
Teraz utwórz bazę danych, w której będzie wyświetlany widok, i dodaj login jako użytkownik:
CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO
Teraz utwórz funkcję, która będzie odwoływać się do tabeli w innej bazie danych, i synonim do drugiej tabeli:
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
Teraz utwórz lokalny stół:
CREATE TABLE dbo.PaymentDetails
(
PaymentID INT
);
GO
Teraz utworzyć widok, że odniesienia do stołu, funkcja i synonim, a dotacje SELECT
do 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
Teraz spróbuj wykonać jako username
i wybierz tylko lokalną kolumnę z widoku:
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
Wynik:
Msg 916, poziom 14, stan 1, wiersz 3
Główna nazwa serwera „nazwa użytkownika” nie może uzyskać dostępu do bazy danych „unrelated_db” w obecnym kontekście bezpieczeństwa.
Teraz zmień widok, aby nie odwoływał się do żadnych obiektów zewnętrznych, i uruchom SELECT
ponownie powyższe , i to działa:
ALTER VIEW dbo.SomeView
AS
SELECT
p.PaymentID
--x = dbo.checkbar(),
--y = (SELECT bar FROM dbo.foo)
FROM dbo.PaymentDetails AS p;
GO
Zamiast pokazywania nam skryptów dla szczegółów płatności, szczegółów konta i obiektów MyView, może możesz dać nam znać, jeśli to zapytanie zwróci jakiekolwiek wyniki. Można znaleźć odniesienia do różnych obiektów za pośrednictwem widoku katalogu sys.sql_expression_dependencies
, ale ten widok nie jest idealny - uważam, że zależy to od odświeżenia wszystkich widoków (w przypadku, gdy widoki odwołują się na przykład do innych widoków lub do zmieniającego się schematu) w kolejności być punktualnym.
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 nie będzie próbował uzyskać dostępu tylko unrelated_db
dla zabawy ... musi istnieć pewien związek z tą bazą danych z widoku, którego próbujesz użyć. Niestety, jeśli nie widzimy definicji widoku i więcej szczegółów na temat dotykanych przez nią obiektów, możemy jedynie spekulować. Dwie główne rzeczy, o których myślę, to synonimy lub funkcje, które używają trzech części, ale zobaczenie rzeczywistych skryptów da nam znacznie lepszy pomysł, niż zgadywanie. :-)
Możesz także chcieć to sprawdzić sys.dm_sql_referenced_entities
, jednak funkcja ta nie zwraca nic użytecznego w powyższym przykładzie.