`

oracle type的解析

 
阅读更多

Oracle 自定义TYPE 的几种用法

Oracle中的类型有很多种,主要可以分为以下几类: 
1、字符串类型。如:char、nchar、varchar2、nvarchar2。 
2、数值类型。如:int、number(p,s)、integer、smallint。 
3、日期类型。如:date、interval、timestamp。 
4、PL/SQL类型。如:pls_integer、binary_integer、binary_double(10g)、binary_float(10g)、boolean。plsql类型是不能在sql环境中使用的,比如建表时。 
5、自定义类型。


下面简单的枚举下常用的几种自定义类型。 
1、子类型。 
这种类型最简单,类似类型的一个别名,主要是为了对常用的一些类型简单化,它基于原始的某个类型。如: 
有些应用会经常用到一些货币类型:number(16,2)。如果在全局范围各自定义这种类型,一旦需要修改该类型的精度,则需要一个个地修改。 
那如何实现定义的全局化呢?于是就引出了子类型: 
subtype cc_num is number(16,2); 
这样就很方便地解决了上述的麻烦。

2、普通类型 
如: 
create or replace type typ_calendar as object( 
    年 varchar2(8), 
    月 varchar2(8), 
    星期日 varchar2(8), 
    星期一 varchar2(8), 
    星期二 varchar2(8), 
    星期三 varchar2(8), 
    星期四 varchar2(8), 
    星期五 varchar2(8), 
    星期六 varchar2(8), 
    本月最后一日 varchar2(2) 
); 
这种类型可以在表结构定义的时候使用: 
create table tcalendar of typ_calendar;

插入数据测试: 
SQL> insert into tcalendar 
  2  select typ_calendar('2010','05','1','2','3','4','5','6','7','31') from dual 
  3  /

注意:插入的数据需要用typ_calendar进行转换。

1 row inserted

--查看结果 
SQL> select * from tcalendar;

年       月       星期日   星期一   星期二   星期三   星期四   星期五   星期六   本月最后一日 
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------ 
2010     05       1        2        3        4        5        6        7        31

3、带成员函数的类型体(type body) 
这种类型包含了对类型中数据的内部处理,调用该类型时,可将处理后的数据返回给调用方。 
对上面的例子进行扩展。要求给当天加上特殊标识(【】)来突出显示。 
首先,在typ_calendar中增加一个成员函数声明: 
create or replace type typ_calendar as object( 
    年 varchar2(8), 
    月 varchar2(8), 
    星期日 varchar2(8), 
    星期一 varchar2(8), 
    星期二 varchar2(8), 
    星期三 varchar2(8), 
    星期四 varchar2(8), 
    星期五 varchar2(8), 
    星期六 varchar2(8), 
    本月最后一日 varchar2(2), 
   
    member function format( 
        curday date        := sysdate, 
        fmtlen pls_integer := 8 
    )return typ_calendar 

然后,创建一个type body,在type body中实现该成员函数: 
create or replace type body typ_calendar as 
    member function format( 
        curday date        := sysdate, 
        fmtlen pls_integer := 8 
    ) return typ_calendar as 
        v_return   typ_calendar := typ_calendar('','','','','','','','','',''); 
        v_dd       varchar2(2)  := to_char(curday, 'dd'); 
       
        function fmt( 
            fmtstr varchar2 
        )return varchar2 as 
        begin 
            return lpad(fmtstr, fmtlen, ' '); 
        end fmt; 
    begin 
        v_return.年 := 年; 
        v_return.月 := 月; 
        v_return.星期日 := fmt(星期日); 
        v_return.星期一 := fmt(星期一); 
        v_return.星期二 := fmt(星期二); 
        v_return.星期三 := fmt(星期三); 
        v_return.星期四 := fmt(星期四); 
        v_return.星期五 := fmt(星期五); 
        v_return.星期六 := fmt(星期六); 
        v_return.本月最后一日 := 本月最后一日;

        if (年 || lpad(月, 2, '0') = to_char(curday, 'yyyymm')) then 
            case v_dd 
            when 星期日 then 
                v_return.星期日 := fmt('【' || 星期日 || '】'); 
            when 星期一 then 
                v_return.星期一 := fmt('【' || 星期一 || '】'); 
            when 星期二 then 
                v_return.星期二 := fmt('【' || 星期二 || '】'); 
            when 星期三 then 
                v_return.星期三 := fmt('【' || 星期三 || '】'); 
            when 星期四 then 
                v_return.星期四 := fmt('【' || 星期四 || '】'); 
            when 星期五 then 
                v_return.星期五 := fmt('【' || 星期五 || '】'); 
            when 星期六 then 
                v_return.星期六 := fmt('【' || 星期六 || '】'); 
            else null; 
            end case; 
        end if; 
       
        return v_return; 
    end format; 
end;


插入测试数据: 
SQL> insert into tcalendar 
  2  select typ_calendar('2010','05','1','2','3','4','5','6','7','31') from dual 
  3  /

1 row inserted

SQL> insert into tcalendar 
  2  select typ_calendar('2010','05','1','2','3','4','5','6','7','31').format() from dual 
  3  /

1 row inserted

SQL> insert into tcalendar 
  2  select typ_calendar('2010','05','11','12','13','14','15','16','17','31').format() from dual 
  3  /

1 row inserted

SQL> select * from tcalendar;

年       月       星期日   星期一   星期二   星期三   星期四   星期五   星期六   本月最后一日 
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------ 
2010     05       1        2        3        4        5        6        7        31 
2010     05              1        2        3        4        5        6        7 31 
2010     05             11   【12】       13       14       15       16       17 31

可以看到数据已经居中处理了,并且到了第三条已经可以突出显示当前日期了。 
在这里type 中的成员函数(member function)和静态函数(static function)的区别有必要说明一下: 
成员函数有隐含参数self,即自身类型,可以在执行的时候引用当前的数据并对数据进行操作。它的调用可以如下:object_expression.method() 
静态函数没有该隐含参数。它的调用如下:type_name.method();

举个例子: 
首先,创建一个带静态函数声明的类型头: 
SQL> create or replace type typ_col as object( 
  2      col_name varchar2(30), 
  3      tab_name varchar2(30), 
  4      static function to_upper return typ_col 
  5  ) 
  6  /

Type created

然后创建类型体: 
SQL> 
SQL> create or replace type body typ_col as 
  2      static function to_upper 
  3      return typ_col as 
  4      begin 
  5          return typ_col(upper(col_name), upper(tab_name)); 
  6      end to_upper; 
  7  end; 
  8  /

Warning: Type body created with compilation errors

SQL> show errors 
Errors for TYPE BODY LYON.TYP_COL:

LINE/COL ERROR 
-------- --------------------------------------------------- 
5/30     PLS-00588: 非限定实例属性引用只允许在成员方法中使用 
5/9      PL/SQL: Statement ignored

错误信息表明,实例属性只能在成员方法中使用。这里隐去了self的调用,其实: 
typ_col(upper(col_name), upper(tab_name)); 
等价于: 
typ_col(upper(self.col_name), upper(self.tab_name)); 
而这种方式的使用根据前面的定义,只能在成员函数中实现: 
SQL> create or replace type typ_col as object( 
  2      col_name varchar2(30), 
  3      tab_name varchar2(30), 
  4      member function to_upper return typ_col 
  5  ) 
  6  /

Type created

SQL> 
SQL> create or replace type body typ_col as 
  2      member function to_upper 
  3      return typ_col as 
  4      begin 
  5          return typ_col(upper(self.col_name), upper(self.tab_name)); 
  6      end to_upper; 
  7  end; 
  8  /

Type body created

那两者调用上又有什么差别呢? 
按照前面的定义,静态函数的用法是type_name.method(),所以有: 
SQL> select typ_col.to_lower(x).tab_name, typ_col.to_lower(x).col_name from tcol 
  2  /

TYP_COL.TO_LOWER(X).TAB_NAME   TYP_COL.TO_LOWER(X).COL_NAME 
------------------------------ ------------------------------ 
ipseg_int_db_tmp               start_ip 
ipseg_int_db_tmp               end_ip 
ipseg_int_db_tmp               area_code 
px_city                        city_id 
px_city                        city_name 
px_city                        province_id 
px_citygdp                     gdp_cycle_id 
px_citygdp                     city_id 
px_citygdp                     gdp 
px_citygdp                     province_id

10 rows selected

SQL> select typ_col(column_name, table_name).to_upper().tab_name, 
  2  typ_col(column_name, table_name).to_upper().col_name 
  3  from user_tab_columns t 
  4  where rownum <= 10;

TYP_COL(COLUMN_NAME,TABLE_NAME TYP_COL(COLUMN_NAME,TABLE_NAME 
------------------------------ ------------------------------ 
DEMO                           X 
IPSEG_INT_DB_TMP               START_IP 
IPSEG_INT_DB_TMP               END_IP 
IPSEG_INT_DB_TMP               AREA_CODE 
PX_CITY                        CITY_ID 
PX_CITY                        CITY_NAME 
PX_CITY                        PROVINCE_ID 
PX_CITYGDP                     GDP_CYCLE_ID 
PX_CITYGDP                     CITY_ID 
PX_CITYGDP                     GDP

10 rows selected 
也就是说,静态函数主要是用于处理并返回外部数据的,而成员函数是用于处理并返回内部数据的。

然后可以在函数中使用该类型,下面是一个显示日历的函数,并调用类型的成员函数对结果做了格式化: 
create or replace function show_calendar( 
    v_yermonth varchar2  := to_char(sysdate, 'yyyymm')) 
return tbl_calendar as 
    v_cal tbl_calendar; 
    v_seg pls_integer := 6; 
    v_len pls_integer := 8; 
    v_yer varchar2(4) := substr(v_yermonth, 1, 4); 
    v_mon varchar2(2) := lpad(substr(v_yermonth, 5, 2), 2, '0'); 
    v_ini date := to_date(v_yermonth || '01', 'yyyymmdd'); 
begin 
    select typ_calendar(v_yer, v_mon, 
           case when rn >= wkn - 1 and rn - wkn + 2 <= mxdays 
           then  rn - wkn + 2 end, 
           case when rn >= wkn - 2 and rn - wkn + 3 <= mxdays 
           then  rn - wkn + 3 end, 
           case when rn >= wkn - 3 and rn - wkn + 4 <= mxdays 
           then  rn - wkn + 4 end, 
           case when rn >= wkn - 4 and rn - wkn + 5 <= mxdays 
           then  rn - wkn + 5 end, 
           case when rn >= wkn - 5 and rn - wkn + 6 <= mxdays 
           then  rn - wkn + 6 end, 
           case when rn >= wkn - 6 and rn - wkn + 7 <= mxdays 
           then  rn - wkn + 7 end, 
           case when rn >= wkn - 7 and rn - wkn + 8 <= mxdays 
           then  rn - wkn + v_len end, 
           mxdays).format() 
      bulk collect into v_cal 
      from (select (rownum - 1)*7 rn, 
                   to_number(to_char(trunc(v_ini, 'mm'), 'd')) wkn, 
                   to_number(to_char(last_day(v_ini), 'dd')) mxdays 
              from dual 
            connect by rownum <= v_seg) b 
     where rn - wkn + 2 <= mxdays; --过滤空行 
    return v_cal; 
end show_calendar;

获得当前月的日历: 
SQL> select * from table(show_calendar); 
/

年       月       星期日   星期一   星期二   星期三   星期四   星期五   星期六   本月最后一日 
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------ 
2010     05                                                                    1 31 
2010     05              2        3        4        5        6        7        8 31 
2010     05              9       10       11   【12】       13       14       15 31 
2010     05             16       17       18       19       20       21       22 31 
2010     05             23       24       25       26       27       28       29 31 
2010     05             30       31                                              31

6 rows selected

获取指定月份的日历: 
SQL> select * from table(show_calendar('201001'));

年       月       星期日   星期一   星期二   星期三   星期四   星期五   星期六   本月最后一日 
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------ 
2010     01                                                           1        2 31 
2010     01              3        4        5        6        7        8        9 31 
2010     01             10       11       12       13       14       15       16 31 
2010     01             17       18       19       20       21       22       23 31 
2010     01             24       25       26       27       28       29       30 31 
2010     01             31                                                       31

6 rows selected

显示多个月的日历: 
SQL> select b.* 
  2    from (select to_char(add_months(date'1998-01-01', rownum-1), 'yyyymm') c from dual connect by rownum <= 10) a, 
  3         table(show_calendar(to_char(a.c))) b 
  4  /

年       月       星期日   星期一   星期二   星期三   星期四   星期五   星期六   本月最后一日 
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------ 
1998     01                                                  1        2        3 31 
1998     01              4        5        6        7        8        9       10 31 
1998     01             11       12       13       14       15       16       17 31 
1998     01             18       19       20       21       22       23       24 31 
1998     01             25       26       27       28       29       30       31 31 
1998     02              1        2        3        4        5        6        7 28 
1998     02              8        9       10       11       12       13       14 28 
1998     02             15       16       17       18       19       20       21 28 
............... 
1998     09                                1        2        3        4        5 30 
1998     09              6        7        8        9       10       11       12 30 
1998     09             13       14       15       16       17       18       19 30 
1998     09             20       21       22       23       24       25       26 30 
1998     09             27       28       29       30                            30 
1998     10                                                  1        2        3 31 
1998     10              4        5        6        7        8        9       10 31 
1998     10             11       12       13       14       15       16       17 31 
1998     10             18       19       20       21       22       23       24 31 
1998     10             25       26       27       28       29       30       31 31

51 rows selected 
上面是一个特殊的table函数使用方法。 
即将a表中构造的月份,作为参数传入到table函数中的show_calendar函数中,然后show_calendar函数根据指定的月份返回 
该月的日历。实现了获取多个月日历的要求。

自定义type的一个限制是不能使用rowid类型:

SQL> create or replace type typ_rowid as object(rid urowid); 
  2  /

Warning: Type created with compilation errors

SQL> show errors; 
Errors for TYPE CUSTOMER21.TYP_ROWID:

LINE/COL ERROR 
-------- --------------------------------------------------- 
1/30     PLS-00530: 为此对象类型属性使用了非法类型: UROWID。


其他的特殊使用还有自定义聚集函数,典型的例子就是字符串相加的问题。 
我们知道,对数字列的相加很简单,直接求sum即可。但是如何对字符列进行相加呢? 
如: 
SQL> with tmp as ( 
  2  select '1' c from dual union all 
  3  select '2' c from dual union all 
  4  select '3' c from dual union all 
  5  select '4' c from dual) 
  6  select * from tmp 
  7  /







1,2,3,4要合并为1->2->3->4,该如何实现? 
一个办法是用层级查询来实现(用sys_connect_by_path即可)。 
另外,10g下,还可以用wm_sys.wm_concat函数来实现。 
还有就是自定义聚集函数了。自定义聚集函数首先要定义一个类型,在类型中调用了Oracle内部实现的几个接口函数: 
CREATE OR REPLACE TYPE "TYP_STRCAT" as object 

    strsum     varchar2(4000), 
    strcnt     number, 
    strdelimit varchar2(10),

    static function ODCIAggregateInitialize( 
        actx in out typ_strcat) 
    return number,

    member function ODCIAggregateIterate( 
        self in out typ_strcat, 
        val  in varchar2) 
    return number,

    member function ODCIAggregateTerminate( 
        self        in typ_strcat, 
        returnvalue out varchar2, 
        flags       in number) 
    return number,

    member function ODCIAggregateMerge( 
        self in out typ_strcat, 
        ctx2 typ_strcat) 
    return number 

CREATE OR REPLACE TYPE BODY "TYP_STRCAT" as 
    static function ODCIAggregateInitialize(actx in out typ_strcat) 
        return number as 
    begin 
        actx := typ_strcat(null, 1, ','); 
        return ODCICONST.Success; 
    end; 
    member function ODCIAggregateIterate(self in out typ_strcat, 
                                         val  in varchar2) return number as 
    begin 
        self.strsum := self.strsum || strdelimit || val; 
        self.strcnt := self.strcnt + 1; 
        return ODCICONST.Success; 
    end; 
    member function ODCIAggregateTerminate(self        in typ_strcat, 
                                           returnvalue out varchar2, 
                                           flags       in number) return number as 
    begin 
        returnvalue := ltrim(self.strsum, strdelimit); 
        return Odciconst.Success; 
    end; 
    member function ODCIAggregateMerge(self in out typ_strcat, 
                                       ctx2 in typ_strcat) return number as 
    begin 
        self.strsum := ctx2.strsum || self.strsum; 
        return Odciconst.Success; 
    end; 
end;

然后创建函数: 
CREATE OR REPLACE FUNCTION "SSUM" (p_str varchar2) 
return varchar2 
/*parallel_enable*/ aggregate using typ_strcat;

然后,就可以使用字符串相加的功能了:

SQL> with tmp as ( 
  2  select '1' c from dual union all 
  3  select '2' c from dual union all 
  4  select '3' c from dual union all 
  5  select '4' c from dual) 
  6  select replace(ssum(c), ',', '->') from tmp 
  7  /

REPLACE(SSUM(C),',','->') 
-------------------------------------------------------------------------------- 
1->2->3->4

 

4.表类型 
这种类型类似于一个数组类型,可以申明一维或多维。 
比如说,创建一个元素长度为4000的字符串数组,则有: 
create or replace type tbl_varchar2 as table of varchar2(4000)

然后可以如下使用该类型: 
SQL> select * from table(tbl_varchar2('1','1','3','4','5','6'));

COLUMN_VALUE 
-------------------------------------------------------------------------------- 





6

6 rows selected

如果要获取多字段的,则可以取上面例子: 
SQL> select * 
  2    from table(tbl_calendar( 
  3               typ_calendar('2008','2','3','4','5','6','7','8','9','28'), 
  4               typ_calendar('2009','12','13','4','5','6','7','8','9','31'), 
  5               typ_calendar('2010','12','13','4','5','6','7','8','9','31')));

年       月       星期日   星期一   星期二   星期三   星期四   星期五   星期六   本月最后一日 
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------ 
2008     2        3        4        5        6        7        8        9        28 
2009     12       13       4        5        6        7        8        9        31 
2010     12       13       4        5        6        7        8        9        31

以上使用的类型都基于schema级别,如果是定义在包、函数、过程等这些结构里是不能给table函数使用的。 
这种类型可以使用在管道函数中(pipelined function)。也可以存放中间处理的数据,类似于临时表的作用,但是是存放在内存中的。

 

转自http://blog.csdn.net/liyongjie/article/details/7395892

分享到:
评论

相关推荐

    oracle 用表结构创建 type

    在Oracle数据库环境中,使用现有的表结构来创建Type是一种常见的需求,尤其当涉及到复杂的数据类型时。根据提供的文件信息,本文将详细介绍如何利用Oracle中的表结构自动生成Type,并深入探讨其中涉及的关键概念和...

    oracle存储过程返回多行多列的结构化数组,java调用并解析

    Java作为常用的后端开发语言,与Oracle数据库交互时,调用这些存储过程并解析返回的数据是一项常见任务。 首先,我们需要理解Oracle中的结构化数组,也称为复合类型或集合类型。Oracle提供了两种主要类型的集合:...

    Oracle数据字典解析

    ### Oracle数据字典解析 #### 一、Oracle数据字典概览 Oracle数据字典是Oracle数据库中存储元数据(即关于数据的数据)的一系列特殊表和视图,用于描述数据库对象及其属性。数据字典提供了数据库内部结构的详细...

    oracle-ocp-051 答案解析

    根据提供的文件信息,我们可以深入分析Oracle OCP 051考试中的一个具体题目及解析,该题目主要关注的是Oracle数据库中的表创建与约束传递规则。 ### 题目背景 题目给出了SALES、CUSTOMERS、PRODUCTS以及TIMES四个...

    Oracle经典故障解析 连接数&会话数

    下面将详细解析这两个概念,以及它们在Oracle故障排查中的重要性。 1. 连接数和会话数的概念:在Oracle中,连接数指的是同一时间连接到数据库的用户数量。每次用户通过SQL客户端登录到数据库时,都建立了一个连接。...

    oracle利用UTL-HTTP包访问SOAP、HTTP接口并通过管道函数解析xml响应文件用游标以表方式输出

    ### Oracle 使用 UTL_HTTP 访问 SOAP/HTTP 接口并解析 XML 响应 #### 一、使用 utl_http 包之前需要做的数据库配置 为了确保 Oracle 数据库能够通过网络进行 HTTP 请求,首先需要对数据库进行一些配置,具体包括...

    Oracle深入解析

    ### Oracle深入解析知识点详解 #### 一、SQL简介与分类 **1.1 SQL介绍** - **SQL** (Structured Query Language 结构化查询语言): 是一种标准的数据管理语言,主要用于管理关系型数据库中的数据。 - **DDL ...

    oracle 数据库 自动创建表

    例如,如果使用Python,可以使用pandas库来读取.doc文档,解析其中的表格信息,然后使用cx_Oracle库连接到Oracle数据库并执行SQL。Python代码可能会如下所示: ```python import pandas as pd import cx_Oracle # ...

    oracle约束键解析.docx

    ### Oracle约束键解析 #### 一、数据库约束的作用与分类 **作用:** - **确保数据完整性:** 约束用于确保数据的正确性和一致性,防止错误数据被插入到数据库中。 - **遵循业务规则:** 约束帮助数据库符合业务...

    Oracle AWR与ASH性能报告深入解析

    ### Oracle AWR与ASH性能报告深入解析 #### 一、Oracle数据库版本信息 根据所提供的数据库版本信息,我们得知当前使用的Oracle版本为11g企业版,版本号为11.2.0.1.0,这是一个64位的生产环境版本。其中包含的组件...

    oracle格式化查看json数据

    例如,如果你有一个包含JSON对象的CLOB字段,你可以使用JSON_TYPE来检查特定键的类型,这在解析和验证数据时非常有用。 2. JSON_VALUE和JSON_QUERY: 这两个函数是提取JSON数据的核心工具。JSON_VALUE用于获取单个...

    ORACLE-TNS协议分析详解.doc

    - **Type (1字节)**:TNS类型,指示数据包的功能。 - **Flag (1字节)**:状态标志。 - **Header checksum (2字节)**:通用头的校验和。 其中,数据包类型定义如下: - **1 (CONNECT)**:连接类型。 - **2 (ACCEPT)*...

    oracle 使用XMLDOM包,保存XML节点数据到数据库表中,支持多个节点嵌套XML格式

    fpat_type VARCHAR2(10) NOT NULL, fpat_hosno VARCHAR2(32) NOT NULL, fmedcard_no VARCHAR2(32), fvisit_id VARCHAR2(32), fvisit_no VARCHAR2(32), fpat_cnname VARCHAR2(80) NOT NULL, fpat_enname ...

    Oracle数据库驱动及连接字符串

    2. Type 2:部分Java,部分本地代码,处理数据库连接和SQL语句解析。 3. Type 3:完全基于Java,通过网络协议与数据库服务器通信,适用于跨平台环境。 4. Type 4:纯Java,直接与数据库通信,性能最优,适用于高性能...

    oracle调用webservice接口地址demo

    ### Oracle调用WebService接口地址Demo解析 #### 一、引言 在企业级应用开发中,不同系统间的集成与通信尤为重要。Oracle数据库作为一款广泛使用的数据库管理系统,支持多种方式与其他系统进行交互,其中通过调用...

    jdbc 源码 oracle 自带jdbc

    Oracle JDBC驱动通常属于Type 4,即纯Java的网络驱动,它提供了与Oracle数据库的高效、完全基于Java的通信方式,无需依赖于本地库。 源码分析主要涉及以下几个核心组件: 1. `Driver`接口:所有JDBC驱动都必须实现...

    vb6连接oracle的代码(更新数据库)测试

    以下是一份详细的知识点解析,将介绍如何使用VB6与Oracle 10G建立连接,并进行数据库操作。 首先,你需要在VB6环境中引入Oracle的数据提供者——ODBC驱动程序或Oracle Data Provider for .NET (ODP.NET),以实现与...

    NETBACKUP oracle 恢复脚步

    根据提供的文件信息,本文将详细解析NETBACKUP在Oracle数据库中的恢复步骤与脚本内容,重点探讨如何通过NETBACKUP实现Oracle数据库恢复到指定时间点的功能。 ### 一、NETBACKUP简介 NETBACKUP是Veritas公司开发的...

    oracle blob转文件读取

    OracleParameter param = new OracleParameter(blobName, OracleType.Blob, blob.Length, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, blob); cmd.Parameters.Add(param); // 执行...

Global site tag (gtag.js) - Google Analytics