gpt4 book ai didi

sql - 查询中的 Oracle 和 SQLServer 函数评估

转载 作者:行者123 更新时间:2023-12-02 22:16:39 26 4
gpt4 key购买 nike

假设我在 Oracle 中的 selectwhere 子句上有一个函数调用,如下所示:

select a, b, c, dbms_crypto.hash(utl_raw.cast_to_raw('HELLO'),3)
from my_table

可以为 MS SQLServer 构建类似的示例。

每种情况下的预期行为是什么?

HASH 函数是否会为表中的每一行调用一次,或者 DBMS 会足够聪明,只调用该函数一次,因为它是一个具有常量参数且没有 副作用

非常感谢。

最佳答案

Oracle 的答案是视情况而定。将为所选的每一行调用该函数,除非该函数被标记为“确定性”,在这种情况下,该函数只会被调用一次。

CREATE OR REPLACE PACKAGE TestCallCount AS
FUNCTION StringLen(SrcStr VARCHAR) RETURN INTEGER;
FUNCTION StringLen2(SrcStr VARCHAR) RETURN INTEGER DETERMINISTIC;
FUNCTION GetCallCount RETURN INTEGER;
FUNCTION GetCallCount2 RETURN INTEGER;
END TestCallCount;

CREATE OR REPLACE PACKAGE BODY TestCallCount AS
TotalFunctionCalls INTEGER := 0;
TotalFunctionCalls2 INTEGER := 0;

FUNCTION StringLen(SrcStr VARCHAR) RETURN INTEGER AS
BEGIN
TotalFunctionCalls := TotalFunctionCalls + 1;
RETURN Length(SrcStr);
END;
FUNCTION GetCallCount RETURN INTEGER AS
BEGIN
RETURN TotalFunctionCalls;
END;

FUNCTION StringLen2(SrcStr VARCHAR) RETURN INTEGER DETERMINISTIC AS
BEGIN
TotalFunctionCalls2 := TotalFunctionCalls2 + 1;
RETURN Length(SrcStr);
END;
FUNCTION GetCallCount2 RETURN INTEGER AS
BEGIN
RETURN TotalFunctionCalls2;
END;

END TestCallCount;




SELECT a,TestCallCount.StringLen('foo') FROM(
SELECT 0 as a FROM dual
UNION
SELECT 1 as a FROM dual
UNION
SELECT 2 as a FROM dual
);

SELECT TestCallCount.GetCallCount() AS TotalFunctionCalls FROM dual;

输出:

A                      TESTCALLCOUNT.STRINGLEN('FOO') 
---------------------- ------------------------------
0 3
1 3
2 3

3 rows selected


TOTALFUNCTIONCALLS
----------------------
3

1 rows selected

因此在第一种情况下 StringLen() 函数被调用了 3 次。现在,当使用 StringLen2() 执行时,这表示确定性:

SELECT a,TestCallCount.StringLen2('foo') from(
select 0 as a from dual
union
select 1 as a from dual
union
select 2 as a from dual
);

SELECT TestCallCount.GetCallCount2() AS TotalFunctionCalls FROM dual;

结果:

A                      TESTCALLCOUNT.STRINGLEN2('FOO') 
---------------------- -------------------------------
0 3
1 3
2 3

3 rows selected

TOTALFUNCTIONCALLS
----------------------
1

1 rows selected

因此 StringLen2() 函数仅被调用一次,因为它被标记为确定性的。

对于未标记为确定性的函数,您可以通过修改查询来解决此问题:

select a, b, c, hashed
from my_table
cross join (
select dbms_crypto.hash(utl_raw.cast_to_raw('HELLO'),3) as hashed from dual
);

关于sql - 查询中的 Oracle 和 SQLServer 函数评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1008709/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com