PostgreSQL: Sử dụng lược đồ và tên bảng từ các bảng khác?


8

Hãy xem xét tình huống trong đó tôi có tất cả các tên lược đồ của mình trong một bảng và tất cả các tên bảng của tôi trong một bảng khác.

Có thể làm một cái gì đó như sau (mã giả)?

SELECT value FROM (SELECT schema_name FROM schemas).(SELECT table_name FROM tables)

Hay tôi phải chia nhỏ truy vấn thành ba CHỌN?

Câu trả lời:


7

Jack đã chứng minh con đường để đi. Tuy nhiên, tôi cảm thấy có chỗ để cải thiện.

Tôi đặt mọi thứ trong lược đồ xđể thử nghiệm thuận tiện. Thiết lập thử nghiệm:

DROP SCHEMA x CASCADE;
CREATE SCHEMA x;

-- meta tables for schema and table name    
CREATE TABLE x.schma(schma_id int, schma text);
INSERT INTO  x.schma VALUES (1, 'x');

CREATE TABLE x.tbl(tbl_id int, tbl text);
INSERT INTO  x.tbl VALUES (1, 't1'), (2, 't2');

-- dummy tables to be used in example query:
CREATE TABLE x.t1(id int);
INSERT INTO  x.t1 VALUES (1),(2);

CREATE TABLE x.t2(foo text);
INSERT INTO  x.t2 VALUES ('some text'), ('some more text');

Hàm cũ (câu trả lời gốc):

CREATE OR REPLACE FUNCTION x.f_dynaquery_old(int, int, _col text, _type anyelement, OUT col anyelement)
  RETURNS SETOF anyelement AS
$func$
BEGIN
   RETURN QUERY EXECUTE '
   SELECT ' || quote_ident(_col) || '
   FROM   ' || (
       (SELECT schma FROM schma WHERE schma_id = $1) || '.' ||
       (SELECT tbl   FROM tbl   WHERE tbl_id   = $2))::regclass;
END
$func$  LANGUAGE plpgsql;

Phiên bản sạch hơn với format()(bản cập nhật 2017):

CREATE OR REPLACE FUNCTION x.f_dynaquery(_schma_id int, _tbl_id int
                                       , _col text, _type anyelement)
  RETURNS TABLE(col anyelement) AS
$func$
BEGIN
   RETURN QUERY EXECUTE format(
      'SELECT %I FROM %I.%I'
    , _col
    , (SELECT schma FROM schma WHERE schma_id = _schma_id)
    , (SELECT tbl   FROM tbl   WHERE tbl_id   = _tbl_id)
   );
END
$func$  LANGUAGE plpgsql;

COMMENT ON FUNCTION x.f_dynaquery(int, int, text, anyelement)
IS 'Query any column from a dynamically assembled tablename.
$1 .. id of schema
$2 .. id of table
$3 .. name of column
$4 .. type of column (only data type matters, not the value)';

Gọi:

SELECT col FROM x.f_dynaquery(1, 1, 'id', NULL::int);
  col
-----
   1
   2


SELECT col FROM x.f_dynaquery(1, 2, 'foo', NULL::text);
  col
----------------
 some text
 some more text

Những điểm chính


@JackDoumund: Tôi đã xây dựng trên ví dụ của bạn, vì vậy bạn có thể quan tâm đến cái này.
Erwin Brandstetter

1
Tôi tình cờ tìm thấy điều này - '@' sẽ không đến được với tôi nếu tôi không phải là người đăng trừ khi tôi đã nhận xét về bài đăng! Nghĩ rằng bạn muốn biết :)
Jack nói hãy thử topanswers.xyz

@JackDoumund: Ah, tôi không biết rằng một nhận xét như vậy không đến được với bạn. Cảm ơn bạn về thông tin!
Erwin Brandstetter

6

Bạn cần SQL động - có lẽ giống như thế này:

create role stack;
create schema authorization stack;
set role stack;

create or replace function f(p_schema in text, p_table in text)
                           returns setof integer language plpgsql immutable as $$
begin
  return query execute 'select value from '||p_schema||'.'||p_table;
end;$$;

create table t1(value integer);
insert into t1(value) values (1);
insert into t1(value) values (2);

create table t2(value integer);
insert into t2(value) values (1);

create table schemas(schema_name text);
insert into schemas(schema_name) values ('stack');

create table tables(table_name text);
insert into tables(table_name) values ('t1');
insert into tables(table_name) values ('t2');
insert into tables(table_name) values ('t1');
insert into tables(table_name) values ('t2');

select f(schema_name, table_name) from schemas cross join tables;
 f
---
 1
 2
 1
(3 rows)

Tôi giả sử rằng mỗi bảng có mặt trong mọi lược đồ như câu hỏi ngụ ý

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.