Bitte benutzen Sie hierfür nicht die Benutzeroberfläche. Es ist ein verwirrendes Durcheinander.
Es hört sich für mich so an, als ob Sie einen Benutzer in einer Datenbank für ein bestimmtes Login erstellen möchten, der nur die Berechtigung hat, aus einer Ansicht auszuwählen. Also, da Sie bereits das Login erstellt haben:
USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO
BEARBEITEN hier ein Beispiel für ein Skript, das zu dem von Ihnen genannten Fehler führt.
Erstellen Sie zunächst eine Tabelle in der unrelated_db:
CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO
Erstellen Sie jetzt ein relativ eingeschränktes Login:
USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO
Erstellen Sie nun eine Datenbank, in der die Ansicht gespeichert wird, und fügen Sie die Anmeldung als Benutzer hinzu:
CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO
Erstellen Sie nun eine Funktion, die auf die Tabelle in der anderen Datenbank verweist, und ein Synonym für die andere Tabelle:
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
Erstellen Sie nun eine lokale Tabelle:
CREATE TABLE dbo.PaymentDetails
(
PaymentID INT
);
GO
Erstellen Sie nun eine Ansicht , die Referenzen der Tabelle, die Funktion und das Synonym und Erteilung SELECT
zu 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
Versuchen Sie nun, als auszuführen username
und wählen Sie nur die lokale Spalte aus der Ansicht aus:
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
Ergebnis:
Meldung 916, Ebene 14, Status 1, Zeile 3
Der Serverprinzipal "Benutzername" kann im aktuellen Sicherheitskontext nicht auf die Datenbank "unrelated_db" zugreifen.
Ändern Sie nun die Ansicht so, dass keine externen Objekte referenziert werden, und führen Sie die obigen Schritte SELECT
erneut aus.
ALTER VIEW dbo.SomeView
AS
SELECT
p.PaymentID
--x = dbo.checkbar(),
--y = (SELECT bar FROM dbo.foo)
FROM dbo.PaymentDetails AS p;
GO
Sie können uns nicht nur die Skripte für die Zahlungsdetails, Kontodetails und MyView-Objekte anzeigen, sondern auch mitteilen, ob diese Abfrage Ergebnisse liefert. Sie können Verweise auf verschiedene Objekte über die Katalogansicht finden sys.sql_expression_dependencies
, aber diese Ansicht ist nicht perfekt - ich glaube, es hängt davon ab, dass alle Ansichten aktualisiert werden (falls sich Ansichten beispielsweise auf andere Ansichten beziehen oder das zugrunde liegende Schema geändert hat) um genau zu sein.
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 wird nicht nur versuchen, darauf zuzugreifen unrelated_db
Spaß Es muss eine Verbindung zu dieser Datenbank in der Ansicht bestehen, die Sie verwenden möchten. Leider können wir nur spekulieren, wenn wir die Ansichtsdefinition und weitere Details zu den Objekten, die sie berührt, nicht sehen können. Die beiden wichtigsten Dinge, an die ich denken kann, sind Synonyme oder Funktionen, die dreiteilige Namen verwenden. Wenn wir jedoch die tatsächlichen Skripte sehen, erhalten wir eine viel bessere Vorstellung, anstatt zu raten. :-)
Möglicherweise möchten Sie auch überprüfen sys.dm_sql_referenced_entities
, aber diese Funktion gibt im obigen Beispiel nichts Nützliches zurück.