①TO_CHAR(number\date,['fmt']) : 숫자 또는 날짜값을 fmt 형식 모델을 사용하여 VARCHAR2 문다스트링으로 바꾸어 줍니다. 


②TO_NUMBER(char) : 숫자를 포함하고 있는 문자 스트링을 숫자로 전환합니다. 


③TO_DATE(char,['fmt']) : 날짜를 나타내는 문자스트링을 명시한 fmt에 따라 날짜값으로 바꾸어 줍니다. fmt를 생략시 형식은 DD-MON-YY가 됩니다.



NVL(column, null인경우 값)

NVL2(column, null이아닌경우, null인경우)

NVLIF(비교1, 비교2) : 동일하면 null, 아니면 첫번째표현식



CASE     WHEN 조건1 THEN 조건만족시 값1

         WHEN 조건2 THEN 조건만족시 값2

         WHEN 조건3 THEN 조건만족시 값3

         ...

         ELSE 0

END 결과컬럼명 



DECODE(column, 조건1, 값1, 

               조건2, 값2,

      조건3, 값3) 결과컬럼명 




rowid : 주소로서 row가 실제로 저장되어있는 공간, 테이블내의 고유주소

rownum : 출력되어지는 순서 

      - 실제칼럼이 아닌 가상의 칼럼

      - 영구적으로 할당된 숫자가 아니다. 

      - 조건절 처리후 sort,집계 수행 이전에 할당, 할당후 증가 


첫번째row를 만났을때 rownum=5 라는 조건을 건다면 false 




//union

select employee_id, first_name, salary, '직원'

from employees

union

select department_id, department_name, 0, '부서'

from departments

order by 4


//rollup

select department_id, job_id, sum(salary)

from employees

group by rollup (department_id, job_id)

order by 1,2


//cube

select department_id, job_id, sum(salary)

from employees

group by cube (department_id, job_id)

order by 1,2


'Computer > DB' 카테고리의 다른 글

SQL if  (0) 2014.09.01
SQL 문자 관련함수  (0) 2014.09.01
SQL trigger 예제  (0) 2014.09.01
SQL join 관련  (0) 2014.09.01
SQL Insert select update delete  (0) 2014.09.01



CREATE TABLE ORDER_LIST (

ORDER_DATE CHAR(8) NOT NULL,

PRODUCT VARCHAR2(10) NOT NULL,

QTY NUMBER NOT NULL,

AMOUNT NUMBER NOT NULL);



CREATE TABLE SALES_PER_DATE (

SALE_DATE CHAR(8) NOT NULL,

PRODUCT VARCHAR2(10) NOT NULL,

QTY NUMBER NOT NULL,

 AMOUNT NUMBER NOT NULL);


CREATE OR REPLACE Trigger SUMMARY_SALES

AFTER INSERT

 ON ORDER_LIST

 FOR EACH ROW

DECLARE

 o_date ORDER_LIST.order_date%TYPE;

 o_prod ORDER_LIST.product%TYPE;

 BEGIN

  o_date := :NEW.order_date;

  o_prod := :NEW.product;

  UPDATE SALES_PER_DATE

  SET qty = qty + :NEW.qty,

  amount = amount + :NEW.amount

  WHERE sale_date = o_date

   AND product = o_prod;

 

 if SQL%NOTFOUND then

   INSERT INTO SALES_PER_DATE

   VALUES(o_date, o_prod, :NEW.qty, :NEW.amount);

 end if;

 END;

  /



INSERT INTO ORDER_LIST VALUES('20120901', 'MONOPACK', 10, 300000);

commit;



INSERT INTO ORDER_LIST VALUES('20120901','MULTIPACK',10,300000);

select~~

rollback;








 



'Computer > DB' 카테고리의 다른 글

SQL 문자 관련함수  (0) 2014.09.01
SQL nvl union rollup cube  (0) 2014.09.01
SQL join 관련  (0) 2014.09.01
SQL Insert select update delete  (0) 2014.09.01
SQL hr 계정 풀기  (0) 2014.09.01

desc departments //칼럼정보보기


select first_name, hire_date, salary, employees.department_id, department_name

from employees, departments

where employees.department_id = departments.department_id


select first_name, hire_date, salary, department_id, department_name

from employees join departments using (department_id)


select e.first_name, e.hire_date, e.salary, e.department_id, d.department_name

from employees e join departments d on e.department_id = d.department_id


select e.ename, e.hiredate, e.sal, s.grade, s.losal, s.hisal

from emp e, salgrade s

where e.sal between s.losal and s.hisal


select e.first_name, e.hire_date, e.salary, j.job_id, j.job_title, j.min_salary, j.max_salary

from employees e, jobs j

where e.job_id = j. job_id





select first_name, hire_date, department_name

from employees e full join departments d


select e.first_name, e.hire_date, d.department_name

from employees e left join departments d

on e.department_id = d.department_id


select e.first_name, j.job_title

from employees e right join jobs j

on e.job_id=j.job_id


select * from jobs


select e.first_name, e.hire_date, nvl(d.department_name, '부서없음')

from employees e left join departments d

on e.department_id = d.department_id


select e.first_name, e.hire_date, nvl2(d.department_name, d.department_name||'**', '부서없음')

from employees e left join departments d

on e.department_id = d.department_id




//natural 조인 자동으로해줌

select emp.ename, dept.dname

from dept natural join emp


select emp.ename, dept.dname

from dept, emp

where dept.deptno = emp.deptno


//Cross 조인 다 곱해서 해줌

select e.first_name, d.department_name

from employees e, departments d


select e.first_name, d.department_name

from employees e cross join departments d

'Computer > DB' 카테고리의 다른 글

SQL nvl union rollup cube  (0) 2014.09.01
SQL trigger 예제  (0) 2014.09.01
SQL Insert select update delete  (0) 2014.09.01
SQL hr 계정 풀기  (0) 2014.09.01
SQL Date 관련 함수  (0) 2014.09.01


//Insert

insert into emp

values (2, '미처','CLERK', 7782, sysdate, 5000, 150, 30)


//select 이용해서 insert

insert into emp(empno, ename)

select employee_id, substr(first_name,1,10)

from employees

where department_id = 110


//update

update emp

set sal=600,

    deptno = 30

where empno in (205, 206)


rollback;



update emp

set sal = ( select avg(sal) from emp)

 where empno =1

commit



//Delete

delete from emp

where empno = 1

commit


delete from emp

where empno in (select employee_id from employees)

commit

'Computer > DB' 카테고리의 다른 글

SQL trigger 예제  (0) 2014.09.01
SQL join 관련  (0) 2014.09.01
SQL hr 계정 풀기  (0) 2014.09.01
SQL Date 관련 함수  (0) 2014.09.01
SQL Injection 방어기법  (0) 2014.08.21

Oracle 

SQL> conn system/root

Connected.

SQL> alter user hr

      identified by hr

      account unlock;

SQL>conn hr/hr



'Computer > DB' 카테고리의 다른 글

SQL join 관련  (0) 2014.09.01
SQL Insert select update delete  (0) 2014.09.01
SQL Date 관련 함수  (0) 2014.09.01
SQL Injection 방어기법  (0) 2014.08.21
SQL 원격 데이터베이스 접속  (0) 2014.08.13

select sysdate from dual

select * from dual

alter session set nls_date_format='DD-MON-YY';



select (sysdate - to_date('02/25/1989'))/365 from dual // 몇년 살앗니


select months_between(sysdate,to_date('02/25/1989'))/12 from dual //몇달 살앗니


select add_months(sysdate,3) from dual //3달 더하기


select next_day(sysdate, 'mon') from dual //다가오는 월요일


select last_day(sysdate) from dual // 이번달 마지막


select round(sysdate, 'year') from dual //년도 반올림 6월이후기 때문에 15년이됨




select 

   round(sysdate, 'YYYY') 

               "년-6월이후",

   round(sysdate, 'MM') 

               "월-16일이후",

   round(sysdate, 'DD') 

               "일-12이후",

   round(sysdate, 'day') 

               주-수요일이후,

   trunc(sysdate, 'YYYY') t1,

   trunc(sysdate, 'MM') t2,

   trunc(sysdate, 'DD') t3,

   trunc(sysdate, 'day') t4

 from dual;



'Computer > DB' 카테고리의 다른 글

SQL Insert select update delete  (0) 2014.09.01
SQL hr 계정 풀기  (0) 2014.09.01
SQL Injection 방어기법  (0) 2014.08.21
SQL 원격 데이터베이스 접속  (0) 2014.08.13
SQL Group by  (0) 2014.08.13
■ 보호 대책
 

(1) 일반 대책

-데이터베이스와 연동을 하는 스크립트의 모든 파라미터들을 점검하여 사용자의 입력 값이 SQL injection을 발생시키지 않도록 수정한다.
 

-사용자 입력이 SQL injection을 발생시키지 않도록 사용자 입력 시 특수문자(' " / \ ; : Space -- +등)가 포함되어 있는지 검사하여 허용되지 않은 문자열이나 문자가 포함된 경우에는 에러로 처리한다.
 

-SQL 서버의 에러 메시지를 사용자에게 보여주지 않도록 설정한다. 공격자는 리턴 되는 에러 메시지에 대한 분석을 통하여 공격에 성공할 수 있는 SQL Injection 스트링을 알아낼 수 있다. 따라서 SQL 서버의 에러 메시지를 외부에 제공하지 않도록 한다.
 

-웹 애플리케이션이 사용하는 데이터베이스 사용자의 권한을 제한한다. 가능하면 일반 사용자 권한으로는 모든 system stored procedures에 접근하지 못하도록 하여 웹 애플리케이션의 SQL Injection 취약점을 이용하여 데이터베이스 전체에 대한 제어권을 얻거나 데이터베이스를 운용중인 서버에 대한 접근이 불가능하도록 한다.
 

-php.ini 설정 변경
  : php.ini 설정 중 magic_quotes_gpc 값을 On으로 설정한다.

; Magic quotes
;

; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = On  ; Off에서 On으로 변경한다.

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off

; Use Sybase-style magic quotes (escape ' with '' instead of \').
magic_quotes_sybase = Off
 
 
 

■ 개발 언어별 대책
-사용자로부터 입력받은 변수로 SQL 쿼리 구문을 생성하는 CGI는 입력받은 변수를 체크하거나 변경하는 로직을 포함하고 있어야 한다.
-입력받은 변수와 데이터 베이스 필드의 데이터형을 일치 시켜야 하고, 사용 중인 SQL 구문을 변경시킬 수 있는 특수문자가 포함되어 있는지 체크해야 한다.
-검색 부분과 같이 클라이언트로부터 생성된 SQL 구문을 받는 부분이 있다면 이를 제거해야 한다.
 
□ ASP
-취약한 SQL Injection 예제
prodId = Request.QueryString("productId")
Set conn = server.createObject("ADODB.Connection")
Set rs = server.createObject("ADODB.Recordset")

query = "select prodName from products where id = " & prodId

conn.Open "Provider=SQLOLEDB; Data Source=(local);
Initial Catalog=productDB; User Id=dbid; Password="
rs.activeConnection = conn
rs.open query

If not rs.eof Then
response.write "제품명" & rs.fields("prodName").value
Else
response.write "제품이 없습니다"
End If
 
 

-안전한 SQL Injection 예제

prodId = Request.QueryString("productId")
prodId = replace(prodId, "'", "''")' 특수문자 제거
prodId = replace(prodId, ";", "")
set conn = server.createObject("ADODB.Connection")
set rs = server.createObject("ADODB.Recordset")
query = "select prodName from products where id = " & prodId
conn.Open "Provider=SQLOLEDB; Data Source=(local);
Initial Catalog=productDB; User Id=dbid; Password="
rs.activeConnection = conn
rs.open query
If not rs.eof Then
response.write "제품명" & rs.fields("prodName").value
Else
response.write "제품이 없습니다"
End If
 
 

□ PHP
-addslashes() 함수 사용
  : 사용자가 입력하는 값들($_GET, $_POST)을 모두 addslashes() 함수를 이용하여 처리하여 준다.

addslashes()
용도 : DB Query와 같이 인용된 부분앞에 역슬래쉬를 붙여서 반환한다. 해당 문자에는 작은 따옴표, 큰 따옴표, 역슬래쉬, NULL이 있다. SQL Injection 공격을 위해서 사용한다.
- 적용 가능한 PHP : PHP 3 이상
 
 

-취약한 SQL Injection 예제

$query = "SELECT id, password, username FROM user_table WHERE id='$id'";// 사용자로부터 입력받은 id 값을 사용자 table에서 조회
$result = OCIParse($conn, $query);
if (!OCIExecute($result)) 
echo "<META http-equiv=\"refresh\" content=\"0;URL=http://victim.com\">";// 메인 페이지로 redirect

OCIFetchInto($result, &$rows);
... 중략 ...
 
 
-안전한 SQL Injection 예제

$query = sprintf("SELECT id,password,username FROM user_table WHERE id='%s';",addslashes($id));
// id변수를 문자형으로 받고, id변수의 특수문자를 일반문자로 변환한다.

// @ 로 php 에러 메시지를 막는다.
$result = @OCIParse($conn, $query);
if (!@OCIExecute($result)) 
error("SQL 구문 에러");
exit;

@OCIFetchInto($result,&$rows);
... 중략 ...
 
 

□ JSP
-취약한 SQL Injection 예제

String sql="SELECT*FROM user_table"+"WHERE id=" + response.getParameter("id")
+ " AND password = " + response.getParameter("password");

Class.forName("org.gjt.mm.mysql.Driver");
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);

stmt = conn.createStatement();
rs = stmt.executeQuery(query);

while(rs.next()) 
 
 

-안전한 SQL Injection 예제

String sql = "SELECT*FROM user_table"+"WHERE id = ?"+"AND password = ?";
ResultSet rs = null;
PreparedStatement pstmt = null;
try 
conn = DBManager.getConnection();
pstmt = conn.prepareStatement(sql);

pstmt.setString(1, request.getParameter("id"));
pstmt.setString(2, request.getParameter("password"));

rs = pstmt.executeQuery();


'Computer > DB' 카테고리의 다른 글

SQL Insert select update delete  (0) 2014.09.01
SQL hr 계정 풀기  (0) 2014.09.01
SQL Date 관련 함수  (0) 2014.09.01
SQL 원격 데이터베이스 접속  (0) 2014.08.13
SQL Group by  (0) 2014.08.13

cmd창

sqlplus hr/hr@127.0.0.1:1521/xe



세팅

set linesize 300

set pagesize 40

'Computer > DB' 카테고리의 다른 글

SQL Insert select update delete  (0) 2014.09.01
SQL hr 계정 풀기  (0) 2014.09.01
SQL Date 관련 함수  (0) 2014.09.01
SQL Injection 방어기법  (0) 2014.08.21
SQL Group by  (0) 2014.08.13
출처 

머릿말
오늘은 GROUP BY문에 대해서 설명을 하도록 하겠습니다.
간단한 사이트를 개발할 때는, 단순히 INSERT, UPDATE, SELECT문만으로 구현이 가능합니다.
하지만, 조금만 사이트의 규모가 커지면, GROUP BY문을 쉴새없이 사용하게 됩니다.
GROUP BY를 제대로 사용하지 못한다면, 개발자로서 한 걸음 나가는데, 큰 무리가 있습니다.
GROUP BY의 원리와 사용법을 제대로 익힐 수 있는 시간이 되기를 기대하며 시작하도록 하겠습니다.


Lesson 4 : GROUP BY
GROUP BY문은 동일한 값을 가진 데이터를 집계해서 조회하고자 할 때 사용하는 문장이다.
조회, 분석용 SQL에서 가장 많이 사용되는 구문이다.
초급 개발자들을 보면, GROUP BY문을 사용할 때, 이렇게 쓰는건가, 저렇게 쓰는건가 하면서 머뭇거리면서 사용하는 경우가 종종 있다. 절대 그런일이 없도록 심도있게 공부하고 익히기를 바란다.

작성방법
SELECT  T1.REGION_GD
FROM    SQL_TEST.CD_REGION T1
GROUP BY T1.REGION_GD
- 집계할 컬럼을 GROUP BY절 뒤에 적어준다.
- SELECT절에는 GROUP BY에 명시된 컬럼만 사용할 수 있다.
- GROUP BY는 WHERE절과 ORDER BY절 사이에 위치한다.

기초이해
-- 일반 SELECT문장
SELECT  T1.STORE_ID
        ,T1.REGION_CD
FROM    SQL_TEST.MA_STORE T1
-- REGION_CD별 데이터를 GROUP BY
SELECT  T1.REGION_CD
FROM    SQL_TEST.MA_STORE T1
GROUP BY T1.REGION_CD
- 조회되는 데이터의 동일한 값들을 하나의 데이터로 집계하는 문장.
- 아래 그림이 GROUP BY의 기본을 이해하는데 더욱 도움을 줄 것이다.
- GROUP BY REGION_CD를 한 경우 SELECT절에는 STORE_ID를 출력할 수 없다.


여러 컬럼의 집계
- 여러 개의 컬럼에 대해서도 GROUP BY의 사용이 가능하다.
SELECT  T1.REGION_CD
        ,T1.STORE_TP
FROM    SQL_TEST.MA_STORE T1
GROUP BY T1.REGION_CD
        ,T1.STORE_TP
- GROUP BY절 뒤에 집계할 컬럼들을 콤마(,)로 구분해서 여러 개 적어준다.
- SELECT절에 컬럼은 GROUP BY에 적은 컬럼들만 올 수 있으며, 순서는 상관 없다.
SELECT  T1.STORE_TP
        ,T1.REGION_CD
FROM    SQL_TEST.MA_STORE T1
GROUP BY T1.REGION_CD
        ,T1.STORE_TP
ORDER BY T1.REGION_CD
        ,T1.STORE_TP


GROUP BY와 집계함수의 사용
- 집계함수는 GROUP BY에 표시된 컬럼들에 대한 집계한 결과값을 만들어 준다.
- GROUP BY에 표시하지 않은 컬럼도 집계함수를 사용하면 SELECT절에 사용이 가능하다.
- 분석용 리포트에서 합계, 데이터의 건수 또는 최대, 최소값을 구하기 위해 많이 사용한다.
SELECT  T1.CALCU_TP
        ,SUM(T1.ORDER_AMT) SUM_ORDER_AMT
FROM    SQL_TEST.HI_ORDER T1
WHERE   T1.ORDER_YMD LIKE '20091001%'
GROUP BY T1.CALCU_TP
- SUM : 데이터의 합계를 구한다.(숫자형 컬럼에만 가능하다.(
- MAX : 최대값을 구한다.
- MIN : 최소값을 구한다.
- COUNT : 데이터의 건수를 구한다.
- AVG : 평균을 구한다.
SELECT  T1.STORE_ID
        ,SUM(T1.ORDER_AMT) SUM_ORDER_AMT
        ,MAX(T1.ORDER_AMT) MAX_ORDER_AMT
        ,MIN(T1.ORDER_AMT) MIN_ORDER_AMT
        ,COUNT(*) CNT_ORDER
FROM    SQL_TEST.HI_ORDER T1
WHERE   T1.ORDER_YMD LIKE '20091001%'
GROUP BY T1.STORE_ID
- 다음 그림을 통해 집계함수를 이해하도록 하자.


GROUP BY : COUNT와 NULL
- COUNT는 데이터의 건수를 집계하는 함수이다.
- GROUP BY를 사용하지 않고 COUNT(*)만 SELECT절에 표시하면, 테이블의 전체건수를 구할 수 있다.
- COUNT(*) 또는 COUNT(컬럼명)으로 사용할 수 있다.
SELECT  COUNT(*)
        ,COUNT(T1.CARD_NO)
FROM    SQL_TEST.HI_ORDER T1
WHERE   T1.ORDER_YMD LIKE '200901%'
- COUNT(*)의 결과는 37948건, COUNT(T1.CARD_NO)의 결과는 15062건이 나왔다.
  (각자의 환경에 따라 결과값은 틀릴 수 있다. 주목할 건, COUNT(*)와 COUNT(T1.CARD_NO)의 결과가 틀리다는 것이다.)
- COUNT(T1.CARD_NO)의 경우는 CARD_NO가 NULL인 경우는 제외하고 COUNT를 수행한다.
- COUNT(*)는 NULL값의 존재 유무 상관없이 카운트된다, 즉 NULL값도 카운트가 1 증가한다.


GROUP BY : COUNT(DISTINCT)
- COUNT집계 함수 안에 DISTINCT를 사용해서, 데이터의 건수가 아닌, 데이터의 종류 수를 알 수 있다.
SELECT  T1.ORDER_YMD
        ,COUNT(*) ORDER_CNT
        ,COUNT(DISTINCT STORE_ID) ORDER_STORE_CNT
FROM    SQL_TEST.HI_ORDER T1
WHERE   T1.ORDER_YMD LIKE '200901%'
GROUP BY T1.ORDER_YMD
ORDER BY T1.ORDER_YMD
- COUNT(DISTINCT)가 발생되는 경우는 많지 않으며, 성능 악화를 발생시킬 수도 있다.
- 최대한 COUNT(DISTINCT)가 발생되지 않도록 테이블이 설계 되어야 하고,
- 아울러, COUNT(DISTINCT)가 발생되지 않도록 사용자 요구사항을 설득하는 것이 필요하다.
- 마지막으로, 최대한 COUNT(DISTINCT)가 발생되지 않도록 SQL을 작성해야 한다.

GROUP BY : ORDER BY에서 집계 함수의 사용
- ORDER BY절에 집계 함수를 사용한다.
SELECT  T1.REGION_CD
        ,COUNT(*) STORE_CNT
FROM    SQL_TEST.MA_STORE T1
GROUP BY T1.REGION_CD
ORDER BY COUNT(*) DESC
- STORE가 많은 REGION_CD부터 출력된다.
- 실제로 분석 시스템에서 이와 같이 집계된 값 기준으로 정렬하는 경우가 많이 있다.

GROUP BY : HAVING절의 사용
- GROUP BY를 통해 집계된 값에 조회 조건을 줄 수 있다.
- GROUP BY가 완료된 결과에 대한 WHERE절이라고 생각할 수 있다.
SELECT  T1.REGION_CD
        ,COUNT(*) STORE_CNT
FROM    SQL_TEST.MA_STORE T1
WHERE   T1.STORE_TP = 'IND'
GROUP BY T1.REGION_CD
HAVING COUNT(*) <= 20
- WHERE졸울 통해 STORE_TP가 IND인 데이터만 찾아낸다.
- GROUP BY를 통해 REGION_CD별로 데이터를 집계한다.
- HAVING절을 통해 STORE카운트가 20이하인 데이터만 조회한다.
- 다음 두 SQL은 동일한 결과를 만들어 내는 SQL이다.
SELECT  T1.REGION_CD
        ,COUNT(*) STORE_CNT
FROM    SQL_TEST.MA_STORE T1
WHERE   T1.STORE_TP = 'IND'
GROUP BY T1.REGION_CD
HAVING T1.REGION_CD IN ('ATL','L.A');
SELECT  T1.REGION_CD
        ,COUNT(*) STORE_CNT
FROM    SQL_TEST.MA_STORE T1
WHERE   T1.STORE_TP = 'IND'
AND     T1.REGION_CD IN ('ATL','L.A')
GROUP BY T1.REGION_CD
- 위의 SQL들은 WHERE절에 조건을 사용하든, HAVING절에 조건을 사용하든 동일한 결과를 조회하는 SQL이다.
- 이와 같은 경우 HAVING조건이 자동으로 WHERE로 변경된다.
- 하지만, 될수 있는한 조건자체를 WHERE절에 적어주도록 한다.
- 경우에 따라 자동 변경이 안될 수 있기 때문이다.


'Computer > DB' 카테고리의 다른 글

SQL Insert select update delete  (0) 2014.09.01
SQL hr 계정 풀기  (0) 2014.09.01
SQL Date 관련 함수  (0) 2014.09.01
SQL Injection 방어기법  (0) 2014.08.21
SQL 원격 데이터베이스 접속  (0) 2014.08.13

+ Recent posts