选择查询完全可以在包过程之外工作,但是在过程中它会抛出'ORA-01858:在需要数字的地方找到一个非数字字符‘错误。
以下是我的疑问:
DECLARE
v_general_number VARCHAR(11);
BEGIN
SELECT 'Q' || TO_CHAR(TO_DATE(SYSDATE, 'MM/DD/YYYY'), 'Q') || '/' || LPAD(TO_CHAR(SEQ_EDP_GENERAL_NUM_ID.NEXTVAL), '3', '0') || '/' || TO_CHAR(EXTRACT(YEAR FROM TO_DATE(SYSDATE, 'MM/DD/YYYY'))) INTO v_general_number FROM DUAL;
DBMS_OUTPUT.PUT_LINE(v_general_number);
END;
而且效果很好。
但是在存储过程中,它会抛出上面的错误。
这是我的程序:
PROCEDURE save_request(p_name IN requests.suggested_name%TYPE,
p_urgency_type IN requests.urgency_type_id%TYPE)
AS
v_general_number VARCHAR(11);
BEGIN
SELECT 'Q' || TO_CHAR(TO_DATE(SYSDATE, 'MM/DD/YYYY'), 'Q') || '/' || LPAD(SEQ_EDP_GENERAL_NUM_ID.NEXTVAL, 3, '0') || '/' || TO_CHAR(EXTRACT(YEAR FROM TO_DATE(SYSDATE, 'MM/DD/YYYY'))) INTO v_general_number FROM DUAL;
INSERT INTO requests (suggested_name,
urgency_type_id,
general_number
) VALUES (
p_name ,
p_urgency_type ,
v_general_number );
END save_request;
我看不出是什么问题。如有任何建议,将不胜感激。
更新:
在改变这个问题之后,我解决了这个问题:
SELECT 'Q' || TO_CHAR(TO_DATE(SYSDATE, 'MM/DD/YYYY'), 'Q') || '/' || LPAD(SEQ_EDP_GENERAL_NUM_ID.NEXTVAL, 3, '0') || '/' || TO_CHAR(EXTRACT(YEAR FROM TO_DATE(SYSDATE, 'MM/DD/YYYY'))) INTO v_general_number FROM DUAL;
对此:
SELECT 'Q' || TO_CHAR(SYSDATE, 'Q') || '/' || LPAD(SEQ_EDP_GENERAL_NUM_ID.NEXTVAL, 3, '0') || '/' || TO_CHAR(EXTRACT(YEAR FROM SYSDATE)) INTO v_general_number FROM DUAL;
而且起作用了。
但是,我仍然不明白为什么相同的查询在过程之外工作,但在过程中抛出错误。
发布于 2018-07-04 06:03:14
SYSDATE
已经是个约会了,所以
TO_DATE(SYSDATE, 'MM/DD/YYYY')
根本没什么意义。您正在执行对字符串的隐式转换,然后将显式转换为日期,即:
TO_DATE(TO_CHAR(SYSDATE, <NLS_DATE_FORMAT>), 'MM/DD/YYYY')
它是否工作取决于会话的NLS_DATE_FORMAT设置:
alter session set nls_date_format = 'MM/DD/YYYY';
select TO_DATE(SYSDATE, 'MM/DD/YYYY') from dual;
TO_DATE(SY
----------
07/04/2018
select TO_CHAR(TO_DATE(SYSDATE, 'MM/DD/YYYY'), 'YYYY-MM-DD') from dual;
TO_CHAR(TO
----------
2018-07-04
alter session set nls_date_format = 'DD/MM/YYYY';
select TO_DATE(SYSDATE, 'MM/DD/YYYY') from dual;
TO_DATE(SY
----------
07/04/2018
select TO_CHAR(TO_DATE(SYSDATE, 'MM/DD/YYYY'), 'YYYY-MM-DD') from dual;
TO_CHAR(TO
----------
2018-04-07
alter session set nls_date_format = 'DD-MON-YYYY';
select TO_DATE(SYSDATE, 'MM/DD/YYYY') from dual;
ORA-01858: a non-numeric character was found where a numeric was expected
alter session set nls_date_format = 'YYYY-MM-DD';
select TO_DATE(SYSDATE, 'MM/DD/YYYY') from dual;
ORA-01843: not a valid month
注意前两个都是“工作”,但实际上给出了不同的日期。(在这个月的晚些时候,在第12号之后,第二个也会失败,一个无效的月份错误。)
运行匿名块的会话和执行过程的会话具有不同的NLS设置。这就是为什么不应该依赖于隐式转换或NLS设置.
无论如何,删除不必要的转换:
SELECT 'Q' || TO_CHAR(SYSDATE, 'Q')
|| '/' || LPAD(TO_CHAR(SEQ_EDP_GENERAL_NUM_ID.NEXTVAL), '3', '0')
|| '/' || TO_CHAR(EXTRACT(YEAR FROM SYSDATE))
INTO v_general_number
FROM DUAL;
或者做同样的任务,而不是从双重任务中选择:
v_general_number := 'Q' || TO_CHAR(SYSDATE, 'Q')
|| '/' || LPAD(TO_CHAR(SEQ_EDP_GENERAL_NUM_ID.NEXTVAL), '3', '0')
|| '/' || TO_CHAR(EXTRACT(YEAR FROM SYSDATE));
甚至,作为一种选择:
v_general_number := TO_CHAR(SYSDATE, '"Q"Q"/"')
|| TO_CHAR(SEQ_EDP_GENERAL_NUM_ID.NEXTVAL, 'FM000')
|| TO_CHAR(SYSDATE, '"/"YYYY');
它使用日期格式模型中的字符值来复制斜杠的级联,以及序列号的格式模型,这样您就不需要将其填充为零。(您不需要一个变量,您可以在insert的values
子句中执行相同的构造。)
https://stackoverflow.com/questions/51175278
复制相似问题