datax-web icon indicating copy to clipboard operation
datax-web copied to clipboard

解决oracle下无法获取schema,视图名,视图字段

Open zyc-cn opened this issue 4 years ago • 13 comments

#1.解决oracle下无法获取schema,视图名,视图字段 ##原有问题分析 在package com.wugui.datax.admin.tool.meta;下的OracleDatabaseMeta类中,是对oracle数据库的基本操作。

  • 但是对于许多场景,数据库只是开了一个很低权限的账户给你,而且你也只有读取view的权限,没有访问系统属性的权限, 对于原有OracleDatabaseMeta类中许多sql是在低权限用户下是无法执行的,执行报错:ORA-00942 具体sql如下:
  1. public String getSQLQueryTables(String... tableSchema) { return "select table_name from dba_tables where owner='" + tableSchema[0] + "'";}
  2. public String getSQLQueryTableSchema(String... args) { return "select username from sys.dba_users"; }
  3. public String getSQLQueryTables() { return "select table_name from user_tab_comments"; }
  4. ....等,详细自己可以尝试

##解决

第一步:修改OracleDatabaseMeta类,添加相应的方法:

  1. public String getSQLQueryTablesSchemasByViews(String... args) { return "select distinct owner from all_views";}
  2. public String getSQLQueryViews(String owner) { return "select view_name from all_views where owner='"+ owner +"'"; }

第二步:修改package com.wugui.datax.admin.tool.query;下的OracleQueryTool类,复写如下三个方法详细如下:

package com.wugui.datax.admin.tool.query;

import com.wugui.datax.admin.core.util.LocalCacheUtil; import com.wugui.datax.admin.entity.JobDatasource; import com.wugui.datax.admin.tool.meta.DatabaseInterface; import com.wugui.datax.admin.tool.meta.DatabaseMetaFactory; import com.wugui.datax.admin.tool.meta.OracleDatabaseMeta; import com.wugui.datax.admin.util.JdbcUtils;

import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Comparator; import java.util.List;

/**

  • Oracle数据库使用的查询工具

  • @author @author 949081272qq.com

  • @ClassName OracleQueryTool

  • @Version 1.0

  • @since 2020/7/23 9:31 */ public class OracleQueryTool extends BaseQueryTool implements QueryToolInterface {

    private Connection connection; private OracleDatabaseMeta oracleDatabaseMeta; /**

    • 用于获取查询语句 */ private DatabaseInterface sqlBuilder;

    // 注意static private static String tableSchema;

    public OracleQueryTool(JobDatasource jobDatasource) throws SQLException { super(jobDatasource); this.connection = (Connection) LocalCacheUtil.get(jobDatasource.getDatasourceName()); sqlBuilder = DatabaseMetaFactory.getByDbType(jobDatasource.getDatasource()); oracleDatabaseMeta = OracleDatabaseMeta.getInstance(); }

    @Override public List<String> getTableSchema() { List<String> schemas = new ArrayList<>(); Statement stmt = null; ResultSet rs = null; try { stmt = connection.createStatement(); //获取sql String sql = oracleDatabaseMeta.getSQLQueryOwners(); rs = stmt.executeQuery(sql); while (rs.next()) { String tableName = rs.getString(1); schemas.add(tableName); } } catch (SQLException e) { logger.error("[getTableNames Exception] --> " + "the exception message is:" + e.getMessage()); } finally { JdbcUtils.close(rs); JdbcUtils.close(stmt); } return schemas; }

    @Override public List<String> getTableNames(String tableSchema) { this.tableSchema = tableSchema; List<String> tableOrViews = new ArrayList<String>(); //获取table的sql String tableSql = getSQLQueryTables(tableSchema); String viewSql = oracleDatabaseMeta.getSQLQueryViews(tableSchema); getTableNamesOrViewsBySql(tableSql, tableOrViews); // 添加表 getTableNamesOrViewsBySql(viewSql, tableOrViews); // 添加视图 return tableOrViews; }

    @Override public List<String> getColumnNames(String tableName, String datasource) { String oarcleQueryTableName = tableSchema + "." + tableName; return super.getColumnNames(oarcleQueryTableName, datasource); }

    private Boolean getTableNamesOrViewsBySql(String sql, List<String> tables) { Boolean getTableNamesOrViewsSuccess; Statement stmt = null; ResultSet rs = null; try { stmt = connection.createStatement(); rs = stmt.executeQuery(sql); while (rs.next()) { String tableName = rs.getString(1); tables.add(tableName); } tables.sort(Comparator.naturalOrder()); getTableNamesOrViewsSuccess = true; } catch (SQLException e) { getTableNamesOrViewsSuccess = false; logger.error("[getTableNamesBySql(String sql) Exception] --> " + "the exception message is:" + e.getMessage());

     } finally {
         JdbcUtils.close(rs);
         JdbcUtils.close(stmt);
     }
     return getTableNamesOrViewsSuccess;
    

    } } ##第三步, 打包datax-web,将服务器上的datax-admin的jar包替换掉即可,具体替换步骤省略。。

zyc-cn avatar Jul 23 '20 08:07 zyc-cn

上面的第一步中:修改OracleDatabaseMeta类,添加相应的方法 新增的两个方法写错了, 写的太快复制错了,,修改后具体如下: /** * 下面两个查询语句解决oracle下无法获取schema,视图名,视图字段 */ public String getSQLQueryOwners() { return "select distinct owner from all_views"; }

public String getSQLQueryViews(String owner) {
    return "select view_name from all_views where owner='"+ owner +"'";
}

zyc-cn avatar Jul 23 '20 09:07 zyc-cn

#1.解决oracle下无法获取schema,视图名,视图字段 ##原有问题分析 在package com.wugui.datax.admin.tool.meta;下的OracleDatabaseMeta类中,是对oracle数据库的基本操作。

  • 但是对于许多场景,数据库只是开了一个很低权限的账户给你,而且你也只有读取view的权限,没有访问系统属性的权限, 对于原有OracleDatabaseMeta类中许多sql是在低权限用户下是无法执行的,执行报错:ORA-00942 具体sql如下:
  1. public String getSQLQueryTables(String... tableSchema) { return "select table_name from dba_tables where owner='" + tableSchema[0] + "'";}
  2. public String getSQLQueryTableSchema(String... args) { return "select username from sys.dba_users"; }
  3. public String getSQLQueryTables() { return "select table_name from user_tab_comments"; }
  4. ....等,详细自己可以尝试

##解决

第一步:修改OracleDatabaseMeta类,添加相应的方法:

  1. public String getSQLQueryTablesSchemasByViews(String... args) { return "select distinct owner from all_views";}
  2. public String getSQLQueryViews(String owner) { return "select view_name from all_views where owner='"+ owner +"'"; }

第二步:修改package com.wugui.datax.admin.tool.query;下的OracleQueryTool类,复写如下三个方法详细如下:

package com.wugui.datax.admin.tool.query; import com.wugui.datax.admin.core.util.LocalCacheUtil; import com.wugui.datax.admin.entity.JobDatasource; import com.wugui.datax.admin.tool.meta.DatabaseInterface; import com.wugui.datax.admin.tool.meta.DatabaseMetaFactory; import com.wugui.datax.admin.tool.meta.OracleDatabaseMeta; import com.wugui.datax.admin.util.JdbcUtils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Comparator; import java.util.List; /**

  • Oracle数据库使用的查询工具

  • @author @author 949081272qq.com

  • @ClassName OracleQueryTool

  • @Version 1.0

  • @SInCE 2020/7/23 9:31 / public class OracleQueryTool extends BaseQueryTool implements QueryToolInterface { private Connection connection; private OracleDatabaseMeta oracleDatabaseMeta; /*

    • 用于获取查询语句 */ private DatabaseInterface sqlBuilder;

    // 注意static private static String tableSchema; public OracleQueryTool(JobDatasource jobDatasource) throws SQLException { super(jobDatasource); this.connection = (Connection) LocalCacheUtil.get(jobDatasource.getDatasourceName()); sqlBuilder = DatabaseMetaFactory.getByDbType(jobDatasource.getDatasource()); oracleDatabaseMeta = OracleDatabaseMeta.getInstance(); } @override public List getTableSchema() { List schemas = new ArrayList<>(); Statement stmt = null; ResultSet rs = null; try { stmt = connection.createStatement(); //获取sql String sql = oracleDatabaseMeta.getSQLQueryOwners(); rs = stmt.executeQuery(sql); while (rs.next()) { String tableName = rs.getString(1); schemas.add(tableName); } } catch (SQLException e) { logger.error("[getTableNames Exception] --> "

    • "the exception message is:" + e.getMessage()); } finally { JdbcUtils.close(rs); JdbcUtils.close(stmt); } return schemas; } @override public List getTableNames(String tableSchema) { this.tableSchema = tableSchema; List tableOrViews = new ArrayList(); //获取table的sql String tableSql = getSQLQueryTables(tableSchema); String viewSql = oracleDatabaseMeta.getSQLQueryViews(tableSchema); getTableNamesOrViewsBySql(tableSql, tableOrViews); // 添加表 getTableNamesOrViewsBySql(viewSql, tableOrViews); // 添加视图 return tableOrViews; } @override public List getColumnNames(String tableName, String datasource) { String oarcleQueryTableName = tableSchema + "." + tableName; return super.getColumnNames(oarcleQueryTableName, datasource); } private Boolean getTableNamesOrViewsBySql(String sql, List tables) { Boolean getTableNamesOrViewsSuccess; Statement stmt = null; ResultSet rs = null; try { stmt = connection.createStatement(); rs = stmt.executeQuery(sql); while (rs.next()) { String tableName = rs.getString(1); tables.add(tableName); } tables.sort(Comparator.naturalOrder()); getTableNamesOrViewsSuccess = true; } catch (SQLException e) { getTableNamesOrViewsSuccess = false; logger.error("[getTableNamesBySql(String sql) Exception] --> "
    • "the exception message is:" + e.getMessage());
     } finally {
         JdbcUtils.close(rs);
         JdbcUtils.close(stmt);
     }
     return getTableNamesOrViewsSuccess;
    

    } } ##第三步, 打包datax-web,将服务器上的datax-admin的jar包替换掉即可,具体替换步骤省略。。

今天比较忙没能尽快回复,非常感谢参与项目的贡献! 我有个疑问请教下,我们dev分支有开发者提了PR,获取用户和表的sql已经改为

    @Override
    public String getSQLQueryTableSchema(String... args) {
        return "select username from all_users";
    }
    @Override
    public String getSQLQueryTables(String... tableSchema) {
        return "select table_name from all_tables where owner='" + tableSchema[0] + "'";
    }

这种方式是不是也能达到效果呢,那种方式更好一点,通用性更强一点。

WeiYe-Jing avatar Jul 23 '20 09:07 WeiYe-Jing

获取用户"select username from all_users"这种方式通用性更好些,可以考虑前端获取表的时候一并把该shema下的视图也获取了。

select table_name from all_tables where owner='tableSchema' union select view_name as table_name from all_views where owner='tableSchema'

zyc-cn avatar Jul 23 '20 10:07 zyc-cn

获取用户"select username from all_users"这种方式通用性更好些,可以考虑前端获取表的时候一并把该shema下的视图也获取了。

select table_name from all_tables where owner='tableSchema' union select view_name as table_name from all_views where owner='tableSchema'

好的,非常感谢!

WeiYe-Jing avatar Jul 23 '20 10:07 WeiYe-Jing

获取用户"select username from all_users"这种方式通用性更好些,可以考虑前端获取表的时候一并把该shema下的视图也获取了。

select table_name from all_tables where owner='tableSchema' union select view_name as table_name from all_views where owner='tableSchema'

好的,非常感谢!

shema下的视图即便获取到,datax也不支持数据数据同步吧

WeiYe-Jing avatar Jul 29 '20 09:07 WeiYe-Jing

datax支持的,我都试过了,生产环境已经在增量同步了,就是你在生成的json中的reader表名需要加上schema,你也可以改一下源码,自动生成。oracle 12c!

------------------ 原始邮件 ------------------ 发件人: "WeiYe-Jing/datax-web" <[email protected]>; 发送时间: 2020年7月29日(星期三) 下午5:46 收件人: "WeiYe-Jing/datax-web"<[email protected]>; 抄送: "学海无崖"<[email protected]>;"Author"<[email protected]>; 主题: Re: [WeiYe-Jing/datax-web] 解决oracle下无法获取schema,视图名,视图字段 (#250)

获取用户"select username from all_users"这种方式通用性更好些,可以考虑前端获取表的时候一并把该shema下的视图也获取了。

select table_name from all_tables where owner='tableSchema' union select view_name as table_name from all_views where owner='tableSchema'

好的,非常感谢!

shema下的视图即便获取到,datax也不支持数据数据同步吧

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

zyc-cn avatar Jul 29 '20 09:07 zyc-cn

datax支持的,我都试过了,生产环境已经在增量同步了,就是你在生成的json中的reader表名需要加上schema,你也可以改一下源码,自动生成。oracle 12c!

好的,谢谢! select owner||'.'||table_name from all_tables where owner='" + tableSchema[0] + "' union select owner||'.'||view_name as table_name from all_views where owner='" + tableSchema[0] + "'order by table_name 这是最新的sql

WeiYe-Jing avatar Jul 29 '20 10:07 WeiYe-Jing

datax支持的,我都试过了,生产环境已经在增量同步了,就是你在生成的json中的reader表名需要加上schema,你也可以改一下源码,自动生成。oracle 12c!

好的,谢谢! select owner||'.'||table_name from all_tables where owner='" + tableSchema[0] + "' union select owner||'.'||view_name as table_name from all_views where owner='" + tableSchema[0] + "'order by table_name 这是最新的sql

以上sql执行会报错.需要加入一下alias `select owner||'.'||table_name

as table_name

from all_tables where owner='" + tableSchema[0] + "' union select owner||'.'||view_name as table_name from all_views where owner='" + tableSchema[0] + "'order by table_name`

别问我怎么知道的 。。。。

deavn avatar Oct 15 '20 06:10 deavn

微野,这个bug还在,代码没有合并是因为什么原因呢。

NeighborOldKing avatar Jan 11 '21 02:01 NeighborOldKing

哎,我这也是,oracle数据库是第三方提供的,只给视图,我用datax web根据获取不到表的字段,哎,真难

czxin788 avatar Jan 12 '21 12:01 czxin788

datax支持的,我都试过了,生产环境已经在增量同步了,就是你在生成的json中的reader表名需要加上schema,你也可以改一下源码,自动生成。oracle 12c! ------------------ 原始邮件 ------------------ 发件人: "WeiYe-Jing/datax-web" <[email protected]>; 发送时间: 2020年7月29日(星期三) 下午5:46 收件人: "WeiYe-Jing/datax-web"<[email protected]>; 抄送: "学海无崖"<[email protected]>;"Author"<[email protected]>; 主题: Re: [WeiYe-Jing/datax-web] 解决oracle下无法获取schema,视图名,视图字段 (#250) 获取用户"select username from all_users"这种方式通用性更好些,可以考虑前端获取表的时候一并把该shema下的视图也获取了。 select table_name from all_tables where owner='tableSchema' union select view_name as table_name from all_views where owner='tableSchema' 好的,非常感谢! shema下的视图即便获取到,datax也不支持数据数据同步吧 — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

您好,请问您使用datax是如何同步Oracle视图的?方便提供一下相关的参考程序么? @zhouYingLove

sty945 avatar Nov 17 '21 13:11 sty945

datax支持的,我都试过了,生产环境已经在增量同步了,就是你在生成的json中的reader表名需要加上schema,你也可以改一下源码,自动生成。oracle 12c!

好的,谢谢! select owner||'.'||table_name from all_tables where owner='" + tableSchema[0] + "' union select owner||'.'||view_name as table_name from all_views where owner='" + tableSchema[0] + "'order by table_name 这是最新的sql

【master代码还没有更新】 修改com.wugui.datax.admin.tool.meta包下的OracleDatabaseMeta类中的两个方法


@Override
  public String getSQLQueryTables(String... tableSchema) {
      return  "  select owner||'.'||table_name as table_name from all_tables where owner='" + tableSchema[0] + "' union select owner||'.'||view_name as table_name from all_views where owner='" + tableSchema[0] + "' ";
  }

  @Override
  public String getSQLQueryTableSchema(String... args) {
      return "select username from sys.all_users";
  }

hengleeme avatar Jun 08 '23 06:06 hengleeme

您的邮件我已收到,我会尽快给您回复!

qujiabin avatar Jun 08 '23 06:06 qujiabin