如何实现100%的动态数据管道(二)

主要思路解决了,下面开始写详细设计(以Sybase ASE数据库为例,其他各位扩展):

            1.建立中间层表vdt_columns,这个表的属性用于构建管道中的列资料.


            执行类似的代码生成:

            ls_sql = "create table vdt_columns ("
            ls_sql +="uid              int             null    ,"
           ls_sql +="upkey            varchar(1)      null    ,"
           ls_sql +="udmid      int         null,"
           ls_sql +="udmname    varchar(30)   null,"
           ls_sql +="unulls           varchar(1)     null    ,"
           ls_sql +="uwidth           int       null    ,"
           ls_sql +="uscale         int         null,"
           ls_sql +="uname         varchar(30)   null,"
           ls_sql +="udefault       varchar(255)  null,"  
           ls_sql +="ucheck         varchar(255)  null,"    
           ls_sql +="uidentity        int     null"
           ls_sql +=")"
   
           EXECUTE IMMEDIATE :ls_sql using SrcSqlca;

        2.构建其他相关的可能用到中间层视图:

           系统对象视图:

            ls_sql = 'create view vdt_objects (uid,uuid,uname,utype) as'+&
               ' select id,uid,name,(case type when~'TR~' then ~'T~' else type end) from sysobjects'
              EXECUTE IMMEDIATE :ls_sql using SrcSqlca;

        系统表视图:

        ls_sql = 'create view vdt_tables (uid,uuid,uname)as'+&
               ' select id,uid,name from sysobjects where type = ~'U~''
          EXECUTE IMMEDIATE :ls_sql using SrcSqlca;

      3.初始化vdt_columns 表.

        insert vdt_columns
   select sc.id,so.name,sc.colid,'N',sc.type,
      (case when (select count(*) from systypes st where sc.type=st.type and sc.usertype=st.usertype)=0 then (select max(st.name) from systypes st where sc.type=st.type) else (select st.name from systypes st where sc.type=st.type and sc.usertype=st.usertype) end),
      'N',(case when prec is not null then isnull(sc.prec,0) else sc.length end),
      sc.scale,sc.name,substring(sy.text,9,char_length(sy.text) -8),"0",(case when sc.status=128 then 1 else 0 end)
     from syscolumns sc,sysobjects so ,syscomments sy
    where sc.id*=so.id and sc.cdefault*=sy.id
    using SrcSqlca;
    
    在Sybase中,确定主键列比较麻烦:

    declare cur_vdtcolumns cursor for
   select distinct utname from vdt_columns
   using SrcSqlca;
   
   open cur_vdtcolumns;
   
   fetch cur_vdtcolumns into :ls_utname;
   
   do while SrcSqlca.sqlcode=0
    wait(true)
    ls_nulls='';ls_pkey=''
    of_getnull_ase(ls_utname,ls_nulls)
 
    of_getpk_ase(ls_utname,ls_pkey)
    if len(ls_pkey)>0 then
     update vdt_columns
      set upkey = 'Y',unulls='N'
      where CHARINDEX(uname,:ls_pkey)>0
      and utname = :ls_utname
      using SrcSqlca;
    end if
    fetch cur_vdtcolumns into :ls_utname;
   loop
  end if

    其中of_getpk_ase()用于确定某列是否是主键.

    /*Out of date*/
Long Ll_Cnt
int Li_keycnt,Li_indexid,Li_indstat,Li_indstat2

String Ls_keys,Ls_ThisKey
int Li_i

If Not IsValid(SrcSqlca) Then return -1

Select Count(*) Into :Ll_Cnt From sysobjects Where name = :as_tablename Using SrcSqlca;
If Ll_Cnt <= 0 Then
 return -2
End if

DECLARE curs_sysindexes CURSOR FOR
 SELECT keycnt, indid, status, status2
 FROM   sysindexes
 WHERE  id = object_id(:as_tablename)   AND indid > 0 Using SrcSqlca;

OPEN curs_sysindexes ;

FETCH curs_sysindexes INTO  :Li_keycnt, :Li_indexid, :Li_indstat, :Li_indstat2;

do while (SrcSqlca.Sqlcode = 0)
 If Mod(int(Li_indstat2/2),2) = 1 Then
  
  IF Mod(int(Li_indstat/2048),2) = 1 Then  //主键
  
   Ls_Keys = ''
   Li_i = 1
   
   do while Li_i <=Li_keycnt
    Select distinct index_col(:as_tablename, :Li_indexid, :Li_i) into :Ls_ThisKey
     From vdt_columns Using SrcSqlca;
    If Isnull(Ls_ThisKey) Then
     Exit
    Else
     If Li_i > 1 Then Ls_keys += ','
     Ls_Keys += Ls_ThisKey
    End if
    Li_i ++
   loop
  End if
 End if
 FETCH curs_sysindexes INTO  :Li_keycnt, :Li_indexid, :Li_indstat, :Li_indstat2;
loop
CLOSE curs_sysindexes;

as_keys=Ls_keys
return 1

    经过以上的步骤,中间层的数据就基本获得了,根据这些数据,基本上能够无误差的传输绝大部分表.构建了中间层,为以后的不同数据库的扩展打下了一个良好的基础.

不同的数据库,构造中间层的语法各有不同,但是中间层的表(视图)的结构是一样的,这样程序中处理的方法也统一了.

    待续...

    

    

你可能感兴趣的:(如何实现100%的动态数据管道(二))