AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 4721
Accepted
Chau
Chau
Asked: 2011-08-18 02:36:08 +0800 CST2011-08-18 02:36:08 +0800 CST 2011-08-18 02:36:08 +0800 CST

PostgreSQL:使用其他表中的模式和表名?

  • 772

考虑一下我的所有模式名称都在一个表中,而我的所有表名都在另一个表中的情况。

是否可以执行以下操作(伪代码)?

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

还是我必须将查询分解为三个 SELECT?

postgresql dynamic-sql
  • 2 2 个回答
  • 15839 Views

2 个回答

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2011-11-09T22:32:38+08:002011-11-09T22:32:38+08:00

    杰克已经展示了要走的路。不过,我觉得还有改进的余地。

    测试设置:

    -- meta tables for schema and table name    
    CREATE TABLE schma(schma_id int, schma text);
    INSERT INTO  schma VALUES (1, 'x');
    
    CREATE TABLE tbl(tbl_id int, tbl text);
    INSERT INTO  tbl VALUES (1, 't1'), (2, 't2');
    
    -- dummy tables to be used in example query:
    CREATE TABLE t1(id int);
    INSERT INTO  t1 VALUES (1),(2);
    
    CREATE TABLE t2(foo text);
    INSERT INTO  t2 VALUES ('some text'), ('some more text');
    

    2017年更新功能format();2021年格式化:

    CREATE OR REPLACE FUNCTION f_dynaquery(_schma_id int
                                         , _tbl_id int
                                         , _col text
                                         , _type anyelement)
      RETURNS TABLE(col anyelement)
      LANGUAGE plpgsql 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$;
    
    COMMENT ON FUNCTION 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)';
    

    db<>在这里摆弄

    称呼:

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

    该函数可以返回任何类型的任何列。
    阅读有关多态类型和声明函数参数的手册。

    用于format()防御 SQL 注入。看:

    • PL/pgSQL regclass 引用名为 like 关键字的表

    根据请求通过查询检索表名。

    为返回的列命名,以便于引用。

    原答案:

    CREATE OR REPLACE FUNCTION f_dynaquery_old(int, int, _col text, _type anyelement, OUT col anyelement)
      RETURNS SETOF anyelement
      LANGUAGE plpgsql 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$;
    

    quote_ident()通过使用和强制转换来regclass防御 SQL 注入。

    • 8
  2. Jack Douglas
    2011-08-18T03:17:31+08:002011-08-18T03:17:31+08:00

    您需要动态 SQL - 可能是这样的:

    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)
    

    我假设每个表都存在于每个模式中,正如问题所暗示的那样

    • 7

相关问题

  • 我可以在使用数据库后激活 PITR 吗?

  • 运行时间偏移延迟复制的最佳实践

  • 存储过程可以防止 SQL 注入吗?

  • PostgreSQL 中 UniProt 的生物序列

  • PostgreSQL 9.0 Replication 和 Slony-I 有什么区别?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve