
# 访问特殊数据类型
ecpg支持numeric、decimal、date、timestamp和interval数据类型。由于这些数据类型的内部结构较为复杂，无法被映射到初级数据类型的宿主变量，因此应用程序通过声明特殊类型的宿主变量，以及使用pgtypes库中的函数来处理这些特殊类型。pgtypes库中的接口函数请参见[ecpg接口参考](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0300.html)章节。
- timestamp、date
  程序必须包含timestamp类型的头文件：
  ```
  #include <pgtypes_timestamp.h>
  ```
  在声明部分中声明类型为timestamp的宿主变量：
  ```
  EXEC SQL BEGIN DECLARE SECTION;
      timestamp ts;
  EXEC SQL END DECLARE SECTION;
  ```
  读取值到宿主变量之后，使用pgtypes库函数进行处理。如下示例中，使用PGTYPEStimestamp_to_asc()函数将timestamp值转换成文本形式：
  ```
  EXEC SQL SELECT now()::timestamp INTO :ts;
  printf("ts = %s\n", PGTYPEStimestamp_to_asc(ts));
  ```
  示例输出如下：
  ```
  ts = 2022-06-27 18:03:56.949343
  ```
  另外，date类型可以用相同的方式处理。程序必须包括pgtypes_date.h头文件，声明一个date类型的宿主变量并用PGTYPEdata_to_asc()函数将其转换成文本形式。
  

- interval interval类型的处理与timestamp和date类型类似，不同的是interval类型变量的存储空间需要分配在堆内存中。
  示例如下：
  ```
  #include <stdio.h>
  #include <stdlib.h>
  #include <pgtypes_interval.h>
  int main(void)
  {
      EXEC SQL BEGIN DECLARE SECTION;
      interval *in;
      EXEC SQL END DECLARE SECTION;
      /* 需提前创建testdb库 */
      EXEC SQL CONNECT TO testdb;
      in = PGTYPESinterval_new();
      EXEC SQL SELECT '1 min'::interval INTO :in;
      printf("interval = %s\n", PGTYPESinterval_to_asc(in));
      PGTYPESinterval_free(in);
      EXEC SQL COMMIT;
      EXEC SQL DISCONNECT ALL;
      return 0;
  }
  ```
  运行结果如下：
  ```
  interval = @ 1 min
  ```
  

- numeric、decimal numeric和decimal类型的处理类似于interval类型，需要定义一个指针，在堆上分配一些内存空间并且使用pgtypes库函数访问该变量。
  示例如下：
  ```
  #include <stdio.h>
  #include <stdlib.h>
  #include <pgtypes_numeric.h>
  EXEC SQL WHENEVER SQLERROR STOP;
  int main(void)
  {
      EXEC SQL BEGIN DECLARE SECTION;
      numeric *num;
      numeric *num2;
      decimal *dec;
      EXEC SQL END DECLARE SECTION;
      
      /* 需提前创建testdb库 */
      EXEC SQL CONNECT TO testdb;
      num = PGTYPESnumeric_new();
      dec = PGTYPESdecimal_new();
      EXEC SQL SELECT 12.345::numeric(4,2), 23.456::decimal(4,2) INTO :num, :dec;
      printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 0));
      printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 1));
      printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 2));
      
      /* 转换十进制到数值型以显示十进制值 */
      num2 = PGTYPESnumeric_new();
      PGTYPESnumeric_from_decimal(dec, num2);
      printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 0));
      printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 1));
      printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 2));
      PGTYPESnumeric_free(num2);
      PGTYPESdecimal_free(dec);
      PGTYPESnumeric_free(num);
      EXEC SQL COMMIT;
      EXEC SQL DISCONNECT ALL;
      return 0;
  }
  ```
  运行结果如下：
  ```
  numeric = 12
  numeric = 12.4
  numeric = 12.35
  decimal = 23
  decimal = 23.5
  decimal = 23.46
  ```
  
 
