【问题标题】:Teradata: Is there a way to generate DDL from a view or select statement?Teradata:有没有办法从视图或选择语句生成 DDL?
【发布时间】:2012-10-06 13:47:30
【问题描述】:

我正在使用全局应用程序用户帐户访问数据库 A。此用户帐户无权修改数据库 A 的架构(即创建表、修改表等)。该用户还可以访问数据库 B,但只能查看。我需要运行 SQL 以将数据库 B 中的视图中的数据馈送到数据库 A 中的表中。

在一个完美的世界里,我可以使用这个 SQL:

create database_a.mytable as (select * from database_b) with no data

但是,用户不能在数据库 A 中创建表。如果我可以获取 select 语句的 DDL,那么我可以在我的个人帐户(没有任何访问数据库 B 的权限)下登录并运行数据库A中的DDL来创建表。

唯一的其他选择是手动编写 SQL,但我不想这样做,特别是因为我要复制的这个视图有许多不同数据类型和大小的列。

编辑:我可能越来越近了。我只是对此进行了实验:

show (select * from database_b.myview)

但是,它生成了视图本身中使用的每个表的 DLL,以及视图的定义。这并没有真正帮助我,因为我只想要 select 语句本身的模式。换句话说,如果我要使用上面提到的create table as 语句,我需要生成什么。

为 Rob 编辑:也许“DDL”这个词用错了。使用show view db.myview 只显示视图的定义,而不是它所代表的模式。在上面的create table as 示例中,我展示了如何创建一个表来模拟选择中返回的结果集的模式。它在后端生成一个用于创建表的 DDL,然后执行该 DDL 以实际创建表。然后您可以说show table db.newtable 并查看新表的 DDL。我想直接从 select 语句中获取 那个 DDL,以便我可以复制它,退出应用程序帐户,进入我的个人帐户,然后执行 DDL 以创建表。

这只是为了让我不必手动输入 DDL 以节省时间并减少输入错误,特别是因为源视图有这么多列。也就是说,我认为找 DBA 或编写一些时髦的存储过程来做动态的东西对于我的需求来说有点过头了。我认为必须有一种方法可以直接从 select 语句中获取用于创建表模式的 DDL。

【问题讨论】:

    标签: teradata


    【解决方案1】:

    为对象生成 DDL 语句:

    SHOW TABLE {DatabaseB}.{Table1};
    SHOW VIEW {DatabaseB}.{View1};
    

    视图中的列细分:

    HELP VIEW {DatabaseB}.{View1};
    

    但是,如果没有在目标数据库DatabaseA 中创建对象的能力,您就没有太多的筹码。显然,如果对象已经存在,INSERT INTO SELECT ... FROM DatabaseB.Table1MERGE INTO 将是您已经探索过的选项。

    替代解决方案

    是否可以创建一个基于提供的视图名称动态创建表的存储过程?全局应用程序帐户只需要特权即可执行该过程。通常,创建存储过程的用户需要权限才能执行存储过程中包含的操作。 (在 Teradata 13.10 中,您有一些额外的灵活性。)

    这种方法有一些注意事项。您正在尝试物化可以引用从数百到数十亿条记录的任何地方的视图。这些不是放在目标表之上的简单的 1:1 视图。试图确定目标数据库中实现视图所需的空间将很困难。性能可以并且将根据视图的复杂性和数据量而有所不同。这将不是快速路径或数据块优化操作。

    作为一名 DBA,我会担心这种方法被一个全球应用程序帐户采用,而没有完全理解其意图。我相信您与支持该系统所涉及的 DBA 有一个开放的沟通渠道。我敢肯定,你的疯狂是有原因的,这里不能透露。

    可能的解决方案 - VOLATILE TABLE

    除非 CREATE TABLE 的隐式特权已从全局应用程序帐户中撤消,否则此解决方案应该可以工作。

    易失性表不需要永久空间。表定义在会话期间持续存在,插入其中的任何数据都依赖于实例化它的用户的假脱机空间。

    CREATE VOLATILE TABLE {Global Application UserID}.{TableA_Copy} AS 
    (
       SELECT *
         FROM {DatabaseB}.{TableA}
    )
     WITH NO DATA
       NO PRIMARY INDEX
       ON COMMIT PRESERVE ROWS;
    
    SHOW TABLE {Global Application UserID}.{TableA_Copy};
    

    我选择使用名为NO PRIMARY INDEX 的 Teradata 13.10 功能。默认情况下,CREATE TABLE AS 将采用SELECT 语句的第一列并将其作为表的PRIMARY INDEX。根据数据人口统计数据,这可能会导致测试中出现倾斜和烫发空间问题。当您了解基础数据时,您可以自行指定显式 PRIMARY INDEX。 (如果不确定,请参阅 DDL 手册以获取有关语法的详细信息。)

    使用ON COMMIT PRESERVE ROWS 作为本示例的意图可能是无关紧要的。但实际上,如果您将任何数据弹出到该表中以测试此子句,则在 Teradata 模式下将是有益的,否则在对 volatile 表执行CREATE TABLE 或任何其他数据操作后,数据将立即丢失。

    【讨论】:

    • 我用详细信息更新我的答案。如果我想做的事情无法完成,请告诉我。
    • 添加了第二个潜在的解决方案。鉴于最新的解决方案,我认为存储过程方法过于繁琐。
    • 太棒了!它工作得很好。我确实需要编辑一些 DDL,但你不知道这会为我节省多少时间。当然,在我发布我的问题并得到答案的时间内,我本可以完成 30 次,但这对于未来是可以重复使用的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    相关资源
    最近更新 更多