PL/SQL新手:SELECT和SYSDATE的函数

0 sql oracle plsql

我是SQL的新手,希望能帮助我们将其变成一个函数:

SELECT 
SYSDATE "Today's Date",
NEXT_DAY(trunc(SYSDATE, 'MONTH')-1, 'Tuesday')"First Tuesday this Month",
NEXT_DAY (LAST_DAY(SYSDATE)+1,'TUESDAY') "First Tuesday of Next Month"
FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

这是我尝试将上述内容转换为函数(因为你可以看到它没有那么热)...

CREATE OR REPLACE FUNCTION first_tuesday
RETURN DATE
AS
  date1 DATE;
  date2 DATE;
  date3 DATE;

BEGIN

  date1 := SELECT SYSDATE;
  date2 := SELECT NEXT_DAY(trunc(SYSDATE, 'MONTH')-1, 'Tuesday');
  date3 := SELECT NEXT_DAY (LAST_DAY(SYSDATE)+1,'TUESDAY');

RETURN 'todays date:' || date1, 
'first tuesday this month:' || date2,
'first tuesday next month:' || date3;

END;
/
SELECT first_tuesday FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Dav*_*dge 6

你真的想在那里返回三个值.我建议将其分解为单独的函数,但将"今天的日期"保留为对sysdate的调用.

您不需要发出SELECT查询来填充变量,在这种情况下,您只需返回一个表达式.

CREATE OR REPLACE FUNCTION first_tuesday
  RETURN DATE
AS
BEGIN
  RETURN NEXT_DAY(trunc(SYSDATE, 'MONTH')-1, 'Tuesday')
END;
/
Run Code Online (Sandbox Code Playgroud)

这里需要注意的是,在执行SQL语句时,SYSDATE始终具有相同的值,但PL/SQL中的情况并非如此.因此,当在从SQL语句调用的PL/SQL中计算sysdate时,您可以在每个上下文中获得不同的值.所以如果你打电话:

select sysdate col1,
       some_function col2
from dual;
Run Code Online (Sandbox Code Playgroud)

...在执行冗长的过程中,some_function会计算sysdate,它可能会使用与父SQL语句略有不同(稍后)的值.

避免这种情况的方法是将sysdate传递给函数:

CREATE OR REPLACE FUNCTION first_tuesday (sysdate_in date)
  RETURN DATE
AS
BEGIN
  RETURN NEXT_DAY(trunc(sysdate_in, 'MONTH')-1, 'Tuesday')
END;
/
Run Code Online (Sandbox Code Playgroud)

那么你可能......

Select ...
From   invoices
Where  invoice_date < first_tuesday(sysdate)
Run Code Online (Sandbox Code Playgroud)

这是一个简单的例子,只是为了演示原理,它实际上只对从SQL调用的函数很重要.

说实话,在你的情况下,大多数从业者可能会跳过这个功能而且只是:

Select ...
From   invoices
Where  invoice_date < NEXT_DAY(trunc(sysdate, 'MONTH')-1, 'Tuesday')
Run Code Online (Sandbox Code Playgroud)

编辑:顺便说一句,您可能想要使用:

NEXT_DAY (LAST_DAY(SYSDATE),'TUESDAY')
Run Code Online (Sandbox Code Playgroud)

......不......

NEXT_DAY (LAST_DAY(SYSDATE)+1,'TUESDAY')
Run Code Online (Sandbox Code Playgroud)