惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
V
V2EX
博客园_首页
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
H
Help Net Security
A
About on SuperTechFans
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Blog — PlanetScale
Blog — PlanetScale
W
WeLiveSecurity
云风的 BLOG
云风的 BLOG
D
Docker
Security Archives - TechRepublic
Security Archives - TechRepublic
Help Net Security
Help Net Security
N
News and Events Feed by Topic
Simon Willison's Weblog
Simon Willison's Weblog
G
Google Developers Blog
A
Arctic Wolf
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
博客园 - 三生石上(FineUI控件)
aimingoo的专栏
aimingoo的专栏
Hacker News: Ask HN
Hacker News: Ask HN
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 司徒正美
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
T
Troy Hunt's Blog
T
Tenable Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recorded Future
Recorded Future
F
Fortinet All Blogs
D
DataBreaches.Net
B
Blog
T
Threat Research - Cisco Blogs
MyScale Blog
MyScale Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
The GitHub Blog
The GitHub Blog
Security Latest
Security Latest
M
MIT News - Artificial intelligence

博客园 - wzc998

Oracle Audit 关于"cannot perform a DDL, commit or rollback inside a query or DML" 错误 关于varchar2在pl/sql和schema级别的最大值 ORA-01031 权限不足错误的解决 通过代码备份存储过程,package body 和表数据 并还原 XSL ASP .net实现松耦合事件的三种方法 Log4net不同版本在app.config和web.config的配置区别 SQL*Loader FAQ 【转】NLS 视图的研究 oracle多语言环境下to_date时间转换问题 【转】如何使用 ADO.NET 和 Visual C# .NET 调用带参数的存储过程 【转】SQL SERVER 存储过程学习笔记 【转】代码复用原则:合理使用类组合和类继承 委托与接口的关系 IOC 【转】范式 【转】oracle范式与交叉表
oracle存储过程返回交叉表(使用存储过程/高级语言调用)
wzc998 · 2010-08-24 · via 博客园 - wzc998

定义:由左边、上边两个标头和右下角交叉数据构成的表我们称之为“交叉表”。

列数:列数固定的交叉表可以使用视图直接返回表数据,在此不讨论。本文演示列数不固定的交叉表数据的返回。

1,创建存储:

create or replace procedure test(p_cursor out SYS_REFCURSOR) is
  sqlstr varchar2(32767);
begin
  sqlstr := 'select i06_feebill_id,';
  for v_cur in (select distinct i06_feebill_id
                  from t_i06_billdetail
                 where i06_feebill_id in
                       ('F200F79AA4D94367A9003139737AB3D5',
                        'F200F79A30DA45379CCFB49FC3E9857A')) loop
    sqlstr := sqlstr || 'sum(decode(i06_feebill_id' ||
              ', '''||v_cur.i06_feebill_id||''', '||
              'i06_fee_amount, 0)) a' || substr(v_cur.i06_feebill_id,0,10) || ',';
  end loop;

  sqlstr := substr(sqlstr, 0, length(sqlstr) - 1);
  sqlstr := sqlstr ||
            ' from t_i06_billdetail t  where t.i06_feebill_id in (''F200F79AA4D94367A9003139737AB3D5'',''F200F79A30DA45379CCFB49FC3E9857A'') group by i06_feebill_id';
          
  open p_cursor for sqlstr;
end;
2,测试(使用存储过程调用),缺点是列数不固定时无法实现调用。因为接收参数没法定义。

-- Created on 2010-08-24 by ADMINISTRATOR
declare
  -- Local variables here
  i         integer;
  tmpCURSOR SYS_REFCURSOR;
  bill      t_i06_billdetail.i06_billdetail_id%TYPE;
  amount    t_i06_billdetail.i06_fee_amount%TYPE;
  amount2   t_i06_billdetail.i06_fee_amount%TYPE;
begin
  -- Test statements here

  test(tmpCURSOR);

  loop
    fetch tmpCURSOR
      into bill, amount, amount2;
    exit when tmpCURSOR%notfound;
    DBMS_OUTPUT.PUT_LINE(bill);
    DBMS_OUTPUT.PUT_LINE(amount);
    DBMS_OUTPUT.PUT_LINE(amount2);
  end loop;
end;

3,测试(使用高级语言调用【C#】),通过绑定可以实现接收列数不固定的数据。

// GetConnectionString() returns a connection string for
// the data source.

string connString = GetConnectionString();
DataSet ds = new DataSet();
OracleConnection conn = new OracleConnection(connString);
OracleCommand cmd = conn.CreateCommand();

cmd.CommandText = "test";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("p_cursor", OracleType.Cursor).Direction =
       ParameterDirection.Output;

OracleDataAdapter da = new OracleDataAdapter(cmd);
da.TableMappings.Add("Table", "Emp");

da.Fill(ds);

4,需要注意返回游标分为两种情况:

a,返回的游标是某个具体的表或视图的数据,调用的时候只要声明一个该表的ROWTYPE类型就可以了,如 R t_i06_billdetail
%ROWTYPE;

CREATE OR REPLACE PROCEDURE P_TESTA (
PRESULT OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN PRESULT FOR SELECT * FROM USERS;
END P_TESTA;

CREATE OR REPLACE PROCEDURE P_TESTB
AS
VARCURSOR SYS_REFCURSOR;
R USERS%ROWTYPE;
BEGIN
P_TESTA(VARCURSOR);
LOOP
FETCH VARCURSOR INTO R;
EXIT WHEN VARCURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(R.NAME);
END LOOP;
END P_TESTB;

b,第二种情况,我们返回的不是表的所有的列,或许只是其中一列或两列。

CREATE OR REPLACE PROCEDURE P_TESTA (
PRESULT OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN PRESULT FOR SELECT ID,NAME FROM USERS;
END P_TESTA;
CREATE OR REPLACE PROCEDURE P_TESTB
AS
VARCURSOR SYS_REFCURSOR;
CURSOR TMPCURSOR IS SELECT ID,NAME FROM USERS WHERE ROWNUM=1;
R TMPCURSOR%ROWTYPE;
BEGIN
P_TESTA(VARCURSOR);
LOOP
FETCH VARCURSOR INTO R;
EXIT WHEN VARCURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(R.ID);
END LOOP;
END P_TESTB;
与之前不同的是我们声明了一个游标类型的变量TMPCURSOR ,注意TMPCURSOR 的结构必须与存储过程P_TESTA 返回的游标结构一致,否则就会出现错误。同理只要保持两个游标类型结构一致,就可以实现自由调用。