использовать выбранное значение в качестве имени таблицы в postgres - PullRequest
2 голосов
/ 03 февраля 2012

Я нашел ответ, но не нашел.

, поэтому у меня есть таблица types

CREATE TABLE types
(
  type_id serial NOT NULL,
  type_name character varying,
  CONSTRAINT un_type_name UNIQUE (type_name)
)

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

Теперь я хочу выполнить запрос, подобный этому:

select type_name, (select count(*) from ???) from types

, чтобы получить список всех имен типов и количество объектов каждого типа.

это можно сделать?

Ответы [ 2 ]

5 голосов
/ 03 февраля 2012

Вы не можете сделать это напрямую в SQL

Вы можете использовать функцию PLpgSQL и динамический SQL

CREATE OR REPLACE FUNCTION tables_count(OUT type_name character varying, OUT rows bigint)
RETURNS SETOF record AS $$
BEGIN
  FOR tables_count.type_name IN SELECT types.type_name FROM types
  LOOP
    EXECUTE 'SELECT COUNT(*) FROM ' || quote_ident(tables_count.type_name) INTO tables_count.rows;
    RETURN NEXT;
  END LOOP;
  RETURN;
END;
$$ LANGUAGE plpgsql;

SELECT * FROM tables_count();
4 голосов
/ 03 февраля 2012

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

Как бы то ни было, то, что вы хотите сделать, не может быть сделано - в чистом SQL.Это можно сделать с помощью функции plpgsql, выполняющей динамический SQL, однако:

CREATE OR REPLACE FUNCTION f_type_ct()
  RETURNS TABLE (type_name text, ct bigint) AS
$BODY$
DECLARE
    tbl     text;
BEGIN
    FOR tbl IN SELECT t.type_name FROM types t ORDER BY t.type_name
    LOOP
        RETURN QUERY EXECUTE
        'SELECT $1, count(*) FROM ' || tbl::regclass
        USING tbl;
    END LOOP;
END;
$BODY$
  LANGUAGE plpgsql;

Вызов:

SELECT * FROM f_type_ct();

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

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

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