Vui lòng không sử dụng UI cho việc này. Đó là một mớ hỗn độn khó hiểu.
Tôi nghe có vẻ như những gì bạn muốn là tạo một người dùng trong cơ sở dữ liệu, để đăng nhập cụ thể, người chỉ có quyền chọn từ một chế độ xem. Vì vậy, vì bạn đã có thông tin đăng nhập được tạo:
USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO
EDIT ở đây là một ví dụ về một kịch bản sẽ dẫn đến lỗi bạn đề cập.
Đầu tiên, tạo một số bảng trong unrelated_db:
CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO
Bây giờ tạo một đăng nhập tương đối hạn chế:
USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO
Bây giờ hãy tạo cơ sở dữ liệu nơi chế độ xem sẽ tồn tại và thêm thông tin đăng nhập với tư cách người dùng:
CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO
Bây giờ hãy tạo một hàm sẽ tham chiếu bảng trong cơ sở dữ liệu khác và đồng nghĩa với bảng khác:
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
Bây giờ tạo một bảng cục bộ:
CREATE TABLE dbo.PaymentDetails
(
PaymentID INT
);
GO
Bây giờ hãy tạo một khung nhìn tham chiếu bảng, hàm và từ đồng nghĩa và cấp SELECT
cho 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
Bây giờ hãy thử thực hiện dưới dạng username
và chỉ chọn cột cục bộ từ chế độ xem:
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
Kết quả:
Msg 916, Cấp 14, Trạng thái 1, Dòng 3
"tên người dùng" chính của máy chủ không thể truy cập cơ sở dữ liệu "unrelated_db" trong bối cảnh bảo mật hiện tại.
Bây giờ thay đổi khung nhìn để không tham chiếu bất kỳ đối tượng bên ngoài nào và chạy lại ở trên SELECT
và nó hoạt động:
ALTER VIEW dbo.SomeView
AS
SELECT
p.PaymentID
--x = dbo.checkbar(),
--y = (SELECT bar FROM dbo.foo)
FROM dbo.PaymentDetails AS p;
GO
Không hiển thị cho chúng tôi các tập lệnh cho các đối tượng Chi tiết thanh toán, Chi tiết tài khoản và MyView, có thể bạn có thể cho chúng tôi biết nếu truy vấn này trả về bất kỳ kết quả nào. Bạn có thể tìm thấy các tham chiếu đến các đối tượng khác nhau thông qua chế độ xem danh mục sys.sql_expression_dependencies
, nhưng chế độ xem này không hoàn hảo - tôi tin rằng nó phụ thuộc vào tất cả các chế độ xem được làm mới (ví dụ trong trường hợp các khung nhìn tham chiếu các khung nhìn khác, hoặc lược đồ cơ bản đã thay đổi) theo thứ tự là chính xác.
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 sẽ không cố gắng truy cập unrelated_db
để giải trí cho nó ... phải có một số ràng buộc với cơ sở dữ liệu đó từ chế độ xem bạn đang cố gắng sử dụng. Thật không may nếu chúng ta không thể nhìn thấy định nghĩa chế độ xem và biết thêm chi tiết về các đối tượng mà nó chạm vào, tất cả những gì chúng ta có thể làm là suy đoán. Hai điều chính tôi có thể nghĩ đến là từ đồng nghĩa hoặc hàm sử dụng tên ba phần, nhưng xem các tập lệnh thực tế sẽ cho chúng ta một ý tưởng tốt hơn nhiều thay vì đoán. :-)
Bạn cũng có thể muốn kiểm tra sys.dm_sql_referenced_entities
, tuy nhiên hàm này trả về không có gì hữu ích trong ví dụ trên.