2010-08-12 2 views
4

오라클 데이터베이스에는 SQLQUERY라는 필드가있는 RULES라는 테이블이 있습니다. 이 필드는 SQL 문이 저장된 varchar입니다. PK는 DM_PROJECT입니다.다른 명령문의 일부로 테이블에 저장된 SQL 문을 사용하려면 어떻게해야합니까?

나는 이런 식으로 뭔가하고 싶은

select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATED_SALES > 500000 

수 저장되어있는 일반적인 문 :

select 
    * 
from 
    customers 
where 
    accountnumber like 'A%' 
    or salesregion = 999 
    or accountnumber in 
    (
     <run the query SQLQUERY from RULES where DM_PROJECT=:DM_PROJECT> 
    ) 

는이 작업을 수행 할 수 있습니까?

(차 우려 : 저장된 쿼리가 자신의 변수를 사용하는 경우는

select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATEDSALES > :LIMIT 

같이 수행 할 수 있습니다)

+0

흥미로운 질문입니다! – Flukey

+1

내부 플랫폼 효과가 다시 타고납니다! –

답변

8

참으로 흥미로운 질문입니다. 이것에는 두 가지 측면이 있습니다.

첫 번째는 좋은 생각인지 여부입니다. 문제는 RULE의 텍스트가 데이터베이스에 보이지 않는다는 것입니다. 의존성 검사에서 나타나지 않으므로 영향 분석이 어려워집니다. 분명히 (또는 분명히는 아닐지라도) 규칙의 구문은 그것을 실행함으로써 만 검증 될 수 있습니다. 이로 인해 규칙을 추가 할 때 문제가 발생할 수 있습니다. 따라서 유지 관리 문제가 될 수도 있습니다. 그리고 우리가 볼 수 있듯이 단순한 쿼리를 넘어 서면 프로그램하기가 어렵습니다.

두 번째 측면은 가능한지 여부입니다. 그것은. 동적 SQL을 사용해야합니다. 동적 SQL과 정적 SQL을 결합하는 것은 가능하지만 치명적입니다.

create table rules (project_name varchar2(30) 
        , rule_name varchar2(30) 
        , rule_text varchar2(4000)) 
/
insert into rules 
values ('SO', 'ACC_SALES' 
     , 'select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATED_SALES > 500000 ') 
/
create table customers (accountnumber number(7,0) 
         , name varchar2(20) 
         , accumulated_sales number 
         , sales_region varchar2(3)) 
/
insert into customers values (111, 'ACME Industries', 450000, 'AA') 
/
insert into customers values (222, 'Tyrell Corporation', 550000, 'BB') 
/
insert into customers values (333, 'Lorax Textiles Co', 500000, 'BB') 
/

이 함수는 규칙을 가져 와서 실행하고 숫자 배열을 반환합니다.

create or replace type rule_numbers as table of number 
/

create or replace function exec_numeric_rule 
    (p_pname in rules.project_name%type 
     , p_rname in rules.rule_name%type) 
    return rule_numbers 
is 
    return_value rule_numbers; 
    stmt rules.rule_text%type; 
begin 
    select rule_text into stmt 
    from rules 
    where project_name = p_pname 
    and rule_name = p_rname; 

    execute immediate stmt 
     bulk collect into return_value; 

    return return_value; 
end exec_numeric_rule; 
/

테스트 해보십시오.

SQL> select * from customers 
    2 where accountnumber in 
    3  (select * from table (exec_numeric_rule('SO', 'ACC_SALES'))) 
    4/

ACCOUNTNUMBER NAME     ACCUMULATED_SALES SAL 
------------- -------------------- ----------------- --- 
      222 Tyrell Corporation    550000 BB 

1 row selected. 

SQL> 

오직 하나의 정답입니다.

하지만 지금 우리는 당신의 suplementary 질문에 와서 : 일이 얻을 시작

이 할 수있는 예 "가 저장된 쿼리 가 자신의 변수를 사용하는 경우 수행 할 수 있습니다"하지만, 조금 더 부서지기 쉽다. 새로운 규칙 : 우리는 기능을 개정

insert into rules 
values ('SO', 'ACC_SALES_VAR' 
     , 'select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATED_SALES > :LMT ') 
/

을 적용합니다 :

create or replace function exec_numeric_rule 
    (p_pname in rules.project_name%type 
     , p_rname in rules.rule_name%type 
     , p_variable in number := null) 
    return rule_numbers 
is 
    return_value rule_numbers; 
    stmt rules.rule_text%type; 
begin 
    select rule_text into stmt 
    from rules 
    where project_name = p_pname 
    and rule_name = p_rname; 

    if p_variable is null then 
     execute immediate stmt 
      bulk collect into return_value; 
    else 
     execute immediate stmt 
      bulk collect into return_value 
      using p_variable;   
    end if; 

    return return_value; 
end exec_numeric_rule; 
/

손가락을 교차!

SQL> select * from customers 
    2 where accountnumber in 
    3  (select * from table (exec_numeric_rule('SO', 'ACC_SALES_VAR', 480000))) 
    4/

ACCOUNTNUMBER NAME     ACCUMULATED_SALES SAL 
------------- -------------------- ----------------- --- 
      222 Tyrell Corporation    550000 BB 
      333 Lorax Textiles Co    500000 BB 

2 rows selected. 

SQL> 

그래, 그래도 작동합니다. 그러나 순열이 친숙하지 않다는 것을 알 수 있습니다. RULE에 하나 이상의 인수를 전달하려면 더 많은 함수 또는 twistier 내부 논리가 필요합니다.날짜 또는 문자열 집합을 반환하려면 더 많은 기능이 필요합니다. 다른 data_types의 P_VARIABLE 매개 변수를 전달하려면 더 많은 함수가 필요할 수 있습니다. 유형 검사 사전 조건이 필요합니다.

내 첫 번째 지점으로 돌아가는 : 예, 할 수 있지만 그 번거 로움입니까?

+0

환상적인 답변입니다. 당신 같은 사람들은 stackoverflow를 멋지게 만듭니다. 잘하셨습니다, 폐하! – Flukey

+0

저는 Jamie와 여기에 동의해야합니다. 정말 흥미롭고 훌륭한 답변이었습니다! +1하십시오. – wasatz

+0

+1 : 아주 잘 답변. 파이프 라인 함수는 이러한 종류의 프로 시저에 대해 중첩 테이블보다 성능이 좋을 수 있습니다. – Allan

0

당신은 더 많은 것을 위해 Execute Immediate을 참조 ..please 동적 SQL을 (즉시 실행)을 사용할 수 있습니다 세부.

관련 문제