用DBMS_LDAP實現LDAP與ORACLE的資料同步

lnwxzyp發表於2011-04-29
     很久沒有在blog上寫東西了,前一段時間在忙結婚的事。人生的一件大事總算是完成了。 婚假結束之後,公司安排讓協助其他部門的同事開發幾個儲存過程,接到任務以後去了解了一下情況說是要開發一個oracle跟LDAP同步更新的一個東西,由於沒有接觸過LDAP,大概google了一下,說這是一個類似於表格的東西,但是嚴格來說沒有列和行的分佈,有些類似於登錄檔或者資源管理器當中的那種分級的資料。經過多方查詢資料,實際上網上的資料還有官方的資料都比較的多,有很多可以借鑑的。下面就把具體的過程貼出來供大家參考:

CREATE OR REPLACE PROCEDURE PSTATIC_SYNC
AS
  -- Adjust as necessary.
  l_ldap_host    VARCHAR2(256) := '10.10.220.15';  --LDAP伺服器的IP地址
  l_ldap_port    VARCHAR2(256) := '389';                    --LDAP伺服器的預設埠
  l_ldap_user    VARCHAR2(256) := 'uid=binder,dc=sctel,dc=com,dc=cn'; --使用者名稱
  l_ldap_passwd  VARCHAR2(256) := 'stat919';    --密碼
  l_ldap_base    VARCHAR2(256) := 'cn=users,dc=scdbc,dc=com,dc=cn'; --要訪問的資料範圍 主要通過cn=xxx來進行區別

  l_retval       PLS_INTEGER;
  l_session      DBMS_LDAP.session;
  l_attrs        DBMS_LDAP.string_collection;
  l_message      DBMS_LDAP.message;
  l_entry        DBMS_LDAP.message;
  l_attr_name    VARCHAR2(256);
  l_ber_element  DBMS_LDAP.ber_element;
  l_vals         DBMS_LDAP.string_collection;

BEGIN
  -- Choose to raise exceptions.
  DBMS_LDAP.USE_EXCEPTION := TRUE;

  -- Connect to the LDAP server.
  l_session := DBMS_LDAP.init(hostname => l_ldap_host,
                              portnum  => l_ldap_port);

  l_retval := DBMS_LDAP.simple_bind_s(ld     => l_session,
                                      dn     => l_ldap_user,
                                      passwd => l_ldap_passwd);

  -- Get all attributes
  l_attrs(1) := '*'; -- retrieve all attributes
  l_retval := DBMS_LDAP.search_s(ld       => l_session,
                                 base     => l_ldap_base,
                                 scope    => DBMS_LDAP.SCOPE_SUBTREE,
                                 filter   => 'objectclass=*',
                                 attrs    => l_attrs,
                                 attronly => 0,
                                 res      => l_message);

  IF DBMS_LDAP.count_entries(ld => l_session, msg => l_message) > 0 THEN
    -- Get all the entries returned by our search.
    l_entry := DBMS_LDAP.first_entry(ld  => l_session,
                                     msg => l_message);

    << entry_loop >>
   WHILE l_entry IS NOT NULL LOOP
      -- Get all the attributes for this entry.
      l_attr_name := DBMS_LDAP.first_attribute(ld        => l_session,
                                               ldapentry => l_entry,
                                               ber_elem  => l_ber_element);

      << attributes_loop >>
      WHILE l_attr_name IS NOT NULL LOOP
        -- Get all the values for this attribute.
        BEGIN
        l_vals := DBMS_LDAP.get_values (ld        => l_session,
                                        ldapentry => l_entry,
                                        attr      => 'cn');
                                        
        EXECUTE IMMEDIATE 'TRUNCATE TABLE member_cn';
        
        << values_loop >>
        FOR i IN l_vals.FIRST .. l_vals.LAST LOOP

         INSERT INTO MEMBER_CN (USER_NAME) VALUES (l_vals(i));
         COMMIT;
         
        END LOOP values_loop;
        
        EXCEPTION WHEN
          OTHERS THEN
            NULL;  
        END;
由於LDAP資料裡面存在為0位元組的資訊,所以遇到這種情況不能選取所有的資訊,只能有選擇的獲取需要檢視的資訊
------------------------首先獲取使用者ID---------------------------------------------
        BEGIN
        l_vals := DBMS_LDAP.get_values (ld        => l_session,
                                        ldapentry => l_entry,
                                        attr      => 'uid');
--迴圈之前先截斷接受UID值的表
        EXECUTE IMMEDIATE 'TRUNCATE TABLE member_uid';
--開始獲取UID的值        
        << values_loop >>
        FOR i IN l_vals.FIRST .. l_vals.LAST LOOP

        INSERT INTO MEMBER_UID (USER_ID) VALUES (l_vals(i));
        COMMIT; 
         
        END LOOP values_loop;
        
        EXCEPTION WHEN
          OTHERS THEN
            NULL;  
        END;     
-------------------------獲取使用者手機號碼--------------------------------------------        
        BEGIN
        l_vals := DBMS_LDAP.get_values (ld        => l_session,
                                        ldapentry => l_entry,
                                        attr      => 'mobile');
--截斷後接受手機資訊
        EXECUTE IMMEDIATE 'TRUNCATE TABLE member_mobile';
          
        << values_loop >>
        FOR i IN l_vals.FIRST .. l_vals.LAST LOOP

        INSERT INTO MEMBER_MOBILE (MOBILE) VALUES (l_vals(i));
        COMMIT; 
              
        END LOOP values_loop;    
        
        EXCEPTION WHEN
          OTHERS THEN
            NULL;  
        END;
-------------------------------公司名稱-------------------------------------
        BEGIN
        l_vals := DBMS_LDAP.get_values (ld        => l_session,
                                        ldapentry => l_entry,
                                        attr      => 'companyName');
--截斷後插入資料
        EXECUTE IMMEDIATE 'TRUNCATE TABLE member_companyName';
        
        << values_loop >>
        FOR i IN l_vals.FIRST .. l_vals.LAST LOOP

        INSERT INTO member_companyname (company_name) VALUES (l_vals(i));
        COMMIT; 
         
        END LOOP values_loop;
        
        EXCEPTION WHEN
          OTHERS THEN
            NULL;  
        END;     
-----------------------------獲取公司ID---------------------------------------
        BEGIN
        l_vals := DBMS_LDAP.get_values (ld        => l_session,
                                        ldapentry => l_entry,
                                        attr      => 'companyId');
--截斷後插入資料
        EXECUTE IMMEDIATE 'TRUNCATE TABLE member_companyid';
        
        << values_loop >>
        FOR i IN l_vals.FIRST .. l_vals.LAST LOOP

        INSERT INTO member_companyid (company_id) VALUES (l_vals(i));
        COMMIT; 
         
        END LOOP values_loop;
        
        EXCEPTION WHEN
          OTHERS THEN
            NULL;  
        END;           
--獲取下一組使用者資訊
        l_attr_name := DBMS_LDAP.next_attribute(ld        => l_session,
                                                ldapentry => l_entry,
                                                ber_elem  => l_ber_element);
      END LOOP attibutes_loop;    --結束資訊獲取迴圈

        INSERT INTO 
          user_sync (
                user_name,
                user_id,
                mobile,
                company_name,
                company_id ) 
        SELECT (SELECT user_name FROM member_cn WHERE rownum=1),
               (SELECT user_id FROM member_uid WHERE rownum=1),
               (SELECT mobile FROM member_mobile WHERE rownum=1),
               (SELECT company_name FROM member_companyname where rownum=1),
               (SELECT company_id FROM member_companyid where rownum=1)
        FROM dual;
        COMMIT;
        
      l_entry := DBMS_LDAP.next_entry(ld  => l_session,
                                      msg => l_entry);
    END LOOP entry_loop;
  END IF;

  -- Disconnect from the LDAP server.
  l_retval := DBMS_LDAP.unbind_s(ld => l_session);
  
  --sync user info.
    MERGE INTO user_info i
    USING user_sync s
    ON (i.user_id = s.user_id)
    WHEN MATCHED THEN
      UPDATE SET
      i.user_name=s.user_name,
      i.mobile=s.mobile,
      i.company_name=s.company_name,
      i.company_id=s.company_id
    WHEN NOT MATCHED THEN 
      INSERT VALUES (s.user_name,s.user_id,s.user_id,s.mobile,'Y',s.company_name,s.company_id);
    COMMIT;
    
    DELETE FROM user_info WHERE user_id IN (
      SELECT user_id FROM user_info 
      MINUS
      SELECT user_id FROM user_sync) AND is_init = 'Y';
    COMMIT;
    
    EXECUTE IMMEDIATE 'TRUNCATE TABLE user_sync';
END;

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12216142/viewspace-694079/,如需轉載,請註明出處,否則將追究法律責任。

相關文章