1

我正在尝试编写一个程序来检查给定的参数(日期)是否位于表中的任何现有日期之间。如果不插入新行。

CREATE OR REPLACE PROCEDURE test(date1 IN DATE, date2 IN DATE) AS 
  ddate1 DATE;
  ddate2 DATE;
  quer VARCHAR2(50);
BEGIN 
  SELECT fdate, tdate INTO ddate1, ddate2 FROM dataHolder; 
  IF (ddate1 < date1) AND (ddate2 > date2) THEN
    quer := 'invalid'; 
  ELSE 
    INSERT INTO dataHolder VALUES (date1, date2);
    quer := 'success';
  END IF; 
  DBMS_OUTPUT.PUT_LINE(quer); 
END;
/

我已经尝试过这样的事情,但是在执行时我得到了这个错误:

ORA-01422: exact fetch returns more than requested number of rows
4

3 回答 3

1

您收到该错误是因为您的 select 语句返回多条记录。为了简化过程,您可以使用merge语句并重写您的过程,如下所示:

CREATE OR REPLACE PROCEDURE test(date1 IN DATE, date2 IN DATE) AS
BEGIN
  merge into Dataholder dh
  using dual
     on ((date1 < dh.fdate) and (date2 < dh.tdate))
  when not matched then
    insert (dh.fdate, dh.tdate)
      values(date1, date2);
  if sql%rowcount > 0
  then
    dbms_output.put_line('success');
  else
    dbms_output.put_line('invalid');
  end if;
END; 
于 2012-12-20T20:51:48.727 回答
1

您的 select 语句获取的不仅仅是记录,而您的代码只需要一个,因为您正在获取单值变量。您可以使用 BULK COLLECT 并将所有日期收集到日期集合中,但我认为您可以使用以下代码对其进行改进:

CREATE OR REPLACE PROCEDURE test(date1 IN DATE, date2 IN DATE) AS 
  ddate1 DATE;
  ddate2 DATE;
  invalidRecords NUMBER := 0;
  quer VARCHAR2(50);
BEGIN
   SELECT COUNT(1) INTO invalidRecords FROM dataHolder WHERE fdate < date1 AND tdate > date2; 

   IF (invalidRecords > 0) THEN
     quer := 'invalid'; 
   ELSE
     INSERT INTO dataHolder VALUES (date1, date2);
     quer := 'success';
   END IF;

   DBMS_OUTPUT.PUT_LINE(quer); 
END;
/

由于 COUNT(1) 将始终只返回一条记录,因此它永远不会抛出 ORA-01422 错误。此外,它总是会返回数据,因此您无需担心 NO_DATA_FOUND,因为如果没有无效记录,则会获取值 0。

于 2012-12-20T20:52:05.347 回答
0

Nuno Guerreiro 回答的一些小优化

SELECT COUNT(1) INTO invalidRecords 
FROM dual 
WHERE exists 
  (SELECT 1 FROM dataHolder WHERE fdate < date1 AND tdate > date2);

它将允许不计数。

于 2012-12-21T06:43:36.957 回答