2014-02-26 3 views
0

우선 Oracle PLSQL에서 나는 녹슬었고 몇몇 사람들은 이것이 할 수 없다고 말했고 다른 사람들은 할 수 있다고 말했고, 나는 그렇게 할 수 없다고 보았습니다. 어떤 도움이라도 대단히 감사하겠습니다.PLSQL이 레코드의 값을 동적으로 가져 오는 중입니까?

동적으로 레코드 유형의 열 값을 읽으려고합니다.

토큰이있는 메시지가있어서 토큰을 레코드 집합의 값으로 대체해야합니다. 내가 토큰을 구문 분석하고 다른 곳이

[AGENT_NAME]에서 [상태] :

그래서 메시지가 같습니다. 나는이가 함께 수행 할 수 있습니다 알고 자바 스크립트에서

:

: (콘솔에서 실행됩니다)

var record = { 
    status : "Open", 
    agent_name : "John" 
}; 

var record2 = { 
    status : "Close", 
    agent_name : "Joe" 
}; 
var records = [record, record2]; 

var token1 = "status"; 
var token2 = "agent_name"; 



for(var i=0; i<records.length; i++){ 
    console.log(records[i][token1] + " by " + records[i][token2]); 
} 


Results : Open by John 
      Close by Joe 

내가 여기

PLSQL

에서 같은 일을하고 싶지는 내 테스트 PLSQL입니다
SET SERVEROUTPUT ON; 
declare 

    TYPE my_record is RECORD 
    (
     status   VARCHAR2(30), 
     agent_name  varchar2(30) 
    ); 

    TYPE my_record_array IS VARRAY(6) OF my_record; 
    v_records   my_record_array := my_record_array(); 
    v_current_rec  my_record; 
    v_current_rec2  my_record; 
    v_token    varchar2(50):= 'agent_name'; 
    v_token2    varchar2(50):= 'status'; 

begin 

    v_current_rec.status := 'Open'; 
    v_current_rec.agent_name := 'John'; 
    v_records.extend; 
    v_records(1) := v_current_rec; 

    v_current_rec2.status := 'Close'; 
    v_current_rec2.agent_name := 'Ron'; 
    v_records.extend; 
    v_records(2) := v_current_rec2; 

    FOR i IN 1..v_records.COUNT LOOP 
     --Hard coded 
     DBMS_OUTPUT.PUT_LINE(v_records(i).status || ' by ' || v_records(i).agent_name); 

     --Substitution vars entering v_records(i).status and v_records(i).agent_name for the prompts. 
     --How to do this without user interaction. 
     DBMS_OUTPUT.PUT_LINE(&status || ' by ' || &agent_name); 

     --Dynamically that doesn't work. How would this be accomplished 
     DBMS_OUTPUT.PUT_LINE(v_records(i).v_token || ' by ' || v_records(i).v_token2); 
    END LOOP; 
END; 

대체 변수를 사용하여 시도해 보았습니다. 사용하는 경우 작동합니다.

DBMS_ 프롬프트가 표시되면 OUTPUT.PUT_LINE (& agent_name)을 입력하고 v_records (i) .agent_name을 입력하십시오. 어떻게해야합니까?

답변 :

set serveroutput on; 
DECLARE 
type sr_record_map 
IS 
    TABLE OF VARCHAR2(30) INDEX BY VARCHAR2(30); 


type record_set 
is 
TABLE of sr_record_map index by BINARY_INTEGER; 

    v_current_rec    sr_record_map; 
    v_record_set    record_set; 
    v_token     varchar2(30) := 'status'; 
    v_token2     varchar2(30) := 'agent_name'; 

    v_index     number :=1; 

begin 
v_current_rec('status') := 'Open'; 
v_current_rec('agent_name') := 'John'; 
v_record_set(1) := v_current_rec; 

v_current_rec('status') := 'Close'; 
v_current_rec('agent_name') := 'Joe'; 
v_record_set(2) := v_current_rec; 

FOR i in 1..v_record_set.COUNT LOOP 
    v_current_rec := v_record_set(i); 
    DBMS_OUTPUT.PUT_LINE(v_current_rec(v_token) || ' by ' || v_current_rec(v_token2)); 
END LOOP; 
end; 
+0

회원님의 기록에는 구성원 (열)이있을 수 있으며이를 선택하여 인쇄 할 수 있습니까? –

+0

여러 개의 토큰이있을 수있는 메시지가 여러 개 있습니다. 나는 현장이 기록에 있다는 것을 알고 있습니다. 따라서 토큰 agent_name이 있으면 v_records (i) .agent_name 문자열을 평가하고 레코드에서 값을 가져 오려고합니다. 따라서 메시지의 토큰을 값으로 바꿀 수 있습니다. – John

답변

2

단지 자바지도 같은 ASSOCIATIVE ARRAY

DECLARE 
type my_record_map 
IS 
    TABLE OF VARCHAR2(30) INDEX BY VARCHAR2(30); 
type my_record 
IS 
    record 
    (
    my_members my_record_map); 
type final_map 
IS 
    TABLE OF my_record INDEX BY VARCHAR2(20); 
    v_final_map final_map; 
    v_my_record_map my_record_map; 
    v_my_record my_record; 
    index_name VARCHAR2(100); 
    index_name_record VARCHAR2(100); 
BEGIN 
    /* Individual Records as key value pairs with their Corresponding Columns */ 
    /* You can put any member name inside */ 

    v_my_record_map('status')  := 'Open'; 
    v_my_record_map('agent_name') := 'John'; 
    v_my_record_map('added_by') := 'Maheshwaran'; 


    /* Put it as a record */ 
    v_my_record.my_members := v_my_record_map; 

    /* Put the record inside Another Map with any Key */ 
    v_final_map('Record1')  := v_my_record; 


    v_my_record_map('status')  := 'Close'; 
    v_my_record_map('agent_name') := 'Joe'; 
    v_my_record_map('added_by') := 'Ravisankar'; 

    v_my_record.my_members := v_my_record_map; 

    v_final_map('Record2')  := v_my_record; 

    /* Take the First Key in the Outer most Map */ 
    index_name   := v_final_map.FIRST; 
    LOOP 
    /* status Here can be dynamic */ 
    DBMS_OUTPUT.PUT_LINE(CHR(10)||'######'||v_final_map(index_name).my_members('status') ||' by '||v_final_map(index_name).my_members('agent_name')||'######'||CHR(10)); 

    index_name_record := v_final_map(index_name).my_members.FIRST; 
    DBMS_OUTPUT.PUT_LINE('$ Ávailable Other Members + Values.. $'||CHR(10)); 
    LOOP 
     DBMS_OUTPUT.PUT_LINE('  '||index_name_record ||'='||v_final_map(index_name).my_members(index_name_record)); 
     index_name_record := v_final_map(index_name).my_members.NEXT(index_name_record); 
     EXIT WHEN index_name_record IS NULL; 
    END LOOP; 
    /* Next gives you the next key */ 
    index_name := v_final_map.NEXT(index_name); 
    EXIT WHEN index_name IS NULL; 
    END LOOP; 
END; 
/

출력 : 예를 들어

######Open by John###### 

$ Ávailable Other Members + Values.. $ 

    added_by=Maheshwaran 
    agent_name=John 
    status=Open 

######Close by Joe###### 

$ Ávailable Other Members + Values.. $ 

    added_by=Ravisankar 
    agent_name=Joe 
    status=Close 
+0

이것은 그 것이다. 이 예제에서는 내 질문에 대답을 게시 할 것입니다. – John

0

나는 그것이 레코드 종류와 함께 할 수 있다고 생각하지 않습니다. 데이터 딕셔너리에서 필드를 쿼리 할 수 ​​있기 때문에 객체 유형이 가능할 수 있지만 일반적으로 사용할 수있는 곳이 어디에도 없습니다 (활성화 된 경우 허용 할 수있는 PL/Scope이라는 11g 기능이 있지만).

레코드 유형을 사용중인 동일한 위치에 정의하고 있기 때문에 관리 가능한 개수의 필드가있는 경우 방금 (!) 낭비되는 각 토큰을 바꾸는 것이 더 간단 할 수 있습니다 메시지에 메시지가 없으면 약간의 CPU :

declare 

    TYPE my_record is RECORD 
    (
     status   VARCHAR2(30), 
     agent_name  varchar2(30) 
    ); 

    TYPE my_record_array IS VARRAY(6) OF my_record; 
    v_records   my_record_array := my_record_array(); 
    v_current_rec  my_record; 
    v_current_rec2  my_record; 
    v_message   varchar2(50):= '[status] by [agent_name]'; 
    v_result    varchar2(50); 
begin 

    v_current_rec.status := 'Open'; 
    v_current_rec.agent_name := 'John'; 
    v_records.extend; 
    v_records(1) := v_current_rec; 

    v_current_rec2.status := 'Close'; 
    v_current_rec2.agent_name := 'Ron'; 
    v_records.extend; 
    v_records(2) := v_current_rec2; 

    FOR i IN 1..v_records.COUNT LOOP 
     v_result := v_message; 
     v_result := replace(v_result, '[agent_name]', v_records(i).agent_name); 
     v_result := replace(v_result, '[status]', v_records(i).status); 
     DBMS_OUTPUT.PUT_LINE(v_result);  
    END LOOP; 
END; 
/

anonymous block completed 
Open by John 
Close by Ron 

물론 유지 관리해야합니다. 레코드 유형에 필드가 추가 된 경우 일치하는 replace이 본문에 추가되어야합니다.

나는 현실 세계에서 토큰으로 완성 된 메시지 텍스트가 프로 시저로 전달된다고 가정합니다. 나는 당신이 다른 것을 필요로하지 않는다면 토큰을 파싱 할 가치가 있는지 확신하지 못한다. 사용

+0

우리는 비슷한 것을 만들었지 만, 기본적으로 이것을 동적으로 만들어서 프로 시저로 보내는 레코드에 데이터를 추가 한 다음 메시지에 새 토큰을 삽입 할 수 있습니다. 이 proc는 레코드 세트와 메시지를 얻습니다. 레코드의 열에 "자동"매핑 만들기. – John

+0

@ 존 - 레코드의 각 필드에 대해 하나의 '대체'가있는 한 역동적으로 만드는 것이 무엇인지 명확하지 않습니다. 필드가 레코드에 정의되어 있지 않으면 메시지에 새 토큰을 추가 할 수 없습니까? 어쩌면 레코드 컬렉션을 전혀 원하지 않을 수도 있지만, 런타임에 필드를 변경해야하는 경우 연관 배열을 사용할 수 있습니까? –

+0

이것은 단지 프로토 타입 일뿐입니다. 유형은 실제로 다른 곳에서 정의됩니다. 나는 변화의 포인트를 최소화하려고 노력하고있다. 우리는이 proc에 레코드 세트를 보낼 procs을 여러 개 가지고 있습니다. 나는 다른 procs가 바뀔 때마다 이것을 바꿔야하는 것을 막고 싶다. – John

0

, 내가 부착있어 간단한 코드 동적의 두 기록을 비교할 수있는 데이터의 차이를 얻기 위해 테이블과 ID 값의 이름으로 모든 테이블.

DECLARE 

p_id_1 NUMBER DEFAULT 697403; 
p_id_2 NUMBER DEFAULT 697402; 
p_table_name VARCHAR2(200) DEFAULT 'Name of the table'; 
V_result_1 VARCHAR2(2000); 
V_result_2 VARCHAR2(2000); 

CURSOR cur IS 
SELECT * FROM ALL_TAB_COLUMNS WHERE table_name = p_table_name ; 

BEGIN 

FOR rec IN cur LOOP 

EXECUTE IMMEDIATE 
     'SELECT ' || rec.COLUMN_NAME || ' FROM ' || P_TABLE_NAME || 
     ' WHERE ID = :1 ' 
     INTO V_result_1 
     USING P_ID_1 
     ; 

EXECUTE IMMEDIATE 
     'SELECT ' || rec.COLUMN_NAME || ' FROM ' || P_TABLE_NAME || 
     ' WHERE ID = :1 ' 
     INTO V_result_2 
     USING P_ID_2 
     ; 

IF NVL(v_result_1, 0) <> NVL(v_result_2,0) THEN 
DBMS_OUTPUT.PUT_LINE('Column_name ' || rec.column_name || ' ' || v_result_1 || '\' || v_result_2); 
END IF; 

END LOOP; 

END; 
관련 문제