使用 SQL / PL SQL 验证日期 [关闭]
Posted
技术标签:
【中文标题】使用 SQL / PL SQL 验证日期 [关闭]【英文标题】:Verify date with SQL / PL SQL [closed] 【发布时间】:2021-09-11 03:44:26 【问题描述】:我在验证代码中的日期时遇到问题。它并没有按应有的方式工作。
错误的部分与此有关。
ADD_COMPLEX_SALE_TO_DB - GENERATED UNEXPECTED EXCEPTION
ADD_COMPLEX_SALE_TO_DB - DATE NOT VALID EXCEPTION INCORRECT (WRONG MONTH)
ADD_COMPLEX_SALE_TO_DB - DATE NOT VALID EXCEPTION INCORRECT (WRONG DAY)
我的测试代码是这样的。我有一个不同的输出块,没有问题。
CREATE OR REPLACE PROCEDURE ADD_COMPLEX_SALE_TO_DB (pcustid Number, pprodid Number, pqty Number, pdate Varchar2) AS
QTY_OUTSIDE_RANGE EXCEPTION;
STATUS_NOT_OK EXCEPTION;
INVALID_SALE_DATE EXCEPTION;
vCUST CUSTOMER%ROWTYPE;
vPROD PRODUCT%ROWTYPE;
SALEID SALE%ROWTYPE;
vPROD_ERROR INT := 0;
BEGIN
IF 1 > pqty OR pqty > 999 THEN
RAISE QTY_OUTSIDE_RANGE;
END IF;
SELECT * INTO vCUST
FROM CUSTOMER
WHERE CUSTID = pcustid;
vPROD_ERROR := 1;
IF vCUST.STATUS != 'OK' THEN
RAISE STATUS_NOT_OK;
END IF;
SELECT * INTO vPROD
FROM PRODUCT
WHERE PRODID = pprodid;
IF (LENGTH(pdate) <> 8) THEN
RAISE INVALID_SALE_DATE;
END IF;
INSERT INTO SALE (SALEID, CUSTID, PRODID, QTY, PRICE, SALEDATE)
VALUES (SALE_SEQ.NEXTVAL, pcustid, pprodid, pqty, vPROD.SELLING_PRICE, pdate);
UPD_CUST_SALESYTD_IN_DB(pcustid, (pqty*vPROD.SELLING_PRICE));
UPD_PROD_SALESYTD_IN_DB(pprodid, (pqty*vPROD.SELLING_PRICE));
EXCEPTION
WHEN QTY_OUTSIDE_RANGE THEN
RAISE_APPLICATION_ERROR (-20234, 'Sale Quantity outside valid range');
WHEN STATUS_NOT_OK THEN
RAISE_APPLICATION_ERROR(-20245, 'Customer status is not OK');
WHEN INVALID_SALE_DATE THEN
RAISE_APPLICATION_ERROR(-20252, 'Date not valid');
WHEN NO_DATA_FOUND THEN
IF vPROD_ERROR = 0 THEN
RAISE_APPLICATION_ERROR (-20263, 'Customer ID not found');
ELSE
RAISE_APPLICATION_ERROR (-20271, 'Product ID not found');
END IF;
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20000, SQLERRM);
END;
这是表创建语句。
CREATE TABLE CUSTOMER (
CUSTID NUMBER
, CUSTNAME VARCHAR2(100)
, SALES_YTD NUMBER
, STATUS VARCHAR2(7)
, PRIMARY KEY (CUSTID)
);
CREATE TABLE PRODUCT (
PRODID NUMBER
, PRODNAME VARCHAR2(100)
, SELLING_PRICE NUMBER
, SALES_YTD NUMBER
, PRIMARY KEY (PRODID)
);
CREATE TABLE SALE (
SALEID NUMBER
, CUSTID NUMBER
, PRODID NUMBER
, QTY NUMBER
, PRICE NUMBER
, SALEDATE DATE
, PRIMARY KEY (SALEID)
, FOREIGN KEY (CUSTID) REFERENCES CUSTOMER
, FOREIGN KEY (PRODID) REFERENCES PRODUCT
);
我怎样才能开始测试日期是否有效?看来我需要以某种方式分解并分别测试月/日/年,但我不确定如何最好地做到这一点。
【问题讨论】:
Oracle 没有例外“日期无效异常错误(错误月份)”。这似乎是你提出的一个例外。但是您发布的代码不会引发这样的异常,所以我猜您没有显示一些额外的代码。我不确定为什么您的程序中的pDate
是varchar2
而不是date
。如果您要使用varchar2
参数,您应该在insert
语句中通过带有显式格式掩码的to_date
将其显式转换为date
,该格式掩码反映您要使用的字符串的格式路过。
由于用户提供日期信息的方式,在 varchar2 中输入 pDate,
要验证字符串是否可以转换为日期,请尝试转换它。您的 Oracle 版本是什么?从 12.2 开始,您可能会查看 validate_conversion 和 to_date 的 on conversion error
子句。
顺便说一句,WHEN OTHERS THEN RAISE_APPLICATION_ERROR(-20000, SQLERRM);
没有添加任何值。如果您没有捕获异常,则默认行为是使过程失败并返回一个错误堆栈,其中包含比您的版本更多的信息。
如果您要使用varchar2
参数,您应该通过to_date
在插入语句中将其显式转换为日期,并使用反映格式的显式格式掩码您传入的字符串。不知道您希望用户传入的字符串格式是什么,我无法建议您应该使用什么格式掩码。
【参考方案1】:
不要通过检查日期来检查日期。 01/01/21 是有效日期,但 99/01/21 不是。 oracle 数据库将尝试进行隐式转换,但将字符串更改为日期并不是一个好习惯。
既然你得到一个字符串,那么传递数据的人必须知道传递日期的格式。如果是 2021 年 2 月 9 日,他会传递 09/02/21, 02 /09/21、09-FEB-21 或 09-FEB-2021 ?所有这些都是有效日期,因此您应该假设传入日期参数的format 日期是已知的。使用已知的格式,您仍然可以获得无效的日期。假设您的日期格式是 DD/MM/YY,那么 09/02/21 是有效日期,但 50/02/21 不是,09/50/21 也不是。
使用TO_DATE
将字符串转换为数据类型DATE
。 Oracle 有几个与日期相关的例外情况。
例子:
DECLARE
l_date_input VARCHAR2(20) := '50/02/21';
l_date DATE;
BEGIN
l_date := TO_DATE(l_date_input,'DD/MM/YY');
END;
/
ORA-01847: day of month must be between 1 and last day of month
ORA-06512: at line 5
01847. 00000 - "day of month must be between 1 and last day of month"
你自己试试吧。将 '50/02/21' 更改为 '09/50/21' 并查看引发了什么异常。
现在,让我们将其放在一个仅处理分配的日期部分的示例中。请注意,此示例是一个匿名 pl/sql 块,但可以轻松地将其更改为过程。 pragma EXCEPTION_INIT
允许 association of a user-defined exception name with an error code 因此下面示例中引发的错误可以映射到您自己的异常。
DECLARE
l_date_input VARCHAR2(2000);
l_date DATE;
--exception thrown: ORA-01843: not a valid month
e_not_a_valid_month EXCEPTION;
PRAGMA EXCEPTION_INIT (e_not_a_valid_month, -01843);
--exception thrown: ORA-01847: day of month must be between 1 and last day of month
e_not_a_valid_day EXCEPTION;
PRAGMA EXCEPTION_INIT (e_not_a_valid_day, -01847);
BEGIN
l_date_input := '01/99/21';
l_date := TO_DATE(l_date_input,'DD/MM/YY');
EXCEPTION
WHEN e_not_a_valid_month THEN
RAISE_APPLICATION_ERROR (-20234, 'DATE NOT VALID EXCEPTION INCORRECT (WRONG MONTH)');
WHEN e_not_a_valid_day THEN
RAISE_APPLICATION_ERROR (-20235, 'DATE NOT VALID EXCEPTION INCORRECT (WRONG DAY)');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR (-20236, 'GENERATED UNEXPECTED EXCEPTION');
END;
/
ORA-20234: DATE NOT VALID EXCEPTION INCORRECT (WRONG MONTH)
ORA-06512: at line 17
【讨论】:
以上是关于使用 SQL / PL SQL 验证日期 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章