我在Oracle数据库中使用SQL。我有几个表需要从另一个程序中提取数据进行分析。我正在努力有效地实施这个过程。
最终产品将是.csv类型文件,例如:
TableName1, Data1, Data2, Data3
TableName1, Data1, Data2, Data3
TableName2, Data1, Data2, Data3, Data4
TableName2, Data1, Data2, Data3, Data4
TableName3, Data1, Data2
等
使用这些查询,我得到了我需要的数据和字段数,因此我可以在可能的for循环中使用它:
SELECT * FROM MY_TABLE_NAME
SELECT count(column_name) FROM all_tab_cols WHERE table_name = 'MY_TABLE_NAME'
我迷失的地方虽然是如何把它翻译成块。我将来必须再次运行此代码,所以我希望能够在开头用我想要的每个表的名称编写一个数组,并且如果需要,可以在以后添加或删除表。每个表还为每个字段提供不同数量的字段和数据类型。到目前为止,我尝试过的所有方法都要求我在DEFINE块中明确说明每个方法,这是不可行的。动态循环遍历这些数据集的最佳方法是什么?
有人能指出我正确的方向去下一步吗?
答案 0 :(得分:2)
您不需要为此编写循环(或与程序和PL / SQL有关的任何内容)。你需要的是两件事:一张包含你想要包含的表名的表(如你所说,这可能会随着时间的推移而改变 - 这组表的最佳位置是......表)和查询。
在下面的解决方案中,我在第一个因子子查询(table_names
子句中)中创建了一个名为tn
的模拟表,其中包含with
列。在现实生活中,删除该CTE,并使用您的实际表和列名称。 LISTAGG
中的列按照它们在SELECT *
中显示的顺序进行汇总(COLUMN_ID
中由USER_TAB_COLUMNS
标识。
我用SCOTT
架构中的表来说明这一点。请注意当table_names表包含模式中不存在的表时会发生什么:结果字符串显示表名,逗号和空格,没有其他内容。这是OUTER JOIN
的结果。如果您不希望包含此类不存在的表,则可以将其更改为INNER JOIN
。 (您也可以编写一个不同的查询来首先检查所有表名实际上是否存在于它们应该存在的模式中。)
我也没有写这个来跨不同的所有者/架构工作。如果这是你需要的,它可以很容易地适应。特别是,您可以使用ALL_TAB_COLUMNS
代替USER_TAB_COLUMNS
。
<强>查询强>:
with table_names ( tn ) as (
select 'PINOCCHIO' from dual union all
select 'EMAIL_ADDRESSES' from dual union all
select 'BONUS' from dual union all
select 'ORDER_ITEM' from dual
)
select t.tn, t.tn || ', ' || listagg(c.column_name, ', ')
within group (order by c.column_id) as str
from table_names t left outer join user_tab_columns c
on t.tn = c.table_name
group by tn
;
输出:
(请记住,我以用户SCOTT
连接 - 默认情况下在任何Oracle DB安装中都存在的标准架构...密码为&#34; tiger&#34;除非您更改了它
TN STR
--------------- ----------------------------------------------------------
BONUS BONUS, ENAME, JOB, SAL, COMM
EMAIL_ADDRESSES EMAIL_ADDRESSES, INTERNET_ADDRESS_ID, EMAIL_ADDRESS
ORDER_ITEM ORDER_ITEM, ORDER_ID, ITEM_ID, QTY
PINOCCHIO PINOCCHIO,
4 rows selected.