【问题标题】:Selecting multiple schemas in a select statement在 select 语句中选择多个模式
【发布时间】:2016-09-09 15:26:53
【问题描述】:

被访问的数据库在 Snowflake 上;不确定幕后的存储细节。

我现在有一个查询,它从存储在同一数据库下不同模式中的 41 个数据表创建一个新视图,看起来像这样:

CREATE VIEW all_data AS
SELECT * FROM db.schema1.data UNION ALL
SELECT * FROM db.schema2.data UNION ALL
SELECT * FROM db.schema3.data

此查询每天运行一次。我的问题是我每隔几天就会添加新的数据表,我必须手动编辑查询以包含这些新表,因为它们存储在单独的模式下(并且模式的命名方案也不一致,因为我无法控制的原因)。有没有一种方法可以使用子查询选择数据库中的所有模式,这样我就可以每天运行查询,而无需在添加新模式 + 表时手动更新?

我希望结果查询的结构有点像

CREATE VIEW all_data as 
SELECT * FROM [SELECT schemas from db].data

但不确定这将如何工作,以及如何正确合并结果数据。

【问题讨论】:

  • 你肯定需要为你的 RDBMS 标记这个。 sql服务器?甲骨文? mysql?.... sql-server 的答案也是“否”,您不能创建一个视图,以这种方式自动从动态识别的模式中进行选择。但是您可以创建一个使用动态 sql 执行此操作的存储过程,或者您可以创建一个存储过程来根据现有架构更改和重新创建您的视图,然后在视图上运行查询之前运行它。
  • 它在雪花上运行,实际上不知道后端是什么。
  • 好的,我想我标记了正确的,但请检查一下。抱歉,我没有使用该特定平台,因此无法提供帮助。
  • 感谢帮助,我对平台也不太熟悉

标签: sql snowflake-cloud-data-platform


【解决方案1】:

不幸的是,在 Snowflake 中,您还不能动态构造 SQL 语句。您当然可以通过使用一种受支持语言(例如 Python、JS)的脚本来实现您想要实现的目标,方法是首先找到所有模式,然后构建完整的 SQL 语句。

希望这会有所帮助。

【讨论】:

  • 感谢您的回复,这就是我要做的事情:将查询包装在可以动态生成它的python脚本中
【解决方案2】:

您绝对可以查询可用的表和架构列表。 SQL Authority 有一篇很好的文章: http://blog.sqlauthority.com/2009/06/17/sql-server-list-schema-name-and-table-name-for-database/

简而言之,查询最终会按照以下方式提取表和架构列表:

SELECT '['+SCHEMA_NAME(schema_id)+'].['+name+']'
AS SchemaTable
FROM sys.tables

虽然您必须在 where 子句中添加数据库名称以指向正确的数据库。

【讨论】:

  • 数据库名称不包含在 sys.tables 系统视图中!如果您想从连接尚未连接的特定数据库中选择,那么您可以从 DBNAME.sys.tables 中选择。此外,虽然这解决了他如何找到 shema,但没有解决他如何使用它来修改他的视图或在他的视图中动态选择表
【解决方案3】:

随着Snowflake Scripting 的发布,Snowflake 内部视图的动态重建现在非常有可能。

create database dynamic_views;
create schema dynamic_views.schema_base;
create schema dynamic_views.schema1;
create table dynamic_views.schema1.data(id int) as select * from values (1);

我们可以使用INFORMATION_SCEMA.TABLES 查找所有DATA 表:

SELECT table_schema 
FROM dynamic_views.information_schema.tables 
WHERE table_name = 'DATA';
TABLE_SCHEMA
SCHEMA1

现在将其推送到游标中并构建视图创建 SQL

此 SQL 需要在新的 Snowsight 控制台中运行,请参阅 (Working with Classic Console):

declare
  sql text;
  add_union boolean := false;
  c1 cursor for SELECT TABLE_SCHEMA 
        FROM dynamic_views.information_schema.TABLES 
        WHERE TABLE_NAME = 'DATA';
begin
  sql := 'CREATE OR REPLACE VIEW dynamic_views.schema_base.all_data AS ';
  for record in c1 do
    if (add_union) then
         sql := sql || 'UNION ALL ';
    end if;
    sql := sql || 'SELECT * FROM dynamic_views.'|| record.TABLE_SCHEMA ||'.data ';
    add_union := true;
  end for;
  
  EXECUTE IMMEDIATE sql;
  return sql;
end;
;

我们可以使用它:

select * from dynamic_views.schema_base.all_data;
ID
1

并添加更多:

create schema dynamic_views.schema2;
create table dynamic_views.schema2.data(id int) as select * from values (2);

重建:

anonymous block
CREATE OR REPLACE VIEW dynamic_views.schema_base.all_data AS SELECT * FROM dynamic_views.SCHEMA1.data UNION ALL SELECT * FROM dynamic_views.SCHEMA2.data

再次使用它:

select * from dynamic_views.schema_base.all_data;
ID
1
2

注意:您不应该在生产中使用SELECT *,因为表格列的顺序将依赖于创建顺序,如果新表格具有不同的形状,您查看的表格将变得无效。

所以确实应该使用显式形式:

'SELECT column1, column2, column4 FROM dynamic_views.'|| record.TABLE_SCHEMA ||'.data ';

【讨论】:

    猜你喜欢
    • 2023-03-09
    • 2014-09-16
    • 2021-11-14
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 2016-10-18
    相关资源
    最近更新 更多