반응형

[오라클 Oracle] ORA-00918 : column ambiguously defined 에러 확인하기


이 에러는 쿼리에서 두개 이상의 테이블을 조인 할때, 컬럼명이 같은 경우가 있습니다. 

대부분 조인을 하기 위한 컬럼의 이름이 같은 경우가 더 많습니다. 

같은 컬럼명의 데이터를 select 할 경우 어느쪽 테이블에 있는 컬럼인지 지정을 하지 않았을때 주로 나타나는 에러 입니다. 


예를 들어 보겠습니다. 

두개의 테이블이 있습니다. 

A 테이블은 두개의 컬럼이 있습니다. 

사원번호, 이름 두개의 컬럼으로 구성되어 있습니다.

[A 테이블]

 사원번호

 이름


B 테이블 역시 두개의 컬럼으로 구성되어 있습니다. 

컬럼명은 사원번호, 직급

[B 테이블]

 사원번호

 직급


이 두개의 테이블을 조인 하여 데이터를 구할 경우 다음과 같은 간단한 쿼리를 사용합니다.

SELECT 이름

FROM A

INNER JOIN B on A.사원번호 = B.사원번호


위 쿼리는 두개의 테이블을 이용해 이름을 알수 있는 쿼리를 표시 합니다.

그런데 이때 사원번호와 직급 데이터 까지 같이 보고 싶을 경우

어떻게 될까요?

SELECT 이름, 사원번호, 직급

FROM A

INNER JOIN B on A.사원번호 = B.사원번호


이와 같은 쿼리를 실행하면 바로 위에서 볼수 있는 에러를 확인 할 수 있습니다. 

이럴땐 중복이 되는 사원번호 컬럼를 지정 하지 않으면 어느쪽에 있는 데이터를 가져 와야 할지 오라클은 알지 못해 에러를 냅니다.

그래서 다름과 같이 수정을 하면 정상으로 작동이 됩니다. 

SELECT a.이름, b.사원번호, b.직급

FROM A a

INNER JOIN B b on A.사원번호 = B.사원번호


테이블 이름을 a와 b로 선언 하고 해당 테이블 명의 데이터를 호출 하는 것입니다. 

사원번호는 B테이블의 데이터를 가져오게 명시를 했기 때문에 에러가 나지 않습니다. 


사람처럼 알아서 처리 되면 좋겠지만 컴퓨터는 해당 부분은을 제대로 명시 하지 않으면 에러가 발생합니다. 

위와 같은 에러를 확인 하게 된다면 데이터를 가져오는데 제대로 된 테이블 명시를 했지 확인 하면 빠르게 오류를 잡을 수 있을 것입니다. 




반응형
반응형

[오라클] 달력 기준으로 매월 세째주 토요일 일자 쿼리로 구하는 방법

실무에서 달력의 날짜나 요일을 구해야 하는일들이 간혹 발생 합니다. 

보통 달력테이블을 만들어 조회하는데 쿼리로 원하는 요일을 구할 수 있습니다.


방법은

  매달 월의 1일에서 14일을 더하면 달력 상에서 항상 3주차가 나오게 됩니다. 

  14일을 더한 날짜의 요일이 월요일이라면 5일을 더해주어야 하고 화요일이라면 4일을 더해주어야 토요일 일자가 나옵니다.

  요일을 구하는 함수는 TO_CHAR(날짜, 'D')이며 일요일 ~ 토요일까지 1~7 값을 반환합니다. 


WITH TEMP_DATE AS (

SELECT TO_DATE(YYYY||MM, 'YYYYMM') YYYYMM     

  FROM (SELECT LPAD(LEVEL, 2, '0') MM FROM DUAL 

        CONNECT BY LEVEL <= 12)

     , (SELECT TO_CHAR(LEVEL+2018) YYYY FROM DUAL 

        CONNECT BY LEVEL <= 1)

ORDER BY 1)


SELECT YYYYMM, YYYYMM + 14 + (7-TO_CHAR(YYYYMM, 'D')) "세째주 토요일"

  FROM TEMP_DATE


위에 있는 쿼리를 사용하면 됩니다. 

TEMP_DATE 를 정의하고 호출하면 됩니다. 이방법을 응용해서 2주차나 4주차에 적용해 볼수 있습니다. 

반응형
반응형

[오라클] 쿼리(query) Hint 내용 정리


A. Initialization Parameter중 OPTIMIZER_MODE 지정가능 값

1.ALL_ROWS

전체 RESOURCE 소비를 최소화 시키기 위한 힌트. Cost-Based 접근방식.

SELECT /*+ALL_ROWS */

EMPNO,ENAME

FROM EMP

WHERE EMPNO = 7655;


2.FIRST_ROWS

조건에 맞는 첫번째 row를 리턴하기 위한 Resource 소비를 최소화 시키기위한 힌트.

특징 : Index Scan 이 가능하다면 Optimizer가 Full Table Scan 대신 Index Scan을 선택합니다.

Index Scan 이 가능하다면 Optimizer가 Sort-Merge 보다 Nested Loop 을 선택합니다.

Order By절에의해 Index Scan 이 가능하다면, Sort과정을 피하기위해 Index Scan을 선택합니다.

Delete/Update Block 에서는 무시됩니다.

다음을 포함한 Select 문에서도 제외됩니다.

집합연산자 (UNION, INTERSECT, MINUS, UNION ALL)

Group By

For UpDate

Group 함수

Distinct


SELECT /*+FIRST_ROWS */

EMPNO,ENAME

FROM EMP

WHERE EMPNO = 7655;


3.CHOOSE

Data Dictionary가 해당테이블에 대해 통계정보를 가지고 있다면 Optimizer는 Cost-Based Approach를 선택하고, 그렇지 않다면 Rule-Based Approach를 선택합니다.


SELECT /*+CHOOSE */

EMPNO,ENAME

FROM EMP

WHERE EMPNO = 7655;


4.RULE

Rule-Based 최적화를 사용하기 위함 입니다.


SELECT /*+RULE */

EMPNO,ENAME

FROM EMP

WHERE EMPNO = 7655;


B. Access Methods 로써의 Hints


1.FULL

해당테이블의 Full Table Scan을 유도.

테이블 Alias 가 있는경우는 Alias사용.

Schema Name은 사용안함(From 에 SCOTT.EMP 라고 기술해도 hint에는 EMP사용).


SELECT /*+FULL(EMP) */

EMPNO, ENAME

FROM EMP

WHERE EMPNO = 7655;


2.ROWID

지정된 테이블의 ROWID를 이용한 Scan 유도


3.CLUSTER

지정된 테이블Access에 Cluster Scan 유도. Cluster된 Objects에만 적용가능.


SELECT /*+CLUSTER(EMP) */

ENAME,DEPTNO

FROM EMP,DEPT

WHERE DEPTNO = 10

AND EMP.DEPTNO = DEPT.DEPTNO;




4.HASH

지정된 테이블Access에 HASH Scan 유도.

/*+HASH(table) */


5.HASH_AJ

NOT IN SubQuery 를 HASH Anti-join으로 변형

/*+HASH_AJ */


6.HASH_SJ

용도 : Correlated Exists Subquery 를 Hash Semi-join으로 변형

/*+HASH_SJ */


7.INDEX

지정된 테이블access에 Index Scan 유도.

하나의 Index만 지정되면 Optimizer는 해당index를 이용.

여러개의 인덱스가 지정되면 Optimizer가 각 Index의 Scan시 Cost를 분석 한 후 최소비용이 드는 Index사용. 경우에 따라 Optimizer는 여러 Index를 사용한 후 결과를 Merge하는 Acees방식도 선택합니다.

Index가 지정되지 않으면 Optimizer는 테이블의 이용가능한 모든 Index에 대해 Scan Cost를 고려 후 최저비용이 드는 Index Scan을 선택합니다.


SELECT /*+INDEX(EMP EMPNO_INDEX) */

EMPNO, ENAME

FROM EMP

WHERE DEPTNO=10;


8.INDEX_ASC

INDEX HINT와 동일 단,ASCENDING 으로 SCAN함을 확실히 하기위함 입니다.


9.INDEX_COMBINE

Index명이 주어지지 않으면 Optimizer는 해당 테이블의 Best Cost 로 선택된 Boolean Combination Index 를 사용한다. Index 명이 주어지면 주어진 특정 Bitmap Index 의 Boolean Combination 의 사용을 시도합니다.

/*+INDEX_COMBINE(table index) */


10.index_desc

지정된 테이블의 지정된 Index를 이용 Descending으로 Scan 하고자 할 때 사용합니다.

/*+index_desc(table index) */


11.INDEX_FFS

Full Table Scan보다 빠른 Full Index Scan을 유도.

/*+INDEX_FFS(table index) */


12.MERGE_AJ

NOT IN Subquery를 Merge Anti-join으로 변형

/*+MERGE_AJ */


13.MERGE_SJ

Correalted EXISTS Subquery를 Merge Semi-join으로 변형

/*+MERGE_SJ */


14.AND_EQUAL

Single-column Index의 Merge를 이용한 Access Path 선택. 적어도 두개이상의 Index가 지정되어야 합니다. 

/*+AND_EQUAL(Table Index1, Index2...) */


15.USE_CONCAT

조건절의 OR 를 UNION ALL 형식으로 변형합니다. 일반적으로 변형은 비용측면에서 효율적일때만 일어납니다.

/*+USE_CONCAT */


C. JOIN 순서를 결정하는 Hints

1.ORDERED

FROM절에 기술된 테이블 순서대로 JOIN이 일어나도록 유도.

/*+ORDERED */


SELECT /*+ORDERED */

TAB1.COL1,TAB2.COL2,TAB3.COL3

FROM TAB1,TAB2,TAB3

WHERE TAB1.COL1=TAB2.COL1

AND TAB2.COL1=TAB3.COL1;


2.STAR

Star Query Plan이 사용가능하다면 이를 이용하기위한 Hint. Star Plan은 규모가 가장큰 테이블이 Query에서 Join Order상 마지막으로 위치하게 하고 Nested Loop 으로 Join이 일어나도록 유도합니다.

적어도 3개 테이블 이상이 조인에 참여해야하며 Large Table의 Concatenated Index는 최소 3컬럼 이상을 Index에 포함해야합니다.

테이블이 Analyze 되어 있다면 Optimizer가 가장효율적인 Star Plan을 선택합니다.

/*+STAR */


D. JOIN OPERATION을 결정하는 HINTS.

1.USE_NL

테이블의 Join 시 테이블의 각 Row가 Inner 테이블을 Nested Loop 형식으로 Join 한다.

/*+USE_NL(inner_table) */


SELECT /*+ORDERD USE_NL(CUSTOMER) */

FROM ACCOUNT.BALANCE,

CUSTOMER.LAST_NAME,

CUSTOMER.FIRST_NAME

WHERE ACCOUNT.CUSTNO = CUSTOMER.CUSTNO;


2.USE_MERGE

지정된 테이블들의 조인이 SORT-MERGE형식으로 일어나도록 유도.

괄호안의 테이블은 JOIN ORDER상의 뒤의 테이블

/*+USE_MERGE(table) */


3.USE_HASH

각 테이블간 HASH JOIN이 일어나도록 유도.

괄호안의 테이블은 JOIN ORDER상의 뒤의 테이블

/*+USE_HASH(table) */


4.DRIVING_SITE

QUERY의 실행이 ORACLE에 의해 선택된 SITE가 아닌 다른 SITE에서 일어나도록 유도.

/*+DRIVING_SITE(table) */


SELECT /*+DRIVING_SITE(DEPT) */

FROM EMP,DEPT@RSITE

WHERE EMP.DEPTNO = DEPT.DEPTNO;


DRIVING_SITE 힌트를 안쓰면 DEPT의 ROW가 LOCAL SITE로 보내져 LOCAL SITE에서 JOIN이 일어나지만,

DRIVING_SITE 힌트를 쓰면 EMP의 ROW들이REMOTE SITE로 보내져 QUERY가 실행된후 LOCAL SITE로 결과가 RETURN됩니다.



( 출처 database.sarang.net 내용 정리 )

반응형
반응형
[오라클] 동일 데이터 반복 조회 access에 대한 쿼리 튜닝 방법
감사합니다. 고맙습니다. 행운을 드립니다.

간혹 최소, 최대값등에 의해 값을 구해야 할경우가 있습니다.

서브쿼리를 이용하여 데이터를 조회한후에 또다시 결과를 조회할경우 테이블 풀스캔이 반복적으로 발생합니다.

이럴경우 RANK를 사용하면 성능에 좋습니다.

예제)

SELECT * FROM EMP
WHERE (JOB, ENAME) IN
(SELECT JOB, MIN(ENAME) AS ENAME FROM EMP GROUP BY JOB)
ORDER BY ENAME;

=>

SELECT * FROM
(SELECT A.*, RANK() OVER(PARTITION BY JOB ORDER BY ENAME) RNK
 FROM EMP A)
WHERE RNK=1
ORDER BY ENAME;
반응형
반응형

오라클 접속 가능한 세션의 수 변경

http://db.necoaki.net/144

오라클 안에는 세션에 관련된 두개의 파라미터 값이 있다.

show parameter processes


SESSIONS = (PROCESSES * 1.1) + 5

 ex> 150 *1.1+5= 170


현재 DB의 최대 접속 가능 세션은 170개 이다.

spfile을 사용 하는 경우 아래의 명령으로 변경 가능하다. (DB 재구동 후 반영)


SQL> alter system set PROCESSES = 300 scope=spfile;

pfile을 사용하는 경우 파라미터 파일을 직접 열어서 *.processes= 값을 변경해주고 재구동 해주면 된다.



반응형
반응형

SYNONYM은 오라클 객체(테이블,뷰,시퀀스,프로시저)에 대한 Alias를 말한다.

SYNONYM은 실질적으로 그차제가 Object가 아니라 Object에 대한 직접적인 참조 


- 실무에서 다른 유저의 객체를 참고할 경우 SYNONYM을 생성해서 사용을 하면

  추후에 참고하고 있는 오프젝트가 이름을 바꾸거나 이동을 할 경우 객체를 사용하는

  SQL 구문을 모두 다시 고칠 필요가 없이 SYNONYM 만 다시 정의 하면 된다.

- 긴 이름을 단순하게, 짧게 만들어 쓸 수 있다. 

- 객체를 참조하는 사용자의 오브젝트를 감출 수 있기 때문에 보안 유지가 된다. 

  SYNONYM을 사용하는 유저는 참조하고 있는 객체에 대한 사용자의 오브젝트 

  소유자,이름,서버이름을 몰라도 SYNONYM이름만 알면 사용할 수 있다. 


SYNONYM 사용하는 경우

#오브젝트의 실제 이름과 소유자 그리고 위치를 감추고 DB보안을 개선하는데 사용

#오브젝트에 Public Access를 제공

#Remote DB의 table,view, program Init를 위해 투명성 제공

#DB SQL문 단순화


SYNONYM 두가지 종류가 있다.

- Private SYNONYM

  특정사용사만 이용할 수있다.

- Publice SYNONYM

  DB에 있는 모든 사용자가 공유 하여 사용할 수 있다. 



SYNONYM 구문


CREATE [PUBLIC] SYNONYM synonm_name

FOR object_name


- Public : 모든 사용자가 접근 가능한 SYNONYM을 생성

             Publice SYNONYM 은 DBA만 생성할 수 있다.



% scott USER의 emp 테이블을 test USER가 사용하는 예제

1. 먼저 scott/tiger USER로 접속해서 test USER에게 emp 테이블의 조작할 권한을 부여한다


GRANT ALL ON emp TO test;

권한이 부여 되었습니다. 


test user에 대하여 scott의 emp테이블을 조작할 수 있는 권한을 부여한다.

권한이 있어야 select 하거나 update, insert 할 수 있다.


2. test USER로 접속해 동의어를 생성한다 


connect test/test


GREATE SYNONYM scott_emp FOR scott.emp;

시노임이 생성 됨


scott USER가 소유하고 있는 emp테이블에 대해 scott_emp라는 일반 시노임을 생성

scott 사용자의 emp 테이블을 test 사용자가 scott_emp라는 동의러로 사용한다.


-- SYNONYM을 이용한 쿼리

select empno ,ename from scott_emp;


-- 일반 테이블 쿼리

select empno ,ename from scott.emp;


두 쿼리 결과는 같다.


동의어 삭제


DROP SYNONM scott_emp;

시노임이 삭제 되었습니다. 


select empno ,ename from scott_emp;

라인 1에 오류:

ORA-00942: 테이블 또는 뷰가 존재 하지 않는다. 


http://jhbench.tistory.com/200 블로그 참조

반응형

+ Recent posts