从 Oracle PL/SQL 匿名块填充 C# DataTable
Fill C# DataTable from Oracle PL/SQL Anonymous Block
我正在尝试执行 return 游标的结果到我的 C# 程序。下面是我的代码:
OracleCommand cmd = new OracleCommand();
cmd.CommandText = @"
declare
varEmpID myTable.emp_id%type;
varSupID myTable.supervisor_id%type;
varNewSupID myTable.supervisor_id%type;
varSupActive myTable.active_ind%type;
Cursor C1 is(
select emp_id,active_ind,supervisor_id
from myTable where emp_id in
('1','2')) order by emp_id;
begin
Open C1;
LOOP
FETCH C1 INTO varEmpID,varSupActive,varSupID;
EXIT WHEN C1%NOTFOUND;
while (varSupActive<>'Y') loop
select m1.supervisor_id, m2.Active_Ind
into varNewSupID,varSupActive
from myTable m1, myTable m2
where m1.supervisor_id = m2.emp_id and m1.emp_id = varSupID;
varSupID := varNewSupID;
end loop;
open :rc1 for select sup.emp_id, sup.FIRST_NAME,sup.LAST_NAME
into varEmpID,varFirstName,varLastName
from myTable sup
where emp_id = varSupID;
END LOOP;
CLOSE C1;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
";
cmd.BindByName = true;
cmd.Parameters.Add("rc1", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
using (cmd.Connection = new OracleConnection(strCon))
{
cmd.Connection.Open();
var reader = cmd.ExecuteReader();
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
}
游标的目的是为一组给定的用户找到活跃的主管。如果我 table 中的用户主管不活跃,我需要在层次结构中向上移动,直到找到活跃的主管。还有一些我在这里删除的条件,但我想说的是,我认为这不能使用单个 SQL 语句来实现。
很明显,我没有让所有新主管都使用 rc1 游标,因为它在循环中并且被覆盖了。所以我的 C# 输出只给我最后一位主管。我尝试创建 table 类型的数组,但即使这样我也必须在 for 循环中使用索引进行访问。
我只有对数据库的读取权限,所以我不能创建函数、过程等。有没有办法可以将新主管数据写入该程序范围内的临时 table的变量,这样我就可以在循环后从那个温度table做一个select *。或者我可以通过任何其他方式获得我需要的东西。谢谢!
我认为您可以使用这样的分层查询代替 PLSQL 块:
select emp_id supervisor_id, last_name, root emp_id
from (
select t.*,
min(case when active_ind = 'Y' and root <> emp_id
then lvl end) over (partition by root) mlvl
from (
select m.*, level lvl,
connect_by_root(emp_id) root
from mytable m
connect by emp_id = prior supervisor_id
start with emp_id in (1, 2) ) t )
where lvl = mlvl
子查询t
创建主管的树。 Next with function min()
我正在搜索这个级别最低(最接近员工)并且活跃的人。
测试数据:
create table myTable (emp_id number(3), active_ind varchar2(1),
last_name varchar(10), supervisor_id number(3));
insert into mytable values (1, 'Y', 'Brown', 3);
insert into mytable values (2, 'Y', 'Smith', 4);
insert into mytable values (3, 'Y', 'Adams', 6);
insert into mytable values (4, 'N', 'Novak', 5);
insert into mytable values (5, 'Y', 'King', null);
insert into mytable values (6, 'Y', 'Jones', null);
输出:
SUPERVISOR_ID LAST_NAME EMP_ID
------------- --------- ------
3 Adams 1
5 King 2
编辑:Oracle 11 和递归 CTE 版本:
with t (root, id, act, name, sid, stop) as (
select emp_id, emp_id, active_ind, last_name, supervisor_id, 0
from mytable where emp_id in (1, 2)
union all
select t.root, m.emp_id, m.active_ind, m.last_name, m.supervisor_id,
case when m.active_ind = 'Y' then 1 else 0 end
from t join mytable m on m.emp_id = t.sid and t.stop = 0
)
select * from t where stop = 1
如果出现 "cycle" 问题,请使用此处描述的 CYCLE id SET cycle TO 1 DEFAULT 0
之类的内容:Recursive Subquery Factoring
我正在尝试执行 return 游标的结果到我的 C# 程序。下面是我的代码:
OracleCommand cmd = new OracleCommand();
cmd.CommandText = @"
declare
varEmpID myTable.emp_id%type;
varSupID myTable.supervisor_id%type;
varNewSupID myTable.supervisor_id%type;
varSupActive myTable.active_ind%type;
Cursor C1 is(
select emp_id,active_ind,supervisor_id
from myTable where emp_id in
('1','2')) order by emp_id;
begin
Open C1;
LOOP
FETCH C1 INTO varEmpID,varSupActive,varSupID;
EXIT WHEN C1%NOTFOUND;
while (varSupActive<>'Y') loop
select m1.supervisor_id, m2.Active_Ind
into varNewSupID,varSupActive
from myTable m1, myTable m2
where m1.supervisor_id = m2.emp_id and m1.emp_id = varSupID;
varSupID := varNewSupID;
end loop;
open :rc1 for select sup.emp_id, sup.FIRST_NAME,sup.LAST_NAME
into varEmpID,varFirstName,varLastName
from myTable sup
where emp_id = varSupID;
END LOOP;
CLOSE C1;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
";
cmd.BindByName = true;
cmd.Parameters.Add("rc1", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
using (cmd.Connection = new OracleConnection(strCon))
{
cmd.Connection.Open();
var reader = cmd.ExecuteReader();
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
}
游标的目的是为一组给定的用户找到活跃的主管。如果我 table 中的用户主管不活跃,我需要在层次结构中向上移动,直到找到活跃的主管。还有一些我在这里删除的条件,但我想说的是,我认为这不能使用单个 SQL 语句来实现。
很明显,我没有让所有新主管都使用 rc1 游标,因为它在循环中并且被覆盖了。所以我的 C# 输出只给我最后一位主管。我尝试创建 table 类型的数组,但即使这样我也必须在 for 循环中使用索引进行访问。
我只有对数据库的读取权限,所以我不能创建函数、过程等。有没有办法可以将新主管数据写入该程序范围内的临时 table的变量,这样我就可以在循环后从那个温度table做一个select *。或者我可以通过任何其他方式获得我需要的东西。谢谢!
我认为您可以使用这样的分层查询代替 PLSQL 块:
select emp_id supervisor_id, last_name, root emp_id
from (
select t.*,
min(case when active_ind = 'Y' and root <> emp_id
then lvl end) over (partition by root) mlvl
from (
select m.*, level lvl,
connect_by_root(emp_id) root
from mytable m
connect by emp_id = prior supervisor_id
start with emp_id in (1, 2) ) t )
where lvl = mlvl
子查询t
创建主管的树。 Next with function min()
我正在搜索这个级别最低(最接近员工)并且活跃的人。
测试数据:
create table myTable (emp_id number(3), active_ind varchar2(1),
last_name varchar(10), supervisor_id number(3));
insert into mytable values (1, 'Y', 'Brown', 3);
insert into mytable values (2, 'Y', 'Smith', 4);
insert into mytable values (3, 'Y', 'Adams', 6);
insert into mytable values (4, 'N', 'Novak', 5);
insert into mytable values (5, 'Y', 'King', null);
insert into mytable values (6, 'Y', 'Jones', null);
输出:
SUPERVISOR_ID LAST_NAME EMP_ID
------------- --------- ------
3 Adams 1
5 King 2
编辑:Oracle 11 和递归 CTE 版本:
with t (root, id, act, name, sid, stop) as (
select emp_id, emp_id, active_ind, last_name, supervisor_id, 0
from mytable where emp_id in (1, 2)
union all
select t.root, m.emp_id, m.active_ind, m.last_name, m.supervisor_id,
case when m.active_ind = 'Y' then 1 else 0 end
from t join mytable m on m.emp_id = t.sid and t.stop = 0
)
select * from t where stop = 1
如果出现 "cycle" 问题,请使用此处描述的 CYCLE id SET cycle TO 1 DEFAULT 0
之类的内容:Recursive Subquery Factoring