如何构造SQL语句以跨多个不相关的平面表运行,并显示结果以及结果来自的表的结果和表的名称。
这个场景是我有几个表,每个表都有相同的列名。我收集的是外部各方提供的数据,因为它存放在不同的表格中。
相同的表格如下:
Table 1: pid, parent_name, student_name, student_number, class_name, columnN
Table 2: pid, previous_school, previous_school, student_number, columnN
Table 3: pid, student_name, student_number, parent_name, column4, columnN
Table 14: pid, student_number, parent_name, column4, columnN
Table N: pid, previous_school, parent_name, column4, columnN
我需要一个在所有表中搜索student_name
的SQL语句
在伪代码中:for each table, find a student named john doe and return to me the row where you got the result and the table where you found the result
在以下演示文稿中给出结果:
john doe, Table 1, pid
john doe, Table 9, pid
为了使它有点复杂,列student_name
可能不在所有表中,因此如果在那里找不到列,查询需要慷慨地进行。
答案 0 :(得分:5)
您正在寻找动态SQL。自动从系统目录中汇编查询:
SELECT string_agg('SELECT student_name, '''
|| c.oid::regclass || ''' AS tbl, pid FROM '
|| c.oid::regclass
|| $$ WHERE student_name = 'John Doe'$$
, E'\nUNION ALL\n')
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
WHERE n.nspname = 'public' -- schema name where your tables lie
AND c.relname LIKE 't%' -- and / or filter table names
AND EXISTS (
SELECT 1 FROM pg_attribute
WHERE attrelid = c.oid
AND attname = 'student_name' -- make sure column exists
AND NOT attisdropped -- and is alive
);
生成查询字符串:
SELECT student_name, 'tbl1' AS tbl, pid FROM tbl1 WHERE student_name = 'John Doe'
UNION ALL
SELECT student_name, 'tbl2' AS tbl, pid FROM tbl2 WHERE student_name = 'John Doe'
UNION ALL
SELECT student_name, 'tbl3' AS tbl, pid FROM tbl3 WHERE student_name = 'John Doe'
...
然后在第二次调用中运行它或使用EXECUTE
使用PL / pgSQL函数完全自动化它。例如:
Select a dynamic set of columns from a table and get the sum for each
此查询生成safe code with sanitized identifiers preventing SQL injection.(此处为oid::regclass
的说明。)
还有更多相关答案。 Use a search.
BTW,LIKE
中的student_name LIKE 'John Doe'
毫无意义。如果没有通配符,只需使用=
。
答案 1 :(得分:0)
只需为描述源表的每个选择添加一个文字值:
select student_name, 'Table 1', pid
from table1
where ...
union
select some_name, 'Table 2', pid
from table2
where ...
union
...
答案 2 :(得分:0)
您可以从all_tables视图中获取表的名称,以dinamically方式创建union查询,然后使用execute immediate执行它。这样的事情 - 小心代码可能有错误 - :
DECLARE
v_query VARCHAR2(4000) := '';
v_student_name VARCHAR2(50) := 'John Doe';
type r_results is record (
student_name VARCHAR2(500),
table_name VARCHAR2(100),
pid NUMBER
);
v_results r_results;
CURSOR c_tables IS
SELECT table_name
FROM all_tables
WHERE upper(table_name) LIKE '%_STUDENT_RECORDS';
BEGIN
FOR client_table IN c_tables LOOP
IF v_query IS NOT NULL THEN
v_query := v_query || ' UNION ';
END IF;
v_query := v_query || 'SELECT student_name, ' || client_table.table_name || ', ' || pid FROM ' || client_table.table_name || ' WHERE student_name = ''' || v_student_name || '''';
END LOOP;
EXECUTE IMMEDIATE v_query INTO v_results;
END;