Por favor, no use la interfaz de usuario para esto. Es un desastre confuso.
Me parece que lo que quieres es crear un usuario en una base de datos, para un inicio de sesión específico, que solo tiene permisos para seleccionar desde una vista. Entonces, como ya ha creado el inicio de sesión:
USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO
EDITAR aquí es un ejemplo de una secuencia de comandos que conducirá al error que mencionas.
Primero, cree una tabla en el unrelated_db:
CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO
Ahora cree un inicio de sesión relativamente restringido:
USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO
Ahora cree una base de datos donde vivirá la vista y agregue el inicio de sesión como usuario:
CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO
Ahora cree una función que haga referencia a la tabla en la otra base de datos, y un sinónimo de la otra tabla:
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
Ahora cree una tabla local:
CREATE TABLE dbo.PaymentDetails
(
PaymentID INT
);
GO
Ahora cree una vista que haga referencia a la tabla, la función y el sinónimo, y otorgue 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
Ahora intente ejecutar como username
y seleccione solo la columna local de la 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
Resultado:
Mensaje 916, Nivel 14, Estado 1, Línea 3
El "nombre de usuario" principal del servidor no puede acceder a la base de datos "unrelated_db" en el contexto de seguridad actual.
Ahora cambie la vista para no hacer referencia a ningún objeto externo y ejecute lo anterior SELECT
nuevamente, y funciona:
ALTER VIEW dbo.SomeView
AS
SELECT
p.PaymentID
--x = dbo.checkbar(),
--y = (SELECT bar FROM dbo.foo)
FROM dbo.PaymentDetails AS p;
GO
A menos que nos muestre los scripts para los detalles de pago, detalles de cuenta y objetos MyView, tal vez pueda informarnos si esta consulta devuelve algún resultado. Puede encontrar referencias a varios objetos a través de la vista de catálogo sys.sql_expression_dependencies
, pero esta vista no es perfecta; creo que depende de que todas las vistas se actualicen (en el caso de que las vistas hagan referencia a otras vistas, por ejemplo, o el esquema subyacente haya cambiado) en orden ser preciso.
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 no solo intentará acceder unrelated_db
por diversión ... debe haber algún vínculo con esa base de datos desde la vista que está tratando de usar. Desafortunadamente, si no podemos ver la definición de la vista y más detalles sobre los objetos que toca, todo lo que podemos hacer es especular. Las dos cosas principales en las que puedo pensar son sinónimos o funciones que usan nombres de tres partes, pero ver los scripts reales nos dará una idea mucho mejor en lugar de adivinar. :-)
Es posible que también desee verificar sys.dm_sql_referenced_entities
, sin embargo, esta función no devuelve nada útil en el ejemplo anterior.