2014-12-12 2 views
0

그래서 일부 PL SQL 문에 약간 문제가 있습니다. 본질적으로 나는 새로운 튜플이 삽입 될 때 프로 시저가 동일한 날짜에 동일한 사람에 대해 다른 계약이 없다는 것을 검사하는 프로 시저를 만들려고합니다. 새 계약의 날짜는 다른 계약의 날짜와 겹치지 않습니다. 여기 PL/SQL 프로 시저 구문

코드입니다 :

CREATE OR REPLACE PROCEDURE dateOrder 
(name IN VARCHAR2, start IN DATE, end IN DATE) 
IS 
    x number; 
    y number; 

BEGIN 
    CREATE OR REPLACE VIEW PersonContracts AS 
    SELECT * FROM ContractInfo WHERE HasContract=name; 

    SELECT COUNT(*) INTO x FROM PersonContracts 
    WHERE start BETWEEN date_from AND date_to; 

    SELECT COUNT(*) INTO y from PersonContracts 
    WHERE end BETWEEN date_from AND date_to; 
    IF x > 0 THEN 
     dbms_output.put_line("overlaps."); 
    END IF; 

    IF Y > 0 THEN 
     dbms_output.put_line("overlaps."); 
    END IF; 

END dateOrder; 
/

BEGIN 
    dateOrder("John Smith", "08-oct-2014", "12-oct-2014"); 
END; 

내가 또는보기없이 시도하지만 난 가능하면보기를 유지하는 것을 선호합니다. 나는 PL에서만 새롭다!

답변

1

DDL을 사용하여 프로 시저 내에서 VIEW를 만들 수 없습니다 (이렇게하려면 EXECUTE IMMEDIATE를 사용해야합니다).

내가 직접 SELECT 문의 WHERE 절을 설정하는 것을 선호 :

CREATE OR REPLACE PROCEDURE dateOrder (name IN VARCHAR2, start IN DATE, end IN DATE) 
    IS 
     x number; 
     y number; 
    BEGIN 

    SELECT COUNT(*) INTO x FROM ContractInfo WHERE HasContract=name 
    AND start BETWEEN date_from AND date_to; 

    SELECT COUNT(*) INTO y from ContractInfo WHERE HasContract=name 
    AND end BETWEEN date_from AND date_to; 

    IF x > 0 THEN 
     dbms_output.put_line("overlaps."); 
    END IF; 

    IF Y > 0 THEN 
     dbms_output.put_line("overlaps."); 
    END IF; 

END dateOrder; 
/

BEGIN 
    dateOrder("John Smith", "08-oct-2014", "12-oct-2014"); 
END; 
+2

내 의견으로는, 이것은 더 나은 해결책입니다. 일반적으로 절차 코드에서 데이터베이스 개체를 다시 정의하는 것은 좋지 않습니다. – Allan

+0

그래, 고마워! 보기는 그렇게 중요하지 않았습니다! 그냥 AND를 WHERE에 추가하면 나에게 동일한 효과가 나타납니다. –

1

그래서 몇 가지 당신 절차에서 작동하지 않습니다. 솔루션으로 권장하지 마십시오.

  1. 절차 내에서 ddl을 코딩하는 것은 좋지 않습니다. 그리고이 과정에서 새로운 관점에 접근하는 것은 불가능합니다 !!
  2. 이렇게하려면 코드 조각과 같은 동적 SQL 문에 만들기보기를 넣으십시오.
  3. 프로 시저에서 액세스하려는 모든 DB 개체는 컴파일 할 때 존재해야합니다. 따라서이 코드는 동적 SQL에도 모든 Select 문을 작성하지 않으면 작동하지 않습니다.
  4. 매개 변수의 이름을 "시작"또는 "종료"로 지정하지 마십시오. Theese는 예약어이므로 허용되지 않습니다.
  5. dateOrder 프로 시저를 호출하는 경우 유효한 날짜를 매개 변수로 전달해야합니다. 귀하의 예에서는 문자열을 전달합니다. 어쩌면 이것은 기본 NLS에서 작동하지만 다른 환경/데이터베이스에서는 작동하지 않을 수도 있습니다.

확인이 아웃 :

CREATE OR REPLACE PROCEDURE dateOrder 
(name IN VARCHAR2, xstart IN DATE, xend IN DATE) 
IS 
    x number; 
    y number; 

BEGIN 
    execute immediate (
     'CREATE OR REPLACE VIEW PersonContracts AS 
     SELECT * FROM ContractInfo ....' 
    ); 
    -- that won't work, because the PersonContracts will be not there at compile time. 
    SELECT COUNT(*) INTO x FROM PersonContracts 
    WHERE start BETWEEN date_from AND date_to; 

    SELECT COUNT(*) INTO y from PersonContracts 
    WHERE end BETWEEN date_from AND date_to; 
    IF x > 0 THEN 
     dbms_output.put_line("overlaps."); 
    END IF; 

    IF Y > 0 THEN 
     dbms_output.put_line("overlaps."); 
    END IF; 


END dateOrder; 


BEGIN 
    dateOrder("John Smith", "08-oct-2014", "12-oct-2014"); 
END; 
+0

이 작업을 수행하려면 프로 시저를 컴파일 할 때보기가 있어야합니다. 사전에 존재하는 한 프로 시저에서 다시 정의 할 수 있습니다. – Allan

+1

네 말이 맞아. 방금 동적 SQL에 초점을 맞추었고 나머지는 확인하지 않았습니다. 그런데 이런 코드를 작성하는 것은 권장되지 않습니다. –

0

뷰가 허용 된 경우에도 필요하지 않습니다. HasContract 값이 name 매개 변수와 같은 행만 검사하려고합니다. 좋아요, 원하는대로 쿼리를 작성한 다음 where 절에 HasContract = name을 추가하십시오. 간단한 해결책을 과장하지 마십시오.

또한 하나의 쿼리에서 필요한 것을 찾을 수 있습니다. catch하려는 조건은 시작 및 중지 날짜로 정의 된 간격과 기존 시작 및 중지 날짜 사이에 겹침이있는 경우입니다. 오버랩으로 이어질 수있는 모든 생각을 열심히 나열 할 수 있지만 이 중복되지 않는 유일한 두 가지 조치를 살펴 보겠습니다.

  • 하나 종료일 시작 다른 날짜 또는
  • 하나의 시작일 다른 끝에 데이터 이상인 경우 이하인 경우.

또는 수식 양식 e1 <= s2 or s1 >= e2. 작은 부울 마술이고 e1 > s2 and s1 < e2으로 바꿀 수 있습니다.그러면 간단한 쿼리가 제공됩니다.

이 쿼리가 0이 아닌 답을 반환하면 어딘가에 겹침이 생깁니다. 하나의 간단한 쿼리. 하나는 나중에 검사합니다. 쉬운.

관련 문제