sql (19)

기본적으로 오라클에는 특수기호에 대해서 검사를 하고 대체할 수 있도록 정의를 해놓은 것이 있는데 이 중에 특수기호 '&'도 포함이 되어있다. 


따라서 insert into table1 values ( 'a & b'); 라는 문장을 실행하면 SQLDeveloper에서는 대체문자를 설정하라고 팝업창이 뜬다.


처음에는 이게 뭐지? 하고서 그냥 엔터를 쳤었는데 나중에 보니 그렇게 엔터쳤던 것 때문에 insert할 때 &가 공백으로 바뀌어져서 내용이 들어가있었다.


그런데 이렇게 특수기호가 들어간 문장을 수 백개 insert해야 한다면....???


일일히 다 대체문자를 입력할 수가 없다!!!


이럴 때 유용하게 쓸 수 있는게


SQL> set define off;


이다.


위 명령어는 현재 세션에 대해서 "특수기호 대체 검사"를 하지 않도록 해준다. 

일반 사용자 계정으로 제약사항 목록을 조회하려면 아래 쿼리를 사용하면 됩니다.


select * from user_constraints;



여러개의 테이블을 한꺼번에 삭제하고 싶은데 like 조건절을 쓸 수가 없다.

뭐 결국 테이블 하나하나를 각각 삭제해줘야 한다는 건데....그렇다고 테이블이 수 십개가 넘는데 이걸 다 손으로 타이핑하기란 짜증하는 일이 아닐 수 없다.


이럴 때 다음 쿼리로 특정 사용자의 전체 테이블을 삭제 할 수 있는 쿼리를 얻어올 수 있다.

 

SELECT 'DROP TABLE ' || TABLE_NAME || ';' FROM ALL_TABLES WHERE OWNER = 'user1';


조건절은 마음대로 바꿀 수 있고 위에서 사용한 ALL_TABLES는 DBA권한이 있어야 접근이 가능하다.


따라서 일반 사용자이면서 자신이 소유한 테이블을 삭제할 때는


ALL_TABLES 대신 USER_TABLES 에서 조회한 테이블명을 사용하면 된다.


SELECT 'DROP TABLE ' || TABLE_NAME || ';' FROM USER_TABLES WHERE OWNER = 'user2';


instr함수는 어떤 스트링의 특정위치에서 시작해서 특정 케릭터가 위치한 곳까지의 위치를 계산해서 반환해주는 함수입니다.


Java의 split 메소드와 같은 기능을 구현할때 오라클의 substr함수와 함께 같이 사용될 수 있죠.


오라클 문서에서 설명하는 instr함수에 대한 정의 및 문법은 아래와 같습니다.


The INSTR functions (INSTR, INSTRB, INSTRC, INSTR2, and INSTR4) searches a string for a substring using characters and returns the position in the string that is the first character of a specified occurrence of the substring. The functions vary in how they determine the position of the substring to return.

  • INSTR calculates lengths using characters as defined by the input character set.

  • INSTRB calculates lengths using bytes.

  • INSTRC calculates lengths using Unicode complete characters.

  • INSTR2 calculates lengths using UCS2 code points.

  • INSTR4 calculates lengths using UCS4 code points.

반환값

A nonzero INTEGER when the search is successful or 0 (zero) when it is not.


문법 

{INSTR | INSTRB | INSTRC | INSTR2 | INSTR4} (string , substring [, position [, occurrence]])


그럼 간단한 예제를 한번 보시죠.


abc.def.ghi.jkl 이라는 패키지명이 있다고 해봅시다.


이 패키지명에서 abc.def ( 두번째 depth 까지)만 추출해내고 싶은데 그러려면 substr을 생각하실 수도 있겠죠.


select substr(packageNm, 1, 7) from ClassTable;


이렇게 하면 결과는 abc.def 가 나올 것입니다.


하지만 만약 패키지명이 3글자.3글자 형태가 아니면 어떻게 될까요?


a.b.c.d.e.f 라는 패키지명을 위처럼 자르면 a.b.c.d 라고 잘려서 나오겠죠?


두번째 depth가 아니라 7번째까지 출력이 되버리겠군요.


이때 instr 함수를 사용을 합니다.


select substr( packageNm, 1, instr( packageNm, '.', 1, 2) - 1 ) ) from ClassTable;


이렇게 함수를 써줍니다.


instr( packageNm, '.', 1, 2 ) 라는 부분은 packageNm이라는 스트링을 '.' (마침표)로 구분을 짓고 1번째 인덱스에서 시작해서 2번째 마침표가 나오는 인덱스를 반환을 합니다. 그러면 마침표가 있는 인덱스가 나오기 때문에 -1을 해준 값을 substr함수의 length에 넣어주면 두번째 depth까지 substr한 결과가 나오게 됩니다.

SQL 커맨드라인에다가 2줄짜리 쿼리문을 한참 치고서 실행했더니 오타가 나서 다시 쳐야한다면???


OMG !!!!!!!!!!


이런 경우를 대비해서 오라클은 SQL 에디터를 제공해준다. 그런데 기본적으로 제공해주는게 뭔진 몰라도 불편하다.


좀더 편하게 하자면 우리가 유닉스 환경에서 자주 사용하는 vi 에디터를 SQL 기본 에디터로 설정해서 사용할 수 있는데


이 기본 에디터는 _editor 라는 변수안에 들어가있다.


SQL > define _editor = vi  


위 명령어를 실행하면 다음부터는 ed라는 명령어를 이용해서 방금 쳤던 명령어를 vi에디터 모드에서 다시 보여준다.


짱이다.

DB작업을 하다가보면 내 계정에 어떤 권한이 있는지 확인해야할 때가 있다.

권한자체가 없으면 작업자체가 안될 수도 있으니까 말이다.

아래 쿼리문은 현재 접속한 계정의 권한을 보여준다.


select * from user_sys_privs;



user_sys_privs외에도 권한과 관련된 다양한 테이블 또는 뷰(view)들이 있다. 아래는 그 테이블들의 목록이다.

각 테이블들이 어떠한 정보를 가지고 있는지는 한번 보면서 확인해보길 바란다.



ALL_COL_PRIVS
ALL_COL_PRIVS_MADE
ALL_COL_PRIVS_RECD
ALL_REPGROUP_PRIVILEGES
ALL_TAB_PRIVS
ALL_TAB_PRIVS_MADE
ALL_TAB_PRIVS_RECD


USER_AQ_AGENT_PRIVS
USER_COL_PRIVS
USER_COL_PRIVS_MADE
USER_COL_PRIVS_RECD
USER_REPGROUP_PRIVILEGES

TNAME
------------------------------
USER_ROLE_PRIVS
USER_SYS_PRIVS
USER_TAB_PRIVS
USER_TAB_PRIVS_MADE
USER_TAB_PRIVS_RECD


💻 Programming/Oracle 11g

[Oracle/SQL] merge into

MERGE INTO bonuses b
USING (
  SELECT employee_id, salary, dept_no
  FROM employee
  WHERE dept_no =20) e
ON (b.employee_id = e.employee_id)
WHEN MATCHED THEN
  UPDATE SET b.bonus = e.salary * 0.1
  DELETE WHERE (e.salary < 40000)
WHEN NOT MATCHED THEN
  INSERT (b.employee_id, b.bonus) VALUES (e.employee_id, e.salary * 0.05) WHERE (e.salary > 40000);



----------------------------------------------------


MERGE INTO bonuses b
USING dual e
ON (b.employee_id = ? )
WHEN MATCHED THEN
  UPDATE SET b.bonus = e.salary * 0.1
WHEN NOT MATCHED THEN
  INSERT (b.employee_id, b.bonus) VALUES (e.employee_id, e.salary * 0.05) WHERE (e.salary > 40000);


💻 Programming/Oracle 11g

[Oracle/SQL] 특정 사용자의 권한 조회

사용자계정이 SAMPLE 인 사용자의 권한을 조회하려면 아래와 같이 하시면 됩니다.

select privilege
from dba_sys_privs
where grantee='SAMPLE'
order by 1;

SQL FOREIGN KEY Constraint on ALTER TABLE

- 외래키 추가하기

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders
ADD FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)


- 외래키 이름 지정해주기

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)


To DROP a FOREIGN KEY Constraint

- 외래키 삭제하기 


MySQL:

ALTER TABLE Orders
DROP FOREIGN KEY fk_PerOrders

SQL Server / Oracle / MS Access:

ALTER TABLE Orders
DROP CONSTRAINT fk_PerOrders


프로젝트를 진행하다 보면 테이블 모델링을 수정해야 할 때가 있다. 이런 저런 추가요구가 들어오면 말이다.

 

그럴 때는 간단하게 SQL 한문장으로 후딱 해치워 버리면 된다.

 

§ 아래는 테이블에 하나의 컬럼을 추가로 만들어 주기위한 SQL문이다.

 

ALTER TABLE table_name ADD column_name datatype

 

§ 테이블에서 필요없는 컬럼을 삭제하려면 아래와 같은 명령어를 사용하면 된다.

 

ALTER TABLE table_name DROP COLUMN column_name

§ 또한 특정 컬럼의 데이타 타입을 변경하려면 아래와 같은 명령어를 사용하면 된다.

Oracle 10G and later: ALTER TABLE table_name MODIFY column_name datatype




§ 오라클이 아닌 다른 데이타베이스 시스템의 경우 아래와 같이 사용하면 된다.

SQL Server / MS Access:

ALTER TABLE table_name ALTER COLUMN column_name datatype

My SQL / Oracle:

ALTER TABLE table_name MODIFY COLUMN column_name datatype


자 오늘은 concat()과 listagg()에 대해서 알아보도록 하겠습니다.

 

DB에서 정보를 추출할 때 여러줄(리스트 형태)로 나오는 것들을 한줄로 합쳐서 뽑아내고 싶거나  

 

한 줄에 여러 필드들이 있을때 이 필드들을 모두 합쳐서 한줄의 스트링으로 뽑아내고 싶을 때가 있을거에요.

 

예를들면 EMP테이블에 한명의 employee만 등록이 되어있다고 가정합시다.

이때 이 사람의 정보를 emp_nm 과 emp_id를 나눠서 emp객체의 name과 id필드에 뽑아올 수도 있지만 궂이 이걸 하나의 String으로 뽑아내고 싶을때가 있을 수도 있다고 가정하고 -_-ㅋ

 

emp_nm | emp_id

---------------

장군이   |     3

 

이렇게 데이터가 들어있을 때 "3장군이" 라는 스트링을 뽑아오려면 concat을 쓰면 됩니다.

 

select concat( emp_id, emp_nm) from emp; 

 

이제 데이타가 한줄 더 들어와서 두명의 employee가 있다고 가정합시다.

 

emp_nm | emp_id

---------------

장군이   |     3

이쁭이   |     5

 

그리고 이 직원들의 이름을 쉼표로 구분해서 하나의 스트링으로 뽑아내고 싶다고 가정합시다.


"장군이,이쁭이" 이렇게 말이죠.

 

이럴때는 listagg()를 쓰면 됩니다. 아래처럼 말이죠.

 

select listagg(emp_nm, ',') within group ( order by emp_id ) from emp; 

 

listagg(리스트애그)에 대한 자세한 내용은 아래 출처에 있는 주소로 가시면 좀 더 자세한 설명을 보실 수 있습니다.

 

그럼 좋은하루 되세요~ ^_^ 

 

 

 

 

출처 : http://oracle-base.com/articles/misc/string-aggregation-techniques.php ( listagg() )  

 

링크가 break될 것을 우려하여 밑에 위 링크로가면 볼 수 있는 내용을 가져왔습니다. ^^

--------------------------------------------------------------------------------

String Aggregation Techniques

On occasion it is necessary to aggregate data from a number of rows into a single row, giving a list of data associated with a specific value. Using the SCOTT.EMP table as an example, we might want to retrieve a list of employees for each department. Below is a list of the base data and the type of output we would like to return from an aggregate query.

Base Data:

    DEPTNO ENAME
---------- ----------
        20 SMITH
        30 ALLEN
        30 WARD
        20 JONES
        30 MARTIN
        30 BLAKE
        10 CLARK
        20 SCOTT
        10 KING
        30 TURNER
        20 ADAMS
        30 JAMES
        20 FORD
        10 MILLER

Desired Output:

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,FORD,ADAMS,SCOTT,JONES
        30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

This article is based on a thread from asktom.oracle.com and contains several methods to achieve the desired results.

LISTAGG Analystic Function in 11g Release 2

The LISTAGG analytic function was introduced in Oracle 11g Release 2, making it very easy to aggregate strings. The nice thing about this function is it also allows us to order the elements in the concatenated list. If you are using 11g Release 2 you should use this function for string aggregation.

COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

WM_CONCAT Built-in Function (Not Supported)

If you are not running 11g Release 2, but are running a version of the database where the WM_CONCAT function is present, then it is a zero effort solution as it performs the aggregation for you. It is actually an example of a user defined aggregate function described below, but Oracle have done all the work for you.

COLUMN employees FORMAT A50

SELECT deptno, wm_concat(ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,FORD,ADAMS,SCOTT,JONES
        30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

3 rows selected.

Note. WM_CONCAT is an undocumented function and as such is not supported by Oracle for user applications (MOS Note ID 1336219.1). If this concerns you, use a User-Defined Aggregate Function described below.

User-Defined Aggregate Function

The WM_CONCAT function described above is an example of a user-defined aggregate function that Oracle have already created for you. If you don't want to use WM_CONCAT, you can create your own user-defined aggregate function as described at asktom.oracle.com.

CREATE OR REPLACE TYPE t_string_agg AS OBJECT
(
  g_string  VARCHAR2(32767),

  STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
    RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                       value  IN      VARCHAR2 )
     RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                         returnValue  OUT  VARCHAR2,
                                         flags        IN   NUMBER)
    RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                     ctx2  IN      t_string_agg)
    RETURN NUMBER
);
/
SHOW ERRORS


CREATE OR REPLACE TYPE BODY t_string_agg IS
  STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
    RETURN NUMBER IS
  BEGIN
    sctx := t_string_agg(NULL);
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                       value  IN      VARCHAR2 )
    RETURN NUMBER IS
  BEGIN
    SELF.g_string := self.g_string || ',' || value;
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                         returnValue  OUT  VARCHAR2,
                                         flags        IN   NUMBER)
    RETURN NUMBER IS
  BEGIN
    returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');
    RETURN ODCIConst.Success;
  END;

  MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                     ctx2  IN      t_string_agg)
    RETURN NUMBER IS
  BEGIN
    SELF.g_string := SELF.g_string || ',' || ctx2.g_string;
    RETURN ODCIConst.Success;
  END;
END;
/
SHOW ERRORS


CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2)
RETURN VARCHAR2
PARALLEL_ENABLE AGGREGATE USING t_string_agg;
/
SHOW ERRORS

The aggregate function is implemented using a type and type body, and is used within a query.

COLUMN employees FORMAT A50

SELECT deptno, string_agg(ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,FORD,ADAMS,SCOTT,JONES
        30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD

3 rows selected.

Specific Function

One approach is to write a specific function to solve the problems. The get_employees function listed below returns a list of employees for the specified department.

CREATE OR REPLACE FUNCTION get_employees (p_deptno  in  emp.deptno%TYPE)
  RETURN VARCHAR2
IS
  l_text  VARCHAR2(32767) := NULL;
BEGIN
  FOR cur_rec IN (SELECT ename FROM emp WHERE deptno = p_deptno) LOOP
    l_text := l_text || ',' || cur_rec.ename;
  END LOOP;
  RETURN LTRIM(l_text, ',');
END;
/
SHOW ERRORS

The function can then be incorporated into a query as follows.

COLUMN employees FORMAT A50

SELECT deptno,
       get_employees(deptno) AS employees
FROM   emp
GROUP by deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,JONES,SCOTT,ADAMS,FORD
        30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

To reduce the number of calls to the function, and thereby improve performance, we might want to filter the rows in advance.

COLUMN employees FORMAT A50

SELECT e.deptno,
       get_employees(e.deptno) AS employees
FROM   (SELECT DISTINCT deptno
        FROM   emp) e;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,JONES,SCOTT,ADAMS,FORD
        30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
        
3 rows selected.

Generic Function using Ref Cursor

An alternative approach is to write a function to concatenate values passed using a ref cursor. This is essentially the same as the previous example, except that the cursor is passed in making it generic, as shown below.

CREATE OR REPLACE FUNCTION concatenate_list (p_cursor IN  SYS_REFCURSOR)
  RETURN  VARCHAR2
IS
  l_return  VARCHAR2(32767); 
  l_temp    VARCHAR2(32767);
BEGIN
  LOOP
    FETCH p_cursor
    INTO  l_temp;
    EXIT WHEN p_cursor%NOTFOUND;
    l_return := l_return || ',' || l_temp;
  END LOOP;
  RETURN LTRIM(l_return, ',');
END;
/
SHOW ERRORS

The CURSOR function is used to allow a query to be passed to the function as a ref cursor, as shown below.

COLUMN employees FORMAT A50

SELECT e1.deptno,
       concatenate_list(CURSOR(SELECT e2.ename FROM emp e2 WHERE e2.deptno = e1.deptno)) employees
FROM   emp e1
GROUP BY e1.deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,JONES,SCOTT,ADAMS,FORD
        30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

Once again, the total number of function calls can be reduced by filtering the distinct values, rather than calling the function for each row.

COLUMN employees FORMAT A50

SELECT deptno,
       concatenate_list(CURSOR(SELECT e2.ename FROM emp e2 WHERE e2.deptno = e1.deptno)) employees
FROM   (SELECT DISTINCT deptno
        FROM emp) e1;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,JONES,SCOTT,ADAMS,FORD
        30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES

3 rows selected.

ROW_NUMBER() and SYS_CONNECT_BY_PATH functions in Oracle 9i

An example on williamrobertson.net uses the ROW_NUMBER() and SYS_CONNECT_BY_PATH functions to achieve the same result without the use of PL/SQL or additional type definitions.

SELECT deptno,
       LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,','))
       KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees
FROM   (SELECT deptno,
               ename,
               ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr,
               ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev
        FROM   emp)
GROUP BY deptno
CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno
START WITH curr = 1;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

COLLECT function in Oracle 10g

An example on oracle-developer.net uses the COLLECT function in Oracle 10g to get the same result. This method requires a table type and a function to convert the contents of the table type to a string. I've altered his method slightly to bring it in line with this article.

CREATE OR REPLACE TYPE t_varchar2_tab AS TABLE OF VARCHAR2(4000);
/

CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab  IN  t_varchar2_tab,
                                          p_delimiter     IN  VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS
  l_string     VARCHAR2(32767);
BEGIN
  FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP
    IF i != p_varchar2_tab.FIRST THEN
      l_string := l_string || p_delimiter;
    END IF;
    l_string := l_string || p_varchar2_tab(i);
  END LOOP;
  RETURN l_string;
END tab_to_string;
/

The query below shows the COLLECT function in action.

COLUMN employees FORMAT A50

SELECT deptno,
       tab_to_string(CAST(COLLECT(ename) AS t_varchar2_tab)) AS employees
FROM   emp
GROUP BY deptno;
       
    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,JONES,SCOTT,ADAMS,FORD
        30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
        
3 rows selected.




이상입니다!!!


아...슬프도다....이 에러의 원인을 찾느라 얼마나 헤맸던지...

쿼리문의 인자로 들어가는 녀석들이 13개이고 이 쿼리문을 스트링 + 스트링 형식으로 묶어놨는데 콤마가 빠진 이유로 변수명이 부적합하다는 오류를 찍어대니 이거 원인을 어떻게 찾으라고.!!!!!!

 

구글링 해보니......

 

콤마가 빠져도 저런 오류를 뿌린다는 것...

 

잘 보니 인자가 많아서 줄바꿈할 때 쉼표를 하나 빼먹었던 것.


1. 나 자신이 가지고 있는 테이블을 조회하고 싶다면 

select * from user_tables;

 

2. dba권한을 가지고 있는 사용자가 다른 사용자의 테이블을 조회하고 싶다면

select * from dba_tables where owner='사용자ID'; 


💻 Programming/Oracle 11g

ORA-00917: 누락된 콤마

말그대로 콤마가 누락되었다는 얘기다.  

하지만!!!!! 때로는 엉뚱한 실수에 엉뚱한 오류가 나기도 한다.

 

내가 저 에러메시지를 본것은 아래와 같은 설정을 했을때다.

스프링 기반 웹앱을 만들고 xml파일에 쿼리문을 넣었는데....

 

================================================ 

<insert id="add">
        insert into
            테이블명
        values(
            column1 = #{col1, jdbcType=VARCHAR}
            ,​column2 = #{col2, jdbcType=VARCHAR}
            ,​column3 = #{col3, jdbcType=VARCHAR}
        )
</insert> 

================================================

자, 여기서 테이블명과 컬럼명은 임의로 써넣었다. 물론 실제 소스에서는 실제 테이블명과 컬럼명이 들어가있다. 이 테이블에는 세개의 컬럼( column1, column2, column3 )이 있다고 가정한다. 

 

이 코드에서 왜 누락된 콤마 누락 에러가 발생했는지 찾았는가???

 

이 코드에는 콤마가 누락된 것이 아니다. Insert 문의 형식자체가 틀렸다.

위 코드는 아래와 같이 바뀌어야 한다.

 

        insert into
            테이블명
        values(
            #{col1, jdbcType=VARCHAR}
            ,​#{col2, jdbcType=VARCHAR}
            ,​#{col3, jdbcType=VARCHAR}
        ) 

 

에러메시지만보고 콤마가 어디가 누락됐다는거지? 라는 생각을 가지고 오류를 찾으려한다면 하루종일을 허비해도 못찾을 것이다.

 

당신의 지식에 조금이나마 도움이 됐기를 바라며 글을 마친다.... 


💻 Programming/Oracle 11g

[SQL] Truncate vs Drop vs Delete

DELETE

The DELETE command is used to remove rows from a table. A WHERE clause can be used to only remove some rows. If no WHERE condition is specified, all rows will be removed. After performing a DELETE operation you need to COMMIT or ROLLBACK the transaction to make the change permanent or to undo it. Note that this operation will cause all DELETE triggers on the table to fire.

 

TRUNCATE

TRUNCATE removes all rows from a table. The operation cannot be rolled back and no triggers will be fired. As such, TRUCATE is faster and doesn't use as much undo space as a DELETE.

 

DROP

The DROP command removes a table from the database. All the tables' rows, indexes and privileges will also be removed. No DML triggers will be fired. The operation cannot be rolled back.  

 

 

* DROP and TRUNCATE are DDL commands, whereas DELETE is a DML command. Therefore DELETE operations can be rolled back (undone), while DROP and TRUNCATE operations cannot be rolled back.


ALTER TABLE [DB명] MODIFY([컬럼명] NOT NULL);

 

간단하다!!!!!!!!!!

 

화이팅!!! 


오라클에서 한번에 여러개의 레코드를 insert하려면 아래와 같은 방식을 사용할 수 있다.

 

 

INSERT ALL
INTO 테이블명 ( column_1, column_2 ) VALUES ( value_1,  value_2)

INTO 테이블명 ( column_1, column_2 ) VALUES ( value_3,  value_4)

SELECT 1 FROM DUAL


💻 Programming/Oracle 11g

[SQL] COUNT(*) 와 COUNT(1)

SQL에서 특정 데이타의 개수를 뽑아낼 때 사용하는 COUNT()함수가 있다.

뭐 데이터의 양이 적은 경우에는 속도차이를 느끼지 못하겠지만 데이터의 양이 많은 DB를 사용하는 경우에는 어떨까...????하는 의문이 생긴다.

 

아직 확실한 테스트를 해보지는 않았다. 그저 인터넷에서 찾은 정보에 의하면....

 

영어에 약한분들은 Example부분은 그냥 건너뛰고 Tip: Performance......부분을 보면된다. 

================================================================= 

Example - Using SQL GROUP BY Clause

In some cases, you will be required to use the SQL GROUP BY clause with the SQL COUNT function.

For example, you could use the SQL COUNT function to return the name of the department and the number of employees (in the associated department) that make over $25,000 / year.

SELECT department, COUNT(*) AS "Number of employees"
FROM employees
WHERE salary > 25000
GROUP BY department;

Because you have listed one column in your SQL SELECT statement that is not encapsulated in the SQL COUNT function, you must use the SQL GROUP BY clause. The department field must, therefore, be listed in the GROUP BY section.

TIP: Performance Tuning with SQL COUNT

Since the SQL COUNT function will return the same results regardless of what NOT NULL field(s) you include as the SQL COUNT function parameters (ie: within the brackets), you can change the syntax of the SQL COUNT function to COUNT(1) to get better performance as the database engine will not have to fetch back the data fields.

For example, based on the example above, the following syntax would result in better performance:

SELECT department, COUNT(1) AS "Number of employees"
FROM employees
WHERE salary > 25000
GROUP BY department;

Now, the SQL COUNT function does not need to retrieve all fields from the employees table as it had to when you used the COUNT(*) syntax. It will merely retrieve the numeric value of 1 for each record that meets your criteria.

======================================================================== 

 

 

 

출처 :Http://www.techonthenet.com/sql/count.php


💻 Programming/Oracle 11g

[SQL] CONNECT BY , START WITH

계층 구조를 가진 데이타를 뽑아보자!!!!

한 테이블 Table_1이 있다.

이 테이블은 objectID필드와 parentObjectID 필드를 갖고 있다.

두 필드에는 OBJECT_X(X는 정수형 숫자)형식의 데이터가 들어있다. 

또, OBJECT_1이 하위 OBJECT_2를 가지고 OBJECT_2가 또 하위 OBJECT_3을 가진다고 가정하자. (OBJECT_2는 OBJECT_1의 자식 OBJECT라고 생각하면된다.)

여러 다른 OBJECT_X 형식의 데이터들이 테이블 내에 많이 있다고 가정하자.

 

이때 CONNECT BY와 START WITH를 이용하여 OBJECT_2와 그 상위, 또 그 상위, 또 그 상위...쭈우욱 해서 OBJECT_2를 갖는 최상위 OBJECT까지 계층구조로 뽑아내기 위해서는 아래와 같이 하면 된다.

 

SELECT *

FROM Table_1

CONNECT BY PRIOR objectID = parentObjectID

START WITH objectID = 'OBJECT_2'

 

------- 

 파란색 조건부의 순서가 바뀌면 결과도 바뀌므로 주의하자.!!!!