如何在一张表格上执行SQL查询,且这张表格的名字来源于另一个表格

4

我有一张表格,存储其他表格的名称。例如:

COL_TAB
--------------
TABLE_NAME
--------------
TAB1
TAB2
TAB3

我是一名有帮助的助手,可以为您进行文本翻译。以下是您需要翻译的内容:

我的目标是在这样的表上运行SQL查询:

SELECT * FROM (SELECT TABLE_NAME from COL_TAB WHERE TABLE_NAME = 'TAB1')

谢谢


你需要在存储过程或函数中使用动态SQL来实现这个。 - user330315
是的,使用存储过程我们可以轻松地完成这个任务。有没有不使用存储过程的方法呢? - Pirate
2
不,没有。SQL要求在语句实际执行之前就要了解所有表格(和列)的信息(说实话:需要这样做的数据库模型听起来像是一个非常糟糕的设计)。 - user330315
您不必持久化存储过程。只要登录Oracle,您就可以将该过程作为匿名块运行。请注意,为了返回值,最好使用PL/SQL表结构。 - T Gray
如果表格具有相同的列,并且您事先知道名称,您可以从联合视图中选择,否则可以利用XML进行操作。否则,您将需要动态代码。 - William Robertson
@a_horse_with_no_name 这可能是一个关于如何使用动态查询的学科。 - Tenzin
3个回答

1
一个Oracle SQL查询可以使用动态表名,使用Oracle Data Cartridge和ANY*类型。但在使用这些高级功能之前,请退后一步,问问自己是否真的有必要。
你真的需要一个SQL语句如此动态吗?通常最好由应用程序处理,可以提交不同类型的查询。有许多应用程序编程语言和工具包可以处理意外类型。如果这是仅针对数据库的操作,则通常结果会存储在某个地方,在这种情况下,PL/SQL和动态SQL更容易。
如果您确信已经拥有那些需要完全动态SQL语句的罕见情况之一,您将需要像我的开源项目Method4这样的东西。下载并安装它,然后尝试下面的代码。
模式设置
create table tab1(a number);
create table tab2(b number);
create table tab3(c number);
insert into tab1 values(10);
insert into tab2 values(20);
insert into tab3 values(30);
create table col_tab(table_name varchar2(30), id number);
insert into col_tab values('TAB1', 1);
insert into col_tab values('TAB1', 2);
insert into col_tab values('TAB1', 3);
commit;

Query

select * from table(method4.dynamic_query(
q'[
    select 'select * from '||table_name sql
    from col_tab
    where id = 1
]'));

结果:

A
--
10

你很快会发现,查询中嵌套查询非常困难。可能有更简单的方法来解决这个问题,但这可能需要进行设计更改。

如果我从查询中删除where条件会怎样?select查询会在所有表上执行吗? - Pirate
是的,它可以与多个表一起使用。但是,每行的列类型必须相同。 - Jon Heller

0
我手头没有数据库来测试,但我认为你是在寻找这样的东西:
DECLARE
    -- Create a cursor on the table you are looking through. 
    CURSOR curTable IS 
        SELECT  * 
        FROM    MainTable;

    recTable    curTable%ROWTYPE;
    vcQuery     VARCHAR2(100);
BEGIN
    -- Loop through all rows of MainTable. 
    OPEN curTable;
    LOOP
        FETCH curTable INTO recTable;
        EXIT WHEN curTable%NOTFOUND;

        -- Set up a dynamic query, with a WHERE example. 
        vcQuery := 'SELECT ColumnA, ColumnB FROM ' || recTable.Table_Name || ' WHERE 1 = 1';

        -- Execute the query. 
        OPEN :dyn_cur FOR vcQuery;
    END LOOP;
    CLOSE curTable;
END;
/

0

试一下这个

CREATE OR REPLACE PROCEDURE TEST IS
   sql_stmt    VARCHAR2(200);
   V_NAME     VARCHAR2(20);
BEGIN
   sql_stmt := 'SELECT * FROM ';
   EXECUTE IMMEDIATE sql_stmt|| V_NAME;
END;
更新:存储过程中的选择语句无法正常工作。

在SQL Server中,您可以尝试使用SQL块。

Declare @name varchar2(50)

Select @name='Select * from '+TABLE_NAME from COL_TAB WHERE TABLE_NAME = 'TAB1' 

EXEC(@name);

是的,但我想不使用过程来完成它。 - Pirate
1
那样行不通。你不能仅仅在存储过程中运行一个 SELECT 语句而不在 PL/SQL 中存储结果。至少你需要一个 ref cursor 或类似的东西。 - user330315
是的,在存储过程中选择语句不起作用。在SQL Server中,您可以尝试使用SQL块。DECLARE @name VARCHAR(50)SELECT @name = 'SELECT * FROM ' + TABLE_NAME FROM COL_TAB WHERE TABLE_NAME = 'TAB1'EXEC (@name); - batflix
1
如果Pirate使用的是Oracle,那么SQL Server解决方案有什么用处呢? - user330315

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接