Non utilizzare l'interfaccia utente per questo. È un casino confuso.
Mi sembra che quello che vuoi sia creare un utente in un database, per un login specifico, che abbia solo le autorizzazioni per selezionare da una vista. Quindi, poiché hai già creato il login:
USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO
EDIT qui è un esempio di uno script che porterà all'errore menzionato.
Innanzitutto, crea una tabella in unrelated_db:
CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO
Ora crea un accesso relativamente limitato:
USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO
Ora crea un database in cui vivrà la vista e aggiungi il login come utente:
CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO
Ora crea una funzione che farà riferimento alla tabella nell'altro database e un sinonimo all'altra tabella:
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
Ora crea una tabella locale:
CREATE TABLE dbo.PaymentDetails
(
PaymentID INT
);
GO
Ora crea una vista che faccia riferimento alla tabella, alla funzione e al sinonimo e concedi SELECT
a 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
Ora prova a eseguire as username
e seleziona solo la colonna locale dalla vista:
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
Risultato:
Messaggio 916, livello 14, stato 1, riga 3
L'entità server "nome utente" principale non è in grado di accedere al database "unrelated_db" nel contesto di protezione corrente.
Ora cambia la vista per non fare riferimento a nessun oggetto esterno ed esegui di SELECT
nuovo quanto sopra e funziona:
ALTER VIEW dbo.SomeView
AS
SELECT
p.PaymentID
--x = dbo.checkbar(),
--y = (SELECT bar FROM dbo.foo)
FROM dbo.PaymentDetails AS p;
GO
A corto di mostrarci gli script per i dettagli di pagamento, i dettagli dell'account e gli oggetti MyView, forse puoi farci sapere se questa query restituisce risultati. Puoi trovare riferimenti a vari oggetti attraverso la vista del catalogo sys.sql_expression_dependencies
, ma questa vista non è perfetta - credo che dipenda da tutte le viste da aggiornare (nel caso in cui le viste facciano riferimento ad altre viste, ad esempio, o lo schema sottostante sia cambiato) in ordine per essere precisi.
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 non tenterà solo di accedervi unrelated_db
per divertimento ... deve esserci un legame con quel database dalla vista che stai cercando di usare. Sfortunatamente se non riusciamo a vedere la definizione della vista e ulteriori dettagli sugli oggetti che tocca, tutto ciò che possiamo fare è speculare. Le due cose principali a cui riesco a pensare sono i sinonimi o le funzioni che usano nomi in tre parti, ma vedere gli script reali ci darà un'idea molto migliore invece di indovinare. :-)
Potresti anche voler controllare sys.dm_sql_referenced_entities
, tuttavia questa funzione non restituisce nulla di utile nell'esempio sopra.