Trying to do a simple User function where I get the number of people whos age is > 100.
试着做一个简单的用户函数,我得到了年龄>100的人的数量。
this is my current table
这是我现在的桌子
select * from peoples
SELECT*From People
**NAME** **AGE**
----------------------
Joe Bloggs 12
Paul Smith 15
Jonah James 534
Mika Rive 31
Hannah Bananas 56
Harry Heelz 4
Brian Bolton 232
Jack Ripper 123
I'm currently trying to implement user function where the output is a single row with the total number of people with an age greater than 100.
我目前正在尝试实现用户函数,其中输出是年龄大于100岁的总人数的单行。
Here is the function I have attempted to make
以下是我尝试创建的函数
create or replace function agetest return number is
v_count number;
begin
select count(age) into v_count
from persons
where age > 100;
return v_count;
end;
When I execute the SQL query directly I get the correct answer
当我直接执行SQL查询时,我会得到正确的答案
select count(age) from persons where age > 100;
but when I run the function
但当我运行该函数时
select agetest from persons;
I get the output of:
我得到以下输出:
|
AGETEST |
1 |
3 |
2 |
3 |
3 |
3 |
4 |
3 |
5 |
3 |
6 |
3 |
7 |
3 |
8 |
3 |
Just looking for guidance on why the output is showing the same result for each row.
我只是想了解一下为什么输出每一行都显示相同的结果。
My ideal output for the function would just be:
我对该函数的理想输出是:
更多回答
Since you don't use a WHERE
clause in your query, the result will be build for each row in your table. The fact you use a function doesn't matter because the query doesn't know what your function will do. Why do you want to use a function at all? This seems absolutely wrong to me. Just write a query and the job is done. If you want to use the function, try to select from the dual
table rather than the persons
table.
由于您没有在查询中使用WHERE子句,因此将为表中的每一行构建结果。您使用函数的事实并不重要,因为查询不知道您的函数将做什么。你到底为什么要使用一个函数呢?在我看来,这绝对是错误的。只需编写一个查询,工作就完成了。如果要使用该函数,请尝试从DUAL表而不是PERSONERS表中进行选择。
This is more of a build up to a larger question I have for school and I'm just trying to get the fundamentals down first.
这更多的是为我在学校有一个更大的问题做准备,我只是想先把基础弄清楚。
Well, one of the most fundamentals things in my opinion is to prefer pure queries over functions or procedures. I often see people use them although not necessary. I think this makes things unnecessary complex because we don't directly see the query, but just the function or procedure call and need to check what is executed there. So I recommend to avoid functions and procedures if possible. But ok, that's just my point of view. Maybe I'm wrong.
在我看来,最基本的事情之一是更喜欢纯查询而不是函数或过程。我经常看到人们使用它们,尽管不是必要的。我认为这使事情变得不必要地复杂,因为我们不能直接看到查询,而只看到函数或过程调用,并且需要检查在那里执行了什么。因此,我建议尽可能避免使用函数和过程。但好吧,这只是我的观点。也许我错了。
When you execute the query:
执行查询时:
select count(age) from persons where age > 100;
You aggregate all the rows into a single row.
您将所有行聚合到一行中。
When you do:
当您这样做时:
select agetest from persons;
You are not executing the first query because agetest
is a scalar function (not an aggregation function) and you are effective executing:
您没有执行第一个查询,因为agetest是一个标量函数(不是聚合函数),并且您正在有效地执行:
SELECT (select count(age) from persons where age > 100) FROM persons;
Which is saying, for each row in persons
execute the sub-query; which is why you get the function's return value repeated for each person and the output is:
这就是说,对于Person中的每一行,执行子查询;这就是为什么您会获得针对每个Person重复的函数返回值,并且输出是:
(SELECTCOUNT(AGE)FROMPERSONSWHEREAGE>100) |
3 |
3 |
3 |
3 |
3 |
3 |
3 |
3 |
If you want to get the function value once then only execute it once by using a table that only has one row (such as DUAL
):
如果要获取一次函数值,则使用只有一行的表(如DUAL)只执行一次:
SELECT agetest FROM dual;
Or, you can change the function from a scalar function to a user-defined aggregation function:
或者,您可以将函数从标量函数更改为用户定义的聚合函数:
CREATE OR REPLACE TYPE CountGreaterThan100Type AS OBJECT(
cnt NUMBER(10,0),
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT CountGreaterThan100Type,
value IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT CountGreaterThan100Type,
returnValue OUT NUMBER,
flags IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT CountGreaterThan100Type,
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY CountGreaterThan100Type
IS
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER
IS
BEGIN
ctx := CountGreaterThan100Type( 0 );
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT CountGreaterThan100Type,
value IN NUMBER
) RETURN NUMBER
IS
BEGIN
IF value > 100 THEN
self.cnt := self.cnt + 1;
END IF;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT CountGreaterThan100Type,
returnValue OUT NUMBER,
flags IN NUMBER
) RETURN NUMBER
IS
BEGIN
returnValue := self.cnt;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT CountGreaterThan100Type,
ctx IN OUT CountGreaterThan100Type
) RETURN NUMBER
IS
BEGIN
self.cnt := self.cnt + ctx.cnt;
RETURN ODCIConst.SUCCESS;
END;
END;
/
CREATE FUNCTION CountGreaterThan100( value NUMBER )
RETURN NUMBER
PARALLEL_ENABLE AGGREGATE USING CountGreaterThan100Type;
/
Then:
然后:
SELECT CountGreaterThan100(age) FROM persons;
Outputs:
产出:
COUNTGREATERTHAN100(AGE) |
3 |
fiddle
小提琴
Try executing the function against DUAL
:
尝试针对DUAL执行函数:
SELECT agetest FROM dual;
In Oracle, the DUAL
table is a sort of dummy table which has only one record in it.
在Oracle中,DUAL表是一种只有一条记录的虚表。
更多回答
This seems to have worked! Thank you :)
这似乎奏效了!谢谢:)
Nice side note: In Oracle 23c, we don't need to use the dual
table anymore. We can just write SELECT xy
without any FROM
clause. As we can in any other RDBMS. This dual
table is some very strange Oracle-thing and will become obsolete.
备注:在Oracle23c中,我们不再需要使用DUAL表。我们可以只编写SELECT XY,而不使用任何FROM子句。就像我们在任何其他RDBMS中一样。这种双重表是一些非常奇怪的甲骨文东西,将会过时。
What I talk about is that we can write queries like SELECT 1
without using a table or a FROM
clause in common RDBMS. And now (or in future) we can also do it in Oracle and don't need the dual
table.
我所说的是,我们可以编写像SELECT 1这样的查询,而不需要在普通的RDBMS中使用表或FROM子句。现在(或将来),我们也可以在Oracle中执行此操作,而不需要DUAL表。
@JonasMetzler, oops. I misread. My bad.
@JonasMetzler,哎呀。我看错了。我的错。
我是一名优秀的程序员,十分优秀!