Устранение неполадок с видимостью метаданных в распределенных секционированных представлениях

При попытке пользователя с ограниченными правами доступа вставить, изменить или удалить данные через распределенное секционированное представление SQL Server выдает следующее сообщение об ошибке:

Ошибка 4436 «Представление UNION ALL '%.*ls' нельзя обновить, поскольку столбец секционирования не найден.»

Эта проблема не затрагивает локально секционированные представления, поскольку для них все базовые таблицы находятся в одном экземпляре SQL Server.

Объяснение

Для выполнения распределенных запросов SQL Server должен иметь возможность читать определение SQL ограничений CHECK для таблиц на удаленном (подключенном) сервере. Это означает, что объект, вызывающий распределенный запрос, должен иметь разрешения CONTROL, ALTER, TAKE OWNERSHIP или VIEW DEFINITION для соответствующей удаленной таблицы. Если объект, вызывающий распределенный запрос, не имеет одного из этих разрешений, запрос завершится с ошибкой 4436.

ПримечаниеПримечание

Если у пользователя нет хотя бы одного из этих разрешений, значение столбца definition в таблице sys.check_constraints будет равно NULL при запросе пользователя к этому каталогу.

Устранение ошибки 4436

Чтобы определение ограничения CHECK было видно вызывающему объекту, предоставьте ему разрешение VIEW DEFINITION для всех целевых таблиц, формирующих данное распределенное секционированное представление.

Пусть, например Server1 и Server2 — федеративные серверы, определенные как связанные друг с другом. Пусть master.dbo.t1 — секционированная таблица, к которой имеют доступ все члены роли базы данных dpv_users. Пусть dpv_users содержит пользователей, у которых есть доступ SELECT, INSERT, UPDATE и DELETE по данному распределенному секционированному представлению.

Выполните следующий код на каждом связанном сервере.

CREATE TABLE t1(c INT PRIMARY KEY CHECK (...)) ; -- CHECK is different on each server.
GO

GRANT SELECT, INSERT, UPDATE, DELETE, VIEW DEFINITION ON t1 TO dpv_users ;
GO

CREATE VIEW the_dpv AS
    SELECT * FROM Server1.master.dbo.t1
    UNION ALL
    SELECT * FROM Server2.master.dbo.t1 
GO