Greenplum获取一个SQL结果的字段名

 在Greenplum中,对于任意一个SQL,我们想获取这个SQL执行后的字段名是比较难的。

比方说在写一个通用工具的时候,使用copy命令将一个SQL导出成文本,但是每个字段的名称导出的文本中却没有,如果使用自己解析SQL的话就太复杂了

如果我们想取得这些字段名的话,不真正执行sql,因为在生成执行计划的时候已经,我知道的有以下几种方法:

1.使用JDBC,prepareStatement先生成执行计划,然后获取字段名:

             PreparedStatement pstmt = conn.prepareStatement("select * from gp_segment_configuration a");
             ResultSetMetaData metaData=pstmt.getMetaData();
             for(int i=1;i<=metaData.getColumnCount();i++){
              System.out.println(metaData.getColumnName(i)+" \t\t :"+metaData.getColumnTypeName(i));
             }

ps:不止是JDBC,其他的客户端接口估计都会有这种接口将字段给取出来。看了jdbc的源码,在获取metaData信息的时候,是直接跟数据库交互,然后将这些信息接收过来的。对于其他的,应该都是有定义好的接口的,这个需要自己去挖掘。


2.explain 如果加上verbose会将整个解析后的语法数打印出来。如下:

aligputf8=# explain verbose select * from cxfa;   
                           QUERY PLAN                           
----------------------------------------------------------------
    {MOTION 
    :motionID 1 
    :motionType 1 
    :sendToSecondary false 
    :sendSorted false 
    :numInputSegs 3 
    :inputSegIdx <> 
    :numHashSegs 0 
    :hashSegIdx 
    :hashExpr <> 
    :hashDataTypes <> 
    :numOutputSegs 1 
    :outputSegIdx -1 
    :numSortCols 0 
    :sortColIdx 
    :sortOperators 
    :plan_node_id 1 
    :plan_parent_node_id -1 
    :startup_cost 0.00 
    :total_cost 0.00 
    :plan_rows 1 
    :plan_width 36 

其中最上层的targetlist就是 SQL要返回的字段列表。

   :targetlist (
       {TARGETENTRY 
       :expr 
          {VAR 
          :varno 1 
          :varattno 1 
          :vartype 23 
          :vartypmod -1 
          :varlevelsup 0 
          :varnoold 1 
          :varoattno 1
          }
       :resno 1 
       :resname a 
       :ressortgroupref 0 
       :resorigtbl 28569230 
       :resorigcol 1 
       :resjunk false
       }
       {TARGETENTRY 
       :expr 
          {VAR 
          :varno 1 
          :varattno 2 
          :vartype 25 
          :vartypmod -1 
          :varlevelsup 0 
          :varnoold 1 
          :varoattno 2
          }
       :resno 2 
       :resname b 
       :ressortgroupref 0 
       :resorigtbl 28569230 
       :resorigcol 2 
       :resjunk false
       }
    )


这样,我们能不能利用这个写一个函数,来将这个字段名给取出来呢,如果直接解析这个语法树还是比较麻烦的。我们发现,字段名前面都有一个      :resname开头,我们可以遍历这个数,把“     :resname”开头的都给找出来,就是字段名了。

函数的代码如下:

CREATE or replace FUNCTION public.get_sql_column_name(sqlori text)
      RETURNS setof text
AS $
    sql_ori=sqlori.strip().lower()
    if not sql_ori.startswith('select'):
        return ['SQL is not Select SQL,Please check!']
    retext=[]
    sql="explain verbose " + sql_ori
    #plpy.info(sql)
    rv = plpy.execute(sql)
    for i in rv:
        if i['QUERY PLAN'].startswith("      :resname"):
            retext.append(i['QUERY PLAN'].replace("      :resname",''))
    return retext;
$ LANGUAGE plpythonu;


执行效果如下:

aligputf8=# select get_sql_column_name('select * from cxfa');
 get_sql_column_name 
---------------------
  a 
  b 
(2 rows)

Time: 32.037 ms
aligputf8=# select get_sql_column_name(pg_get_viewdef('pg_partitions'));
    get_sql_column_name     
----------------------------
  schemaname 
  tablename 
  partitionschemaname 
  partitiontablename 
  partitionname 
  parentpartitiontablename 
  parentpartitionname 
  partitiontype 
  partitionlevel 
  partitionrank 
  partitionposition 
  partitionlistvalues 
  partitionrangestart 
  partitionstartinclusive 
  partitionrangeend 
  partitionendinclusive 
  partitioneveryclause 
  partitionisdefault 
  partitionboundary 
(19 rows)

Time: 44.404 ms


 

 

  

<think>好的,我需要回答用户关于如何在Greenplum数据库中查看一个数据库的OID的问题。首先,我得回忆一下Greenplum的相关知识,因为它是基于PostgreSQL的,所以很多系统表和函数应该和PostgreSQL类似。 用户提到“数据库的oid”,OID是对象标识符,每个数据库对象都有一个唯一的OID。对于数据库来说,系统表pg_database里应该存储了这些信息。记得在PostgreSQL中,可以通过查询pg_database系统表来获取数据库的OID,使用datname和oid字段。 不过,用户具体是要通过什么方式查看呢?可能有几种方法。第一种是使用psql命令行工具,登录到数据库后执行SQL查询。第二种可能是使用Greenplum的管理工具,比如gpconfig或者gpstate,不过这些可能更多用于集群管理,不确定是否有直接查OID的功能。 首先确认查询系统表的方法。在PostgreSQL中,查询SELECT oid, datname FROM pg_database; 就可以得到所有数据库的OID和名称。同样的方法应该适用于Greenplum,因为它们的系统表结构相似。 另外,用户可能需要查找特定数据库的OID,这时候可以在WHERE子句中指定datname。例如,SELECT oid FROM pg_database WHERE datname = '数据库名'; 这样可以直接获取目标数据库的OID。 还要考虑到Greenplum的分布式特性,是否需要在所有节点上执行?不过系统表pg_database应该是存在于Master节点上的全局表,所以只需要在Master节点查询即可。 另外,是否有其他方法?比如使用函数,例如pg_database.oid或者某个内置函数,不过可能直接查询系统表更直接。 需要验证这些步骤是否正确。例如,连接到Greenplum的Master节点,使用psql,然后运行上述查询,应该能返回正确的结果。同时提醒用户替换数据库名为实际需要查询的名称。 可能需要注意权限问题,用户需要有访问系统表的权限,比如超级用户或者具有相应权限的角色。 总结下来,步骤应该是: 1. 使用psql或其他客户端连接到Greenplum的Master节点。 2. 执行SQL查询:SELECT oid, datname FROM pg_database WHERE datname = '目标数据库名'; 3. 结果中的oid列即为所需。 确保语句中的单引号正确,数据库名称区分大小写吗?在PostgreSQL中,数据库名称是大小写敏感的,但如果在创建时使用了双引号,可能需要精确匹配。但通常情况下,使用小写即可,因为如果不加引号,名称会被转换为小写。所以在查询时,datname应该用小写,除非创建时指定了大写并用引号包裹。 可能还需要提醒用户,如果不知道数据库名,可以先执行SELECT * FROM pg_database; 查看所有数据库的列表和对应的OID。 最后,确保给出的示例准确,比如: SELECT oid FROM pg_database WHERE datname = 'mydatabase'; 或者使用转义符号,避免语法错误。 总之,关键点在于通过查询系统表pg_database,结合datname字段来获取对应的OID。</think>在Greenplum数据库中查看数据库OID的操作步骤如下: $$ SELECT oid FROM pg_database WHERE datname = 'your_database_name'; $$ **操作详解:** 1. **连接数据库** 使用`psql`或其他SQL客户端连接到Greenplum的Master节点: ```bash psql -h <主机名> -p <端口号> -U <用户名> -d <目标数据库名> ``` 2. **执行系统表查询** Greenplum沿用PostgreSQL系统表结构,通过查询`pg_database`系统目录表: ```sql -- 查看所有数据库OID列表 SELECT oid, datname FROM pg_database; -- 查看特定数据库OID(示例:查找数据库"mydb") SELECT oid FROM pg_database WHERE datname = 'mydb'; ``` 3. **结果解读** 执行后会返回数字格式的OID值(如`16384`),该标识符在集群中唯一对应目标数据库。 **注意事项:** - 需要具有`超级用户权限`或`pg_read_all_stats`角色权限 - 数据库名称严格区分大小写(默认按小写存储) - 若提示`relation "pg_database" does not exist`,请检查是否连接到了Master节点 **扩展应用:** 通过OID可快速定位数据库物理文件路径(数据目录路径为`$PGDATA/base/<OID>`),这对运维人员处理存储问题很有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值