如何从返回引用游标的 Oracle 过程中获得格式良好的结果?
在 MS SQL Server 中,如果我想检查存储过程的结果,我可以在 Management Studio 中执行以下命令。
--SQL SERVER WAY
exec sp_GetQuestions('OMG Ponies')
结果窗格中的输出可能如下所示。
ID Title ViewCount Votes
----- ------------------------------------------------- ---------- --------
2165 Indexed View vs Indexes on Table 491 2
5068 SQL Server equivalent to Oracle’s NULLS FIRST 524 3
1261 Benefits Of Using SQL Ordinal Position Notation? 377 2
(3 row(s) affected)
无需编写循环或 PRINT 语句。
要在 Oracle 中执行相同的操作,我可能会在 SQL Developer 中执行以下匿名块,
--ORACLE WAY
DECLARE
OUTPUT MYPACKAGE.refcur_question;
R_OUTPUT MYPACKAGE.r_question;
USER VARCHAR2(20);
BEGIN
dbms_output.enable(10000000);
USER:= 'OMG Ponies';
recordCount := 0;
MYPACKAGE.GETQUESTIONS(p_OUTPUT => OUTPUT,
p_USER=> USER,
) ;
DBMS_OUTPUT.PUT_LINE('ID | Title | ViewCount | Votes' );
LOOP
FETCH OUTPUT
INTO R_OUTPUT;
DBMS_OUTPUT.PUT_LINE(R_OUTPUT.QUESTIONID || '|' || R_OUTPUT.TITLE
'|' || R_OUTPUT.VIEWCOUNT '|' || R_OUTPUT.VOTES);
recordCount := recordCount+1;
EXIT WHEN OUTPUT % NOTFOUND;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Record Count:'||recordCount);
CLOSE OUTPUT;
END;
其输出类似于
ID|Title|ViewCount|Votes
2165|Indexed View vs Indexes on Table|491|2
5068|SQL Server equivalent to Oracle’s NULLS FIRST|524|3
1261|Benefits Of Using SQL Ordinal Position Notation?|377|2
Record Count: 3
“因此 SQL 版本有 1 行,而 Oracle 有 18 行”,并且输出很丑陋。如果有很多列和/或数据是数字,情况会更加严重。
对我来说奇怪的是,如果我在 SQL Developer 或 Management studio 中编写此语句...
SELECT
ID,
Title,
ViewCount,
Votes
FROM votes where user = 'OMG Ponies'
结果非常相似。这让我觉得我要么错过了一项技术,要么使用了错误的工具。
In MS SQL Server if I want to check the results from a Stored procedure I might execute the following in Management Studio.
--SQL SERVER WAY
exec sp_GetQuestions('OMG Ponies')
The output in the results pane might look like this.
ID Title ViewCount Votes
----- ------------------------------------------------- ---------- --------
2165 Indexed View vs Indexes on Table 491 2
5068 SQL Server equivalent to Oracle’s NULLS FIRST 524 3
1261 Benefits Of Using SQL Ordinal Position Notation? 377 2
(3 row(s) affected)
No need to write loops or PRINT statements.
To do the same thing in Oracle I might execute the following anonymous block in SQL Developer
--ORACLE WAY
DECLARE
OUTPUT MYPACKAGE.refcur_question;
R_OUTPUT MYPACKAGE.r_question;
USER VARCHAR2(20);
BEGIN
dbms_output.enable(10000000);
USER:= 'OMG Ponies';
recordCount := 0;
MYPACKAGE.GETQUESTIONS(p_OUTPUT => OUTPUT,
p_USER=> USER,
) ;
DBMS_OUTPUT.PUT_LINE('ID | Title | ViewCount | Votes' );
LOOP
FETCH OUTPUT
INTO R_OUTPUT;
DBMS_OUTPUT.PUT_LINE(R_OUTPUT.QUESTIONID || '|' || R_OUTPUT.TITLE
'|' || R_OUTPUT.VIEWCOUNT '|' || R_OUTPUT.VOTES);
recordCount := recordCount+1;
EXIT WHEN OUTPUT % NOTFOUND;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Record Count:'||recordCount);
CLOSE OUTPUT;
END;
This outputs like
ID|Title|ViewCount|Votes
2165|Indexed View vs Indexes on Table|491|2
5068|SQL Server equivalent to Oracle’s NULLS FIRST|524|3
1261|Benefits Of Using SQL Ordinal Position Notation?|377|2
Record Count: 3
So the SQL version has 1 line and the oracle has 18 and the output is ugly. Its exacerbated if there are a lot of columns and/or the data is numeric.
What's odd to me about this is that if I write this statement in either SQL Developer or Management studio...
SELECT
ID,
Title,
ViewCount,
Votes
FROM votes where user = 'OMG Ponies'
The results are fairly similar. This makes me feel like I'm either missing a technique or using the wrong tool.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果 GetQuestions 是一个返回引用游标的函数,这似乎是 SQL Server 版本中的函数,那么您可能可以执行如下操作:
或者如果您在 PL/ SQL 块然后您可以在游标中使用相同的选择。
您还可以让该函数生成
dbms_output
语句,以便它们始终可用于调试,尽管这会增加一点开销。编辑
嗯,不确定是否可以
cast()
返回的refcursor为可用类型,除非您愿意声明自己的类型(以及该类型的表) )在包装外。不过,您可以这样做,只是为了转储结果:并且您可以在另一个过程或函数中使用调用的结果;只是在 PL/SQL 之外实现它似乎有点棘手。
编辑添加:通过这种方法,如果它是一个过程,您基本上可以做同样的事情:
If
GetQuestions
is a function returning a refcursor, which seems to be what you have in the SQL Server version, then rather you may be able to do something like this:Or if you need it in a PL/SQL block then you can use the same select in a cursor.
You can also have the function produce the
dbms_output
statements instead so they're always available for debugging, although that adds a little overhead.Edit
Hmmm, not sure it's possible to
cast()
the returned refcursor to a usable type, unless you're willing to declare your own type (and a table of that type) outside the package. You can do this though, just to dump the results:And you can use the result of the call in another procedure or function; it's just getting to it outside PL/SQL that seems to be a little tricky.
Edited to add: With this approach, if it's a procedure you can do essentially the same thing:
SQL Developer 自动捕获运行存储过程的输出。直接从我们的过程编辑器运行存储过程,您可以在我的文章中详细了解此行为
SQL 开发人员提示:查看 REFCURSOR 输出
现在,如果您想将 refcursor 作为 SQL 工作表中 anon 块的一部分运行,您可以执行与此类似的操作
--其中 GET_EMPS() 将是您的 sp_GetQuestions('OMG Ponies') 调用。 PRINT 命令发送通过存储过程运行的“查询”的输出,如下所示:
现在,您说的是 10g。如果您使用的是 12c,我们已增强了 PL/SQL 引擎以支持隐式游标结果。因此,这变得更容易一些,不再需要设置光标,您只需调用即可获取数据,如此处记录的:
http://docs.oracle.com/database/121/DRDAA/migr_tools_feat .htm#DRDAA230
SQL Developer automatically catches the output from running your stored procedures. Running the stored procedure directly from our procedure editor, you can see this behavior detailed in my post here
SQL Developer Tip: Viewing REFCURSOR Output
Now, if you want to run the refcursor as part of an anon block in our SQL Worksheet, you could do something similar to this
--where GET_EMPS() would be your sp_GetQuestions('OMG Ponies') call. The PRINT command sends the output from the 'query' which is ran via the stored procedure, and looks like this:
Now, you said 10g. If you're in 12c, we have enhanced the PL/SQL engine to support implicit cursor results. So this gets a bit easier, no more setting up the cursor, you just make a call to get the data, as documented here:
http://docs.oracle.com/database/121/DRDAA/migr_tools_feat.htm#DRDAA230