Как гарантировать таблицу с ровно одной строкой и одним столбцом? - PullRequest
1 голос
/ 21 сентября 2019

Использование PostgreSQL 11.5.Мне нужно разрешить таблице разрешить только одну строку и один столбец в ней (не 0 или 2, а ровно 1).Я чувствую, что ADD CONSTRAINT было бы полезно, но я не уверен, что делать.

Я хотел бы иметь возможность обновлять эту строку при необходимости.

Что-то, чтобы сделать следующеедействительный:

 foo
-----
 bar

Но не следующие:

 foo | baz
-----+-----
 bar | bin
-----+-----
     | gar

Ответы [ 3 ]

2 голосов
/ 21 сентября 2019

Вот пример, который может вам помочь:

CREATE TABLE singleton (x SMALLINT NOT NULL UNIQUE CHECK (x=1), foo VARCHAR(10) NOT NULL);

INSERT INTO singleton (x, foo) VALUES (1,'one row');
2 голосов
/ 21 сентября 2019

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

ALTER TABLE <tablename> ADD CONSTRAINT [<name>] CHECK ([pk/unique field] = [constant value]);

В любом случае, так каквы хотите иметь обновляемое поле, вам нужно использовать таблицу с 2 столбцами.Если вам действительно нужна только одна строка (и выбор только foo или создание представления для этой цели не вариант), вы также можете использовать триггеры для вставки и удаления (и отклонять любые операции внутри них, вызывая исключение),Чтобы избежать пустой таблицы (не уверен, если вам нужно), вам также понадобится этот триггер при удалении, ограничение будет недостаточно сильным.Триггеры см. Здесь: https://www.postgresql.org/docs/current/triggers.html

Чтобы избежать дальнейших команд ALTER TABLE (например, добавление столбца) и DROP TABLE, используйте триггер события.Для получения дополнительной информации ознакомьтесь с документацией: https://www.postgresql.org/docs/current/event-triggers.html

Для использования PL / pgSQL с триггерами также обратите внимание на https://www.postgresql.org/docs/current/plpgsql-trigger.html

1 голос
/ 21 сентября 2019

Создайте VIEW в качестве суперпользователя или доверенную роль:

CREATE VIEW onerow AS SELECT 'bar' AS foo;  -- defaults to type text
GRANT SELECT ON onerow TO public;

Создатель является владельцем.Или:

ALTER VIEW onerow OWNER TO postgres;   -- or to a trusted role

Каждый может SELECT из него, как и из любой другой таблицы.
Никто не может добавлять или удалять строки из VIEW - или вообще что-либо изменять с помощью команд DDL.
Только команды DML могут изменить его, и только владельцу или суперпользователю разрешено делать это:

CREATE OR REPLACE VIEW onerow AS 
SELECT 'bar1' AS foo;

Помните, что, в конечном счете, мотивированный суперпользователь может сделать что угодно .

В чрезвычайно загруженной системе может возникнуть проблема с эксклюзивной блокировкой, принятой CREATE OR REPLACE VIEW.Это единственная возможная проблема с этим решением, о которой я только могу подумать.


В качестве альтернативы рассмотрим этот тесно связанный ответ, чтобы разрешить не более одну строку:

Вы можете сделать это и (как суперпользователь):

ALTER TABLE onerow OWNER TO postgres;
REVOKE ALL ON onerow FROM public;
GRANT SELECT ON onerow TO public;

Суперпользователи все еще могут DELETE или TRUNCATE.Вы также можете предотвратить это с помощью TRIGGER или RULE ...

, или вы можете добавить общее TRIGGER с RETURN NULL или RULE с DO INSTEAD NOTHING для INSERT и DELETE ...


Одно отдельное значение может быть альтернативно предоставлено функцией или "глобальной переменной".См .:

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