首先,我在Oracle PLSQL上真的很生气,我看到有几个人说这不能做,而其他人说它可以做到,而我却无法实现。任何帮助将不胜感激。
我正在尝试动态读取记录类型中列的值。
我有一个带令牌的消息,我需要用记录集中的值替换令牌。
所以消息看起来像是:[agent_name]
的[status]我还有另外一个解析标记的地方。
在java脚本中我知道这可以通过以下方式完成:(将在Console中运行)
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(&amp; 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 :(得分:2)
像使用Java中的地图一样使用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
答案 1 :(得分: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
添加到正文中。
我假设在现实世界中,带有标记的消息文本将被传递给过程。我不确定是否值得解析令牌,除非你需要它们用于别的东西。
答案 2 :(得分:0)
作为一个例子,我附加了简单的代码,通过它可以动态地比较任何表的任何两个记录的表名和id值,以获得数据的差异。
myList