Lütfen bunun için kullanıcı arayüzünü kullanmayın. Bu kafa karıştırıcı bir karmaşa.
Bana sadece bir görünümden seçim yapma izni olan belirli bir giriş için veritabanında bir kullanıcı oluşturmak gibi. Yani, zaten giriş oluşturduğunuzdan:
USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO
Burada DÜZENLE bahsettiğiniz hataya yol açacak bir komut dosyası örneğidir.
İlk olarak, unrelated_db içinde bir tablo oluşturun:
CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO
Şimdi nispeten kısıtlı bir giriş oluşturun:
USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO
Şimdi görünümün yaşayacağı bir veritabanı oluşturun ve girişi kullanıcı olarak ekleyin:
CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO
Şimdi diğer veritabanındaki tabloya başvuracak bir işlev ve diğer tablo ile eşanlamlı oluşturun:
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
Şimdi yerel bir tablo oluşturun:
CREATE TABLE dbo.PaymentDetails
(
PaymentID INT
);
GO
Şimdi tabloya, işleve ve eşanlamı referans alan bir görünüm oluşturun ve SELECT
aşağıdakilere verin 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
Şimdi as komutunu çalıştırmayı deneyin username
ve görünümden yalnızca yerel sütunu seçin:
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
Sonuç:
Msg 916, Seviye 14, Durum 1, Satır 3
Sunucu asıl adı "kullanıcı adı", geçerli güvenlik bağlamı altında "ilgisiz_db" veritabanına erişemiyor.
Şimdi görünümü herhangi bir harici nesneye başvurmayacak şekilde değiştirin ve yukarıdakileri SELECT
tekrar çalıştırın ve çalışır:
ALTER VIEW dbo.SomeView
AS
SELECT
p.PaymentID
--x = dbo.checkbar(),
--y = (SELECT bar FROM dbo.foo)
FROM dbo.PaymentDetails AS p;
GO
Bize Ödeme Ayrıntıları, Hesap Ayrıntıları ve MyView nesneleri için komut dosyaları göstermemek, belki de bu sorgunun herhangi bir sonuç döndürüp döndürmediğini bize bildirebilirsiniz. Katalog görünümü aracılığıyla çeşitli nesnelere referans bulabilirsiniz sys.sql_expression_dependencies
, ancak bu görünüm mükemmel değildir - sırayla yenilenen tüm görünümlere (örneğin görünümlerin diğer görünümlere veya altta yatan şemaya başvurması durumunda) bağlı olduğuna inanıyorum doğru olmak.
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 sadece unrelated_db
eğlenmek için erişmeye çalışmakla kalmayacak ... Kullanmaya çalıştığınız görünümden bu veritabanına bir bağ olması gerekir. Maalesef, görünüm tanımını ve dokunduğu nesneler hakkında daha fazla ayrıntı göremediğimizde, yapabileceğimiz tek şey spekülasyon yapmaktır. Düşünebileceğim iki ana şey eş anlamlılar veya üç bölümlü adlar kullanan işlevlerdir, ancak gerçek komut dosyalarını görmek bize tahmin etmek yerine daha iyi bir fikir verecektir. :-)
Ayrıca kontrol etmek isteyebilirsiniz sys.dm_sql_referenced_entities
, ancak bu işlev yukarıdaki örnekte yararlı hiçbir şey döndürmez.