면책 조항 : 업무 시간의 일부만 데이터베이스를 사용하는 사람으로 저와 함께하십시오. (대부분 저는 C ++ 프로그래밍 작업을 수행하지만 매월마다 Oracle 데이터베이스에서 무언가를 검색 / 수정 / 추가해야합니다.)
저는 임시 쿼리와 응용 프로그램에 내장 된 쿼리 모두에 대해 복잡한 SQL 쿼리를 반복해서 작성해야했습니다. 여기서는 쿼리의 대부분이 "코드"를 반복했습니다.
기존의 프로그래밍 언어와 같은 가증를 작성하는 것은 곤경에 당신을 얻을 것이다, 그러나 I ( 나는 ) 아직 방지 SQL 쿼리 코드의 반복에 어떤 점잖은 기술을 찾을 수 없었습니다.
편집 : 1, 나는 원래의 예를 크게 개선 한 답변자에게 감사드립니다 . 그러나이 질문은 내 예에 관한 것이 아닙니다. SQL 쿼리의 반복성에 관한 것입니다. 따라서 지금까지 답변 ( JackP , Leigh )은 더 나은 쿼리를 작성하여 반복성을 줄일 수 있다는 것을 보여줍니다 . 그러나 그때 조차도 분명히 제거 할 수없는 반복성에 직면합니다. "전통적인"프로그래밍 언어에서는 코드의 반복성을 최소화하기 위해 상당히 많은 리팩토링을 수행 할 수 있지만 SQL을 사용하면 덜 반복적 인 명령문을 작성하는 것 외에는이를 허용하는 도구가없는 것 같습니다.
더 많은 것을 허용하는 데이터베이스 나 스크립팅 언어가 없는지에 관심이 있기 때문에 Oracle 태그를 다시 제거했습니다.
여기 제가 오늘 함께 모은 보석이 있습니다. 기본적으로 단일 테이블의 열 집합의 차이를보고합니다. 다음 코드를 통해 훑어보십시오. 끝에 큰 쿼리. 아래 계속하겠습니다.
--
-- Create Table to test queries
--
CREATE TABLE TEST_ATTRIBS (
id NUMBER PRIMARY KEY,
name VARCHAR2(300) UNIQUE,
attr1 VARCHAR2(2000),
attr2 VARCHAR2(2000),
attr3 INTEGER,
attr4 NUMBER,
attr5 VARCHAR2(2000)
);
--
-- insert some test data
--
insert into TEST_ATTRIBS values ( 1, 'Alfred', 'a', 'Foobar', 33, 44, 'e');
insert into TEST_ATTRIBS values ( 2, 'Batman', 'b', 'Foobar', 66, 44, 'e');
insert into TEST_ATTRIBS values ( 3, 'Chris', 'c', 'Foobar', 99, 44, 'e');
insert into TEST_ATTRIBS values ( 4, 'Dorothee', 'd', 'Foobar', 33, 44, 'e');
insert into TEST_ATTRIBS values ( 5, 'Emilia', 'e', 'Barfoo', 66, 44, 'e');
insert into TEST_ATTRIBS values ( 6, 'Francis', 'f', 'Barfoo', 99, 44, 'e');
insert into TEST_ATTRIBS values ( 7, 'Gustav', 'g', 'Foobar', 33, 44, 'e');
insert into TEST_ATTRIBS values ( 8, 'Homer', 'h', 'Foobar', 66, 44, 'e');
insert into TEST_ATTRIBS values ( 9, 'Ingrid', 'i', 'Foobar', 99, 44, 'e');
insert into TEST_ATTRIBS values (10, 'Jason', 'j', 'Bob', 33, 44, 'e');
insert into TEST_ATTRIBS values (12, 'Konrad', 'k', 'Bob', 66, 44, 'e');
insert into TEST_ATTRIBS values (13, 'Lucas', 'l', 'Foobar', 99, 44, 'e');
insert into TEST_ATTRIBS values (14, 'DUP_Alfred', 'a', 'FOOBAR', 33, 44, 'e');
insert into TEST_ATTRIBS values (15, 'DUP_Chris', 'c', 'Foobar', 66, 44, 'e');
insert into TEST_ATTRIBS values (16, 'DUP_Dorothee', 'd', 'Foobar', 99, 44, 'e');
insert into TEST_ATTRIBS values (17, 'DUP_Gustav', 'X', 'Foobar', 33, 44, 'e');
insert into TEST_ATTRIBS values (18, 'DUP_Homer', 'h', 'Foobar', 66, 44, 'e');
insert into TEST_ATTRIBS values (19, 'DUP_Ingrid', 'Y', 'foo', 99, 44, 'e');
insert into TEST_ATTRIBS values (20, 'Martha', 'm', 'Bob', 33, 88, 'f');
-- Create comparison view
CREATE OR REPLACE VIEW TA_SELFCMP as
select
t1.id as id_1, t2.id as id_2, t1.name as name, t2.name as name_dup,
t1.attr1 as attr1_1, t1.attr2 as attr2_1, t1.attr3 as attr3_1, t1.attr4 as attr4_1, t1.attr5 as attr5_1,
t2.attr1 as attr1_2, t2.attr2 as attr2_2, t2.attr3 as attr3_2, t2.attr4 as attr4_2, t2.attr5 as attr5_2
from TEST_ATTRIBS t1, TEST_ATTRIBS t2
where t1.id <> t2.id
and t1.name <> t2.name
and t1.name = REPLACE(t2.name, 'DUP_', '')
;
-- NOTE THIS PIECE OF HORRIBLE CODE REPETITION --
-- Create comparison report
-- compare 1st attribute
select 'attr1' as Different,
id_1, id_2, name, name_dup,
CAST(attr1_1 AS VARCHAR2(2000)) as Val1, CAST(attr1_2 AS VARCHAR2(2000)) as Val2
from TA_SELFCMP
where attr1_1 <> attr1_2
or (attr1_1 is null and attr1_2 is not null)
or (attr1_1 is not null and attr1_2 is null)
union
-- compare 2nd attribute
select 'attr2' as Different,
id_1, id_2, name, name_dup,
CAST(attr2_1 AS VARCHAR2(2000)) as Val1, CAST(attr2_2 AS VARCHAR2(2000)) as Val2
from TA_SELFCMP
where attr2_1 <> attr2_2
or (attr2_1 is null and attr2_2 is not null)
or (attr2_1 is not null and attr2_2 is null)
union
-- compare 3rd attribute
select 'attr3' as Different,
id_1, id_2, name, name_dup,
CAST(attr3_1 AS VARCHAR2(2000)) as Val1, CAST(attr3_2 AS VARCHAR2(2000)) as Val2
from TA_SELFCMP
where attr3_1 <> attr3_2
or (attr3_1 is null and attr3_2 is not null)
or (attr3_1 is not null and attr3_2 is null)
union
-- compare 4th attribute
select 'attr4' as Different,
id_1, id_2, name, name_dup,
CAST(attr4_1 AS VARCHAR2(2000)) as Val1, CAST(attr4_2 AS VARCHAR2(2000)) as Val2
from TA_SELFCMP
where attr4_1 <> attr4_2
or (attr4_1 is null and attr4_2 is not null)
or (attr4_1 is not null and attr4_2 is null)
union
-- compare 5th attribute
select 'attr5' as Different,
id_1, id_2, name, name_dup,
CAST(attr5_1 AS VARCHAR2(2000)) as Val1, CAST(attr5_2 AS VARCHAR2(2000)) as Val2
from TA_SELFCMP
where attr5_1 <> attr5_2
or (attr5_1 is null and attr5_2 is not null)
or (attr5_1 is not null and attr5_2 is null)
;
보다시피, "차이 보고서"를 생성하는 쿼리는 동일한 SQL SELECT 블록을 5 번 사용합니다 (쉽게 42 배일 수 있음). 이것은 절대적으로 뇌가 죽은 것처럼 보입니다 (코드를 작성한 후에도 말할 수 있습니다). 그러나 이것에 대한 좋은 해결책을 찾지 못했습니다.
이 몇 가지 실제 응용 프로그램 코드에서 쿼리 될 경우에, 나는 할 수 함께이 쿼리 자갈 함수 쓰기 문자열로를 한 후 나는 문자열로 쿼리를 실행할 것입니다.
- -> 건물 끈은 테스트하고 유지하기가 끔찍하고 끔찍합니다. "응용 프로그램 코드"가 PL / SQL과 같은 언어로 작성된 경우 너무 잘못 느껴집니다.
또는 PL / SQL 등에서 사용하는 경우이 쿼리를보다 유지 관리하기 쉽게 만드는 절차 적 수단이 있다고 생각합니다.
- -> 코드 반복을 방지하기 위해 단일 쿼리에서 절차 단계로 표현할 수있는 무언가를 풀면 잘못된 느낌이 든다.
이 쿼리가 데이터베이스의보기로 필요하다면, 내가 이해하는 한, 위에서 게시 한대로보기 정의를 실제로 유지하는 것 외에 다른 방법은 없습니다. (!!?)
- -> 실제로 2 페이지 뷰 정의에서 한 번 유지 보수를 수행해야했지만 위의 설명에서 멀지 않았습니다. 분명히,이보기에서 무엇이든 변경하려면 동일한 서브 문이 다른 행에서 사용되었는지 여부와 변경해야하는지 여부에 대한보기 정의를 정규식 텍스트 검색해야했습니다.
제목이 지남에 따라- 그러한 혐오를 작성하지 않아도되는 기술은 무엇입니까?
UNION ALL
. 일반적 으로 필요한 정렬 작업 ( 'UNION'이 효과적으로 뒤 따르는 정렬을 의미 함) 을 위해 임시 스토리지에 대한 스풀을 생성UNION
하지 않으므로 경우에 따라 성능 차이가 클 수 있습니다.ALL
UNION ALL
DISTINCT