How could you create six unique random numbers between 1 and 49 with one SQL statement?
We would generate the set of numbers to pick from (see the innermost query that follows); any table with 49 or more records would do it. First the quick-and-dirty solution without a pipelined function.
select r
from (select r
from (select rownum r
from all_objects
where rownum < 50)
order by dbms_random.value)
where rownum <= 6;
R
----------
10
2
19
34
12
21
That query works by generating the numbers 1 .. 49, using the inline view. We wrap that innermost query as an inline view and sort it by a random value, using DBMS_RANDOM.VALUE. We wrap that result set in yet another inline view and just take the first six rows. If we run that query over and over, we'll get a different set of six rows each time.
This sort of question comes up frequently—maybe not about how to generate a set of six random numbers but rather, "how can we get N rows?" For example, we'd like the inclusive set of all dates between 25-FEB-2004 and 10-MAR-2004. The question becomes how to do this without a "real" table, and the answer lies in Oracle9i/10g with its PIPELINED functioncapability. We can write a PL/SQL function that will operate like a table. We need to start with a SQL collection type; this describes what the PIPELINED function will return. In this case, we are choosing a table of numbers; the virtual table we are creating will simply return the numbers 1, 2, 3, ... N:
create type array
as table of number
/
Type created.
Next, we create the actual PIPELINED function. This function will accept an input to limit the number of rows returned. If no input is provided, this function will just keep generating rows for a very long time (so be careful and make sure to use ROWNUM or some other limit in the query itself!). The PIPELINED keyword on line 4 allows this function to work as if it were a table:
create function
gen_numbers(n in number default null)
return array
PIPELINED
as
begin
for i in 1 .. nvl(n,999999999)
loop
pipe row(i);
end loop;
return;
end;
/
Function created.
Suppose we needed three rows for something. We can now do that in one of two ways:
select * from TABLE(gen_numbers(3));
COLUMN_VALUE
------------
1
2
3
or
select * from TABLE(gen_numbers)
where rownum <= 3;
COLUMN_VALUE
------------
1
2
3
Now we are ready to re-answer the original question, using the following functionality:
select *
from (
select *
from (select * from table(gen_numbers(49)))
order by dbms_random.random
)
where rownum <= 6
/
COLUMN_VALUE
------------
47
42
40
15
48
23
We can use this virtual table functionality for many things, such as generating that range of dates:
select to_date('25-feb-2004')+
column_value-1
from TABLE(gen_numbers(15))
/
TO_DATE('
---------
25-FEB-04
26-FEB-04
27-FEB-04
28-FEB-04
29-FEB-04
01-MAR-04
02-MAR-04
03-MAR-04
04-MAR-04
05-MAR-04
06-MAR-04
07-MAR-04
08-MAR-04
09-MAR-04
10-MAR-04
Note the name of the column we used: COLUMN_VALUE. That is the default name for the column coming back from the PIPELINED function.
This are the typical steps to perform when using PL/SQL Table Functions:
- The producer function must use the PIPELINED keyword in its declaration.
- The producer function must use an OUT parameter that is a record, corresponding to a row in the result set.
- Once each output record is completed, it is sent to the consumer function through the use of the PIPE ROW keyword.
- The producer function must end with a RETURN statement that does not specify any return value.
- The consumer function or SQL statement then must use the TABLE keyword to treat the resulting rows from the PIPELINE function like a regular table.
The first step is to define the format of the rows that are going to be returned. In this case here, we're going to return a INT, DATE followed by a VARCHAR2(25).
CREATE OR REPLACE TYPE myObjectFormat
AS OBJECT
(
A INT,
B DATE,
C VARCHAR2(25)
)
/
Next a collection type for the type previously defined must be created.
CREATE OR REPLACE TYPE myTableType
AS TABLE OF myObjectFormat
/
Finally, the producer function is packaged in a package. It is a pipelined function as indicated by the keyword pipelined.
CREATE OR REPLACE PACKAGE myDemoPack
AS
FUNCTION prodFunc RETURN myTableType PIPELINED;
END;
/
CREATE OR REPLACE PACKAGE BODY myDemoPack AS
FUNCTION prodFunc RETURN myTableType PIPELINED IS
BEGIN
FOR i in 1 .. 5
LOOP
PIPE ROW (myObjectFormat(i,SYSDATE+i,'Row '||i));
END LOOP;
RETURN;
END;
END;
/
Test It:
ALTER SESSION SET NLS_DATE_FORMAT='dd.mm.yyyy';
SELECT * FROM TABLE(myDemoPack.prodFunc());
A B C
---------- ---------- ---------
1 31.05.2004 Row 1
2 01.06.2004 Row 2
3 02.06.2004 Row 3
4 03.06.2004 Row 4
5 04.06.2004 Row 5
相关推荐
高通QCOM camera Pipeline可视化工具 1.4版本
pipeline engineering
方便gltf-pipeline相关人员下载使用
构建机器学习Pipeline,Architecting a Machine Learning Pipeline 。
赛诺菲 Pipeline.pdf
强生 Pipeline.pdf
This book describes the Direct3D graphics pipeline, from presentation of scene data to pixels appearing on the screen. The book is organized sequentially following the data °ow through the pipeline ...
pipeline ADC的设计指南
Hosted Community Edition - Try It Now! ...Email: help@pipeline.ai Web: https://support.pipeline.ai YouTube: https://youtube.pipeline.ai Slideshare: https://slideshare.pipeline.ai Work
pipeline studio快速入门,确实容易上手
默克 Pipeline.pdf
digital high speed pipeline ADC
主要介绍了Jenkins Pipeline 部署 SpringBoot 应用的详细教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
ASP.NET MVC Pipeline
Qsys系统中会使用互联结构,这篇文档是介绍如何使用Avalon-MM Pipeline Bridge
keepalive、pipeline。 一个包里包含了2个请求的请求响应包。 服务端用的是Nginx 1.9.12。
艾伯维 Pipeline.pdf
阿斯利康 Pipeline.pdf
武田 Pipeline 2.pdf
pipeline.pdf