PostgreSQL 8.2: требуется наличие определенного столбца в выражении UPDATE - PullRequest
1 голос
/ 08 октября 2009

Я хотел бы заставить пользователя указать источник обновления для некоторой таблицы (sometbl), например. указать 'local' или 'remote' (для col2) - но проверка этого требования должна выполняться на уровне БД, когда оператор UPDATE выполняется так:

UPDATE sometbl SET col1 = 'abc';

должен выдавать ошибку (исключение), но:

UPDATE sometbl SET col1 = 'abc', col2 = 'remote';

... добьется успеха.

Я пытался создать ПЕРЕД обновлением для этой таблицы, но не смог проверить, NEW.col2 был явно установлен.

Я использовал условие

IF NEW.col2 IS NULL THEN 
   RAISE EXCEPTION 'you must specify source of this update (local/remote)'
END IF;

но каждый раз, когда col2 не было указано в обновлении (UPDATE sometbl SET col1 = 'abc')

Я получил текущее значение этого поля в псевдо-переменной NEW.col2 вместо предполагаемого NULL.

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

Ответы [ 5 ]

1 голос
/ 09 октября 2009

Я бы использовал функцию security definer, принадлежащую единственному пользователю, кроме администратора и / или владельца таблицы, который имеет право на обновление sometbl.

Примерно так:

create table sometbl (
  id serial primary key,
  col1 text,
  col2 text not null,
    check (col2 in ('local','remote'))
);
create role sometbl_updater;
grant update on sometbl to sometbl_updater;

create function update_sometbl(integer, text, text)
returns void as
$$
  update sometbl set col1=$2, col2=$3 where id=$1;
$$ security definer volatile language sql;
alter function update_sometbl(integer, text, text)
  owner to sometbl_updater;

Но будьте осторожны с функциями, определяющими безопасность security .

1 голос
/ 09 октября 2009

Как насчет пары триггеров ? Один запускает перед обновлением и устанавливает для столбца значение null. Один запускает после обновления и проверяет (возвращает NULL), если столбец все еще нулевой. (Если триггер возвращает NULL, обновление завершается неудачно.)

0 голосов
/ 12 октября 2009

ОК, прочитав документы и опробовав их, я могу сообщить, что ПЕРЕД триггером - путь. Триггер предоставляет имена NEW и OLD, связанные с новыми и бывшими кортежами. Возврат NULL из триггера BEFORE предотвращает обновление. Следовательно:

CREATE OR REPLACE FUNCTION prevent_not_changing_col2()
  RETURNS trigger AS $$
begin
  if NEW.col2 = OLD.col2 then return NULL; end if;
  return NEW;
end ;
$$ LANGUAGE plpgsql;

CREATE TRIGGER col2_check
  BEFORE UPDATE
  ON sometbl
  FOR EACH ROW
  EXECUTE PROCEDURE prevent_not_changing_col2();
0 голосов
/ 08 октября 2009

Вы можете создать пару хранимых процедур, например

create or replace function update_remote(text) returns void
    as 'update sometbl SET col1 = $1, col2 = ''remote'''
    language SQL
    volatile
    strict;
0 голосов
/ 08 октября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...