Каков самый простой способ сделать столбец только для чтения в Oracle?

у нас есть одна из тех странных загадочных ошибок повреждения данных, которые появляются каждые несколько недель, и никто не знает, почему. До сих пор кажется, что первичный ключ в таблице спонтанно меняется, поэтому другие строки, которые указывают на него, теперь перепутаны.

хотя я все еще ищу первопричину этого (невозможно повторить), я хотел бы какой-то временный хак, чтобы предотвратить изменение значения столбца. Вот схема таблицы:

CREATE TABLE TPM_INITIATIVES  ( 
    INITIATIVEID    NUMBER NOT NULL,
    NAME            VARCHAR2(100) NOT NULL,
    ACTIVE          CHAR(1) NULL,
    SORTORDER       NUMBER NULL,
    SHORTNAME       VARCHAR2(100) NULL,
    PROJECTTYPEID   NUMBER NOT NULL,
    CONSTRAINT TPM_INITIATIVES_PK PRIMARY KEY(INITIATIVEID)
    NOT DEFERRABLE
     VALIDATE
)

мы конечно нужно иметь возможность создавать новые строки, но я хочу предотвратить что-либо от изменения INITIATIVEID когда-либо, независимо от того, какие странные запросы выполняются.

некоторые идеи, которые я могу придумать:

  • Я не очень хорошо знаком с разрешениями таблицы на Oracle (я больше Postgres), но не можете ли вы предоставить или запретить права на обновление определенный столбец для всех пользователей? Повлияет ли это на обновления или Вставляет также? Какова будет команда DENY updates для этого колонка?
  • создайте своего рода триггер, который запускается при обновлении строки. Мы можем обнаружить, если INITIATIVEID изменяется, и если это так, бросьте исключение или взрыв?

по крайней мере, мы можем поймать и/или войдите это событие, чтобы увидеть, когда это произойдет и что запрос, который вызывает INITIATIVEID изменить?

спасибо!

3 ответов


если есть дочерние таблицы, заполненные данными, которые ссылаются на INITIATIVEID столбец Oracle должен автоматически затруднять изменение значения первичного ключа, предотвращая создание строк-сирот путем изменения первичного ключа родителя. Так, например, если есть дочерняя таблица, которая имеет ограничение внешнего ключа на TPM_INITIATIVES и в этой дочерней таблице есть строка с INITIATIVEID из 17, вы не сможете изменить INITIATIVEID в строке TPM_INITIAITVES таблица, текущая значение 17. Если в любой дочерней таблице нет строки, которая ссылается на конкретную строку в TPM_INITIATIVES таблица, вы можете изменить значение, но, предположительно, если нет отношений, изменение значения первичного ключа не имеет значения, поскольку оно не может по определению вызвать проблему целостности данных. Конечно, у вас может быть код, который вставляет новую строку в TPM_INITIATIVES новая INITIATIVEID, измените все строки в дочерней таблице, которые ссылаются на старую строку, чтобы ссылаться на новую строку, а затем измените старую строку. Но это не будет поймано ни одним из предложенных решений.

если ваше приложение определило дочерние таблицы, но не объявило соответствующие ограничения внешнего ключа, это был бы лучший способ решить проблему.

это, как говорится, решение Арнона о создании представления должно работать. Вы переименуете таблицу, создадите представление с тем же именем, что и существующая таблица, и (потенциально) определите вместо триггера в представлении, которое просто никогда не обновит


скрыть таблицу за представлением и сделать триггер обновления обновить все, кроме столбца, который вы хотите защитить


второй вариант может быть лучше. Если у вас есть таблица/файл журнала, вы можете попробовать написать сообщение с таким количеством диагностической информации, как вы можете, каждый раз, когда есть попытка изменить значение.