迭代表格

时间:2013-01-31 15:16:27

标签: sql postgresql plpgsql

我需要在几个表上执行相同的操作。现在查询看起来像这样:

create view foobar
as 
select this, that 
from here 
where this=1 
union all 
select this,that 
from there 
where this=1
..... ..... 

等等,对于几个表。所有结果都是联合的。

有没有办法,而不是写这个很长的查询很容易出错,写一些像

for table in here, there, upthere
 do
 select this, that from $table where this=1

然后将它们联合起来。

我现在有查询工作,这需要一段时间,但这只是好奇心,我不知道如何在Google上搜索这个!

2 个答案:

答案 0 :(得分:4)

从您需要的所有表格VIEW中创建UNION,然后SELECTVIEW创建VIEW

此外,您可以像这样创建CREATE OR REPLACE VIEW table_set AS SELECT 'table1' as table_name, field1, field2 ... FROM table1 UNION ALL SELECT 'table2' as table_name, field1, field2 ... FROM table2 UNION ALL SELECT 'table3' as table_name, field1, field2 ... FROM table3 UNION ALL ...

SELECT
来自此VIEW

SELECT field1, field3 FROM table_set WHERE table_name IN ('table2','table4') AND field5 = 'abc' 赞:

{{1}}

答案 1 :(得分:1)

视图 like @Igor desrcibes是一种选择。

如果性能至关重要并且您没有大量的写入操作,则可以使用该视图(重新)创建materialized view

或者,对于源表的较短语法和动态选择,您可以使用像这样的 plpgsql函数

CREATE OR REPLACE FUNCTION f_select_from_tbls(tables text[], cond int)
  RETURNS TABLE (this int, that text) AS
$BODY$
DECLARE
   tbl text; -- automatically avoids SQLi
BEGIN
   FOREACH tbl IN ARRAY tables LOOP
      RETURN QUERY EXECUTE format('
      SELECT this, that
      FROM   %I
      WHERE  this = $1', tbl)
      USING cond;
   END LOOP;
END
$BODY$
  LANGUAGE plpgsql;

呼叫:

SELECT * FROM f_select_from_tbls('{t1,t2,nonStandard tablename}', 4);

我假设有许多表共享相同名称和类型(this int, that text)的列(您没有在问题中定义数据类型。)该函数将array of text作为表名称和integer值为条件。

有关手册中Looping Through Arrays的更多信息 有关Returning From a Function的更多信息,请参阅手册。

使用动态SQL,您必须警惕 SQL注入。这种威胁在两方面得到了中和:

  • 数组tables中的表名称使用函数format()注入,该函数正确引用任何非标准表名称
  • 参数cond中的值通过USING传递,从而使SQLi无法实现。

变体VARIADIC parameter

目的是使函数调用更简单。您可以提交文本变量列表,而不是从中构建数组(数组是从参数内部构建的)。就是这样。

CREATE OR REPLACE FUNCTION f_select_from_tbls2(cond int, VARIADIC tables text[])
  RETURNS TABLE (this int, that text) AS
$BODY$
DECLARE
   tbl text; -- automatically avoids SQLi
BEGIN
   FOREACH tbl IN ARRAY tables LOOP
      RETURN QUERY EXECUTE format('
      SELECT this, that
      FROM   %I
      WHERE  this = $1', tbl)
      USING cond;
   END LOOP;
END
$BODY$
  LANGUAGE plpgsql;

在这种情况下,我将tables放在最后,以便为VARIADIC参数设置一个开放式结尾。 拨打:

SELECT * FROM f_select_from_tbls2(4, 't1','t2','iLLegal name')