DatabaseMetadata.getTables()方法 问题记录
Posted blackstring
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DatabaseMetadata.getTables()方法 问题记录相关的知识,希望对你有一定的参考价值。
之前写了一个程序,负责从一个集群中同步Hive数据到另一个集群中,代码中有这么一步,指定好表格后,会首先判断表格是否存在,不存在则创建,已经存在则提示是否覆盖。
在我最初编写程序的时候,两个集群中的表格基本上都是一致的,所以当初没有出什么问题。但是最近组长说这个程序干脆整合到平台里好了,所以找了一个前辈来帮我测试。
前辈不愧是前辈,噼里啪啦没多久就找出一堆小问题(主要因为最初是给自己写的,没有考虑那么多),其中一个问题就是就是在他删除了某张表之后,再次同步这张表的数据时,程序提示表已经存在,但是最终修复表格信息时确保了错,提示表格不存在。
我很容易就想到应该是表格判断那里出了问题。判断表格是否存在我使用的是DatabaseMetadata类下的getTables(),这个方法有四个参数,可以根据指定的参数从元数据中获取表格信息,理论上是不会出错的,毕竟是元数据,而且删除表格使用的Hue,删除没出任何问题,理论上元数据中的数据也应该删掉的:
public static boolean tableExist(String database, String table) throws SQLException
rs = connection.getMetaData().getTables(null, null, table ,null);
return rs.next();
我针对那张表进行测试,发现返回的真的是true。
事实上,我对这个方法并不怎么熟悉,连这个判断的方法也是从网上查到的。
所以,为了解决这个问题,我开始研究这个方法。首先看这个方法的描述:
Retrieves a description of the tables available in the given catalog.Only table descriptions matching the catalog, schema, tablename and
type criteria are returned.They are ordered by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM and TABLE_NAME.
检索给定目录中可用表的说明。只返回与目录、架构、表名和类型条件匹配的表说明。它们按表类型、表类别、表计划和表名称排序。
它有四个参数:String catalog,String schemaPattern,String tableNamePattern,String[] types,分别表示:
catalog 包含目录名称的 String。对此参数提供 Null 值表示无需使用目录名称。
schema 包含架构名称模式的 String 值。对此参数提供 Null 值表示无需使用架构名称。
tableNamePattern 包含表名称模式的 String。
types 含有要包含的表类型的字符串数组。Null 表示应包含所有表类型。
最初我提供的参数是null, null, table ,null,即仅提供表名,因为当初查到的就是这样的,而且catalog和schema代表什么我也不清楚。
这种做法下在最初是没有什么问题的,但是到底为什么会导致查询出一张已经被删除的表?
我注意到了参数中的"tableNamePattern",而不是"tableName"或"table",所以是不是因为这个原因,它匹配到了其他表?
因为在Hive中我当初为了测试建立过几张副表(假设原表名为A,另外几张表是A2,A3等)。
所以我开始尝试替换掉"_",并且指定头尾(^ $ )进行精准匹配,然而反而任何表都匹配不到了。经过了数十分钟的测试,我最终认为原因应该不在这里。
getTables()方法的结果集中可能有以下列:
TABLE_CAT String=>表目录(可能为空)
TABLE_SCHEM String=>表架构(可能为空)
TABLE_NAME String=>表名
TABLE_TYPE String =>表类, 典型的类型有"TABLE","VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY","LOCAL TEMPORARY", "ALIAS", "SYNONYM"
REMARKS String => 表格注释
TYPE_CAT String => 目录类型(可能为空)
TYPE_SCHEM String => 架构类型(可能为空)
TYPE_NAME String => 类型名(可能为空)
SELF_REFERENCING_COL_NAME String => 类型表的指定“标识符”列的名称(可能为空)
REF_GENERATION String => 指定如何创建引用_col_name的inself_值。值为"SYSTEM", "USER", "DERIVED"(可能为空)
我在想,方法中匹配到的真的是那张表的信息吗?于是我编写了以下方法,输出所查询到的表的信息:
public static void tableData(String database, String table) throws SQLException
rs = connection.getMetaData().getTables(null, database, table ,null);
while(rs.next())
System.out.println("==>"+rs.getString(1));
System.out.println("==>"+rs.getString(2));
System.out.println("==>"+rs.getString(3));
System.out.println("==>"+rs.getString(4));
System.out.println("==>"+rs.getString(5));
输出如下(A为我所查询的表名):
==>
==>test
==>A
==>TABLE
==>null
查询到的的确是这张表,但是这张表所在的库却是"test",我赶紧去test库中看了一下,发现里面真的存在一张A表,我这才想起来,这不是我当初写程序的时候创检测测试表吗?!!
闹了半天是被以前的自己坑了,但是这个问题也是很有价值的。
在输出中可以看到,第一列代表参数catalog,第二列代表参数schemaPattern,第三列代表参数tableNamePattern,第四列代表参数types。
所以参数schemaPattern应该指定为数据库,这样就能利用到我最初传入的参数database了。
将方法修改为:
public static boolean tableExist(String database, String table) throws SQLException
rs = connection.getMetaData().getTables(null, database, table ,null);
return rs.next();
接着进行测试,发现果然返回了false!最终,在困扰了我两个多小时后,这个问题终于得以解决。
以上就是我在使用DatabaseMetadata.getTables()方法时遇到的一个小问题,希望能够给予大家帮助。
以上是关于DatabaseMetadata.getTables()方法 问题记录的主要内容,如果未能解决你的问题,请参考以下文章