Для аннулирования привилегий используется оператор REVOKE, определяемый следующим синтаксическим правилом:
REVOKE [ GRANT OPTION FOR] privilege_commalist ON privilege_object FROM { PUBLIC | authID_commalist } [ GRANTED BY { CURRENT_USER | CURRENT_ROLE } ] { RESTRICT | CASCADE }
Синтаксис конструкций privilege и privilege_object такой же, как для оператора GRANT. Общий смысл операции должен быть понятен из синтаксиса: у указанных authID аннулируются указанные привилегии доступа к указанному объекту базы данных.
Первой важной особенностью оператора аннулирования привилегий является обязательность указания одного из ключевых слов RESTRICT или CASCADE. Если в операторе содержится RESTRICT, то при выполнении операции система проверит, не передавалась ли какая-либо из указанных привилегий каким-либо authID от того authID, у которого привилегия должна быть аннулирована (это вполне возможно, если ранее привилегия была передана с правом передачи). Если это действительно так, операция не выполняется; в противном случае указанные привилегии у указанных authID аннулируются. Иначе говоря, при наличии ключевого слова RESTRICT не допускается, например, ситуация, показанная на рис.18.2.
На этом рисунке authID1 является владельцем объекта базы данных с именем object и, следовательно, обладает всеми привилегиями над этим объектом. Пунктирной стрелкой обозначена одна из подобных привилегий pr1. От имени authID1 привилегия pr1 была передана authID2 вместе с привилегией на ее дальнейшую передачу. Наконец, от имени authID2 привилегия pr1 была передана authID3. Тогда операция аннулирования этой привилегии от имени authID1 у authID2 при наличии ключевого слова RESTRICT не будет выполнена успешно.
В той же ситуации привилегия была бы аннулирована для authID2 (и для authID3), если бы в операторе GRANT присутствовало ключевое слово CASCADE. В общем случае если выполняется операция REVOKE ... CASCADE, то указанные привилегии аннулируются у всех authID, прямо или косвенно (через промежуточные authID) получивших привилегии от текущего authID SQL-сессии, в которой выполняется данная операция.
Если в операторе содержится раздел GRANT OPTION FOR, но имеется ключевое слово RESTRICT, то указанные привилегии для указанных authID не аннулируются, но у указанных authID аннулируется привилегия передачи данных привилегий (операция должна успешно выполняться только при соблюдении обсуждавшихся ранее условий). Однако если в операторе одновременно содержатся и GRANT OPTION FOR, и CASCADE, то указанные привилегии аннулируются у всех authID, которые прямо или косвенно (через промежуточные authID) получили привилегии от текущего authID SQL-сессии, в которой выполняется данная операция.
Задание в операторе необязательного раздела GRANTED BY позволяет явно указать, что должно использоваться в качестве текущего authID - текущий пользовательский идентификатор или текущее имя роли SQL-сессии. Если раздел GRANTED BY в операторе REVOKE не содержится, то действия производятся от имени текущего authID SQL-сессии (о том, как он определяется, см. выше).
Если текущий (или указанный) authID не обладает ни одной из указанных в операторе REVOKE привилегий, то выполнение операции не производится (фиксируется ошибка). Если authID обладает некоторыми, но не всеми, привилегиями из числа указанных, то операция выполняется по отношению к этим некоторым привилегиям, но выдается предупреждение.
Возможны ситуации, когда у некоторого authID остается некоторая привилегия после выполнения операции аннулирования у этого authID этой привилегии. Одна из таких ситуаций проиллюстрирована на рис.18.3.
Здесь привилегия pr1 передана от authID1 к authID2 вместе с правом на дальнейшую передачу этой привилегии. Далее, привилегия pr1 передается от authID2 к authID3. И затем выполняется прямая передача привилегии от authID1 к authID3 (на самом деле, порядок таких действий не является существенным). Теперь предположим, что от имени authID1 выполняется операция
REVOKE pr1 ON object FROM authID2 CASCADED
В соответствии с правилами SQL:1999 после выполнения этой операции authID3 будет продолжать владеть привилегией pr1 по отношению к объекту object, поскольку получил данную привилегию двумя разными способами. Грубо говоря, операция REVOKE, выполняемая от имени authID1, выполняется только по тем путям графа идентификаторов авторизации и объектов базы данных, которые начинаются с узлов, соответствующих authID, указанных в разделе FROM этой операции.
Далее, напомним, что если при передаче от authID1 к authID2 привилегии на выполнение некоторых действий над некоторой таблицей T (например, UPDATE) явно не указывается список имен столбцов этой таблицы, то привилегия распространяется на все столбцы этой таблицы (включая столбцы, которые, возможно, еще будут созданы). Если действительно использовался такой способ передачи привилегий, то в дальнейшем можно аннулировать привилегию authID2 на модификацию отдельных (уже определенных) столбцов таблицы T, оставив привилегию на модификацию всех остальных столбцов (включая те, которые еще не созданы).
И последнее замечание. Если некоторая привилегия была передана псевдоauthID PUBLIC, то, конечно, этой привилегией обладают все authID. Но нет возможности аннулировать такую привилегию у отдельно указываемого authID. Привилегия была передана всем, и аннулировать ее можно только сразу у всех.