쿼리 (13)

select 

owner, segment_name, segment_type, sum(bytes)/1024/1024 as MB

from 

dba_segments

where

owner='{username in uppercase}' 

group by owner, segment_name, segment_type order by MB

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


select * from user_constraints;



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;

자 오늘은 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. dba권한으로 모든 테이블을 조회할 경우 : dba_tables

2. 일반 사용자 권한으로 내 소유의 테이블을 조회할 경우 : user_tables

 

아래 예제를 보면

 

SQL > select * from user_tables;

 

를 실행하면 꽤나 긴 페이지를 보게 될 것입니다.  

putty를 이용해서 DB에 접속한 뒤 pagesize와 linesize를 설정하지 않았을 경우 특히 더 길게 나올거에요. 

만약 pagesize와 linesize를 설정하지 않았다면 아래와 같이 실행해보세요.

 

SQL > set pagesize 100

SQL > set linesize 3000

 

위 두 줄을의 내용은 한 페이지에 100 라인이 들어가고 한 라인에 3천개의 문자가 들어간다고 정의하는 것입니다.

 

그리고 다시 select문을 실행시켜보면 그나마 보기좋게 나올 것입니다. 그래도 아직 영 맘에 안들죠? 

위 select문을 실행시키면 테이블명과 해당 테이블이 속해있는 테이블 스페이스명을 시작으로 온갖 속성들의 값이 나올것입니다.  

아래는 user_tables에 어떤 컬럼들이 있는지를 뽑아본 것인데 아래 컬럼중에서 원하는 것만 뽑아서 조회를 하는것이 보이에 훨씬 좋을테니 몇개만 골라서 조회해보세요. 

 

TABLE_NAME                      

TABLESPACE_NAME                 

CLUSTER_NAME                                                                               IOT_NAME                                                                                    

STATUS      

PCT_FREE    

PCT_USED   

INI_TRANS   

MAX_TRANS  

INITIAL_EXTENT  

NEXT_EXTENT  

MIN_EXTENTS  

MAX_EXTENTS  

PCT_INCREASE   

FREELISTS  

FREELIST_GROUPS  

LOG  

B    

NUM_ROWS      

BLOCKS  

EMPTY_BLOCKS   

AVG_SPACE   

CHAIN_CNT  

AVG_ROW_LEN A

VG_SPACE_FREELIST_BLOCKS  

NUM_FREELISTOW_MOVE  

GLO  

USE  

DURATION                                             

SKIP_COR MON CLUSTER_OWNER                                                                               

DEPENDEN  

COMPRESS  

COMPRESS_FOR  

DRO  

REA  

SEG  

RESULT_

💻 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}
        ) 

 

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

 

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


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