IF 문


형식 : if ( 조건문, 참일때 값, 거짓일때 값)

EX)  select member_id, if ( isnull(birthday), '-', birthday ) from member

설명 - 멤버 테이블에서 아이디(member_id) 와 생일을 뽑는데 null 일경우는 - 를 출력, 

      아니면 생일을 출력

 

 

Case 문


형식 :  case (조건 또는 값)

          when 값1 then 표시값

          when 값2 then 표시값

        else 표시값

        end

EX)   select case a when '1' then a when '2' then b else c end from table_name

설명 - a 값이 '1'이면 a, '2' 이면 b, 둘다 아닐경우 c 를 출력

 

 

ifnull문 ( mysql 에서 사용 )


 형식 : ifnull ( 값1, 값2)

EX ) select ifnull ( price, 0 ) from books

설명 - price 값이 Null 이면 0을, Null 이 아니면 price 값을 출력

 

 

isnull문 ( MS-SQL 에서 사용 )


 형식 : ifnull ( 값1, 값2)

EX ) select isnull ( price, 0 ) from books

설명 - price 값이 Null 이면 0을, Null 이 아니면 price 값을 출력

 

 

NVL문 ( Oracle 에서 사용 )


 형식 : NVL ( 값1, 값2) 

EX ) select nvl ( price, 0 ) from books

설명 - price 값이 Null 이면 0을, Null 이 아니면 price 값을 출력




                                                                                                     



%% OPENQUERY : 원격 DB 서버에서 데이터를 가지고 오는 것


-- 원격 서버의 DB (OpenQuery)
-- WHERE 조건은 OpenQuery 안에 넣어서 처리하는 것이 최적화가 쉽다.


Select

SELECT * FROM OPENQUERY([ip], 'SELECT * FROM table WHERE ');


Insert

INSERT OPENQUERY(L_TESTDB, 'SELECT * FROM table WHERE  ') VALUES (1, '홍길동');


Update

UPDATE OPENQUERY(L_TESTDB, 'SELECT * FROM table WHERE ') SET NAME = '홍길동';


Delete

DELETE FROM OPENQUERY(L_TESTDB, 'SELECT * FROM table WHERE ');


-- 로컬 서버의 DB (Linked Server) SELECT * FROM [192.168.0.1].[데이터베이스].dbo.[테이블] WHERE no < 101; -- 로컬 서버의 DB (Linked Server) SELECT * FROM [데이터베이스].dbo.[테이블] WHERE no < 101;



                                                                                                     


%% DECLARE : 쿼리 내에 변수 선언

 Set : 변수 초기화

 Exec : 실행


Declare @strQuery varchar(1024)

Declare @no char(6) = '001553'

 

Set @strQuery = 'SELECT * FROM Openquery(

    [192.168.0.1], '''

    + ' SELECT id FROM [데이터베이스].dbo.[테이블] WHERE no = '''+ @no +''' '

    + ''')'

--Exec SP_EXECUTESQL @strQuery

Exec (@strQuery);

  

Set @no varchar(100) = '2,4'

Set @strQuery = 'SELECT * FROM Openquery(

    [192.168.0.1], '''

    + ' SELECT * FROM [데이터베이스].dbo.[테이블] WHERE no in ('+ @no +') '

    + ''')'

Exec (@strQuery);



출처 : http://tofriendy.tistory.com/26

출처 : SPATIUM

CSV(comma seperated  values, 쉼표로 구분된 값들)파일을 읽어서 처리하는 코드를 작성하고보니 업로드 해야겠다는 생각이 들었다.

python 에서는 csv라는 모듈을 제공해준다. 그래서 import csv를 해서 사용하면 된다.

- csv 파일 읽기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import csv
 
def getCsv(self):
        csvList = []
    
        f = open('./exam.csv','r')    #현재 경로의 exam.csv를 연다.
        csvReader = csv.reader(f)    #reader로 파일을 읽는다.
        
        for i in csvReader:            #한 행씩 돌면서 i[2]값 (3번째 컬럼)을 가져와서 리스트에 저장한다.
            csvList.append(i[2])
        f.close()
    
        return csvList
        
def checker(self):
    csvList = self.getCsv()
    
    if 'ecycle' not in csvList:        #리스트에서 ecycle 문구 존재여부 체크
        print "X"
    else:
        print "O"    
 
if __name__ =='__main__':
    
    print sta.Checker()    
cs

- csv 파일 쓰기

1
2
3
4
5
6
7
8
def setCsv(self):
    
    f = open('./exma2.csv','w')
    csvWriter = csv.writer(f)
        
    csvWriter.writerow(['ecycle','1989','seoul','preprofession'])
    f.close()
        
cs


- 약한 참조 : 레퍼런스 카운트로 고려되지 않는 레퍼런스 객체

% Reference count(참조수)란?
        : 얼마나 많은 부분에서 객체를 참조하고 있는가를 나타내 주는 정수


sys모듈의 getrefcount는 요소의 레퍼런스카운트 갯수를 반환해줌

1. python을 구현한 내부코드에서 3이란 숫자를 29번 참조했다는 의미

2. 한 변수를 참조하는 다른 변수 또한 같은 메모리 공간을 가리키고 있음

3. 서로 같은 값(256이하)을 가지고 있는 다른 변수는 같은 메모리 공간을 가리킴

4. 257 이상 부터는 같은 값을 저장해도 다른 아이디 값은 가진다. 

%아마도 256까지는 singletone으로 구현되었을 것이다.


**python의 Garbage Collecter의 원리**
        : 레퍼런스 카운트가 0인 경우 사용하지 않는 메모리라고 판단하고 GC가 메모리를 반환한다. 


- weakref.ref()
        : 주어진 객체에 대한 약한 참조를 만들어 낸다. 원 객체를 얻을 때에는 약한 참조 자체를 함수처럼 호출.


- weakref.proxy()
        : 원본객체를 대신하는 프록시 객체로 약한 참조를 얻는다. (약한 참조를 객체로 접근 하는 방법)


- 사용 용도

1. 탱글링 방지(cycle reference : 순환 참조)
    : 서로 다른 객체들 사이에 참조 방식이 순환 형태로 연결되는 방식
    독립적으로 존재하지만 순환 참조되는 서로 다른 객체 그룹은 쓰레기 수집이 잘 안됨.
    주기적으로 수집 기능이 있지만 CPU자원 장비가 심함 > 빈도가 낮으면 메모리 불필요한 메로리 점유

2. caching에 사용하면 효과적
    : 대용량의 이미지 데이터들을 가지고 있을 때, 메모리 관리를 편하게 하기 위해 (local에 제한을 둠) 예제 참고 ExpensiveObject.py
        (불필요한 데이터를 끝까지 가지고 있을 필요 없음)

3. 용량이 큰 객체를 자주 사용하거나, 쉽게 만들 수 있을 때 


ExpensiveObject.py (WeakValueDictionary를 사용하여 약한 참조를 만든다. > 원 객체를 참조를 없애고 가비지 컬렉터를 돌려 약한 참조의 생명주기를 확인한다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import gc
from pprint import pprint
import weakref
 
gc.set_debug(gc.DEBUG_LEAK)
 
class ExpensiveObject(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return 'ExpensiveObject(%s)' % self.name
    def __del__(self):
        print '(Deleting %s)' % self
        
def demo(cache_factory):
    # hold objects so any weak references 
    # are not removed immediately
    all_refs = {}
    # the cache using the factory we're given
    print 'CACHE TYPE:', cache_factory
    cache = cache_factory()
    for name in [ 'one''two''three' ]:
        o = ExpensiveObject(name)
        cache[name] = o
        all_refs[name] = o
        del o # decref
 
    print 'all_refs =',
    pprint(all_refs)
    print 'Before, cache contains:', cache.keys()
    for name, value in cache.items():
        print '  %s = %s' % (name, value)
        del value # decref
        
    # Remove all references to our objects except the cache
    print 'Cleanup:'
    del all_refs
    gc.collect()
 
    print 'After, cache contains:', cache.keys()
    for name, value in cache.items():
        print '  %s = %s' % (name, value)
    print 'demo returning'
    return
 
demo(dict)
print
demo(weakref.WeakValueDictionary)
cs


- 반복자(iterator) 
    : 데이터 타입의 내부 구현을 노출하지 않고 포함하고 있는 요소들을 순회하는 방법

리스트 또는 어떤 컨테이너를 Iterator로 만들려면

def __iter__(self):
    return self

def next(self):
    self.data += 1
    if self.limit and self.limit <= self.data:
       
         raise StopIteration
    return self.data

을 선언해 주면 된다. > iterator가 되었으므로 for문을 돌면서 next 메소드를 호출시켜 준다.

StopIteration을 종료후 던져야 한다.

ex)    


- 발생자 (Generator)
    : return 대신 yield를 사용하는 것

-> 함수 호출된 후에 되돌아갈 때, 메모리가 해제되지 않고 그대로 남아있음
    그리고 다시 그 함수가 호출되면 이전에 수행이 종료되었던 지점 이후를 계속 진행함.

yield : Iterator를 구현할 수 있는 훨씬 간결한 문법을 제공한다.!!


   코드 설명

gen = generate_inits(3) #초기 스택 프레임 발생 / 실행 중단 상태
gen.next()                  #실행 재개
yield                         #실행 중단/ 값 return

- 일반 함수와의 차이점 : 일반 함수는 모든 일을 마친 결과를 넘김, But 정보를 생성하는 중간에 값을 넘길 수 있다.
    > 어떤 작업의 중간 결과를 다른 코드에서 참조해야 할 경우 유용하게 활용됨
    > 병행 프로세스나 멀티쓰레드 처리 업무에도 활용 가능
    > 메모리 효율성에 좋음

1번 글에서 conf의 모양을 봤다면 DB접속 정보라는 것을 알 수 있다.

DBInfo.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[DB] 
host= 1.1.1.1
user=ecycle
passwd=ecycle123123
db=testdb
charset=utf8
use_unicode=true
sql_insert =    insert into user
                (
                CONNTIME,
                UNO,
                UNAME,
                UEMAIL,
                UPASSWORD
                )
                VALUES(
                str_to_date('%s', '%%Y%%m%%d%%H%%i%%s'),
                '%s',
                '%s',
                '%s',
                '%s'
                )
                ;
 
cs

이 conf파일은 DB정보와 insert 구문을 가지고 있다.
이 파일을 이용해서 DB와 연동된 python 코드를 작성해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python
#-*- codig: utf-8 -*-
 
import MySQLdb
import sys
import time
import ConfigParser
import signal
from datetime import datetime
 
 
SHUTDOWN = False
 
def shutdown(sigNum , frame):
    global SHUTDOWN
    SHUTDOWN = True
    __LOG__.Trace("SIGNAL NUM:%s" %sigNum)
    return
 
signal.signal(signal.SIGTERM, shutdown)  # Sig Terminate: 15
signal.signal(signal.SIGINT, shutdown)    # Sig Inturrupt: 2
try:
    signal.signal(signal.SIGHUP, shutdown)  # Sig HangUp: 1
except Exception, e : pass
try:
    signal.signal(signal.SIGPIPE, shutdown) # Sig Broken Pipe: 13
except Exception, e : pass
 
def db_connPool(cfg):
    conn = None
    try:
        conn = MySQLdb.connect(
            host = cfg.get('DB''host'),
            user = cfg.get('DB''user'),
            passwd = cfg.get('DB''passwd'),
            db = cfg.get('DB''db'),
            charset = cfg.get('DB''charset'),
            use_unicode = cfg.getboolean('DB''use_unicode')
            )
    except Exception as e:
        __LOG__Trace("DB connection error : %s" %e)
 
 
    return conn
 
 
def db_insert(params,cfg):
    try:
        
        conn = db_connPool(cfg)
        __LOG__.Trace("DB connected")
 
        #cursor = None
 
        #transaction
    
        conn.autocommit = False
        cursor = conn.cursor()
        strSql = cfg.get('DB','sql_insert') % params
        cursor.execute(strSql)
        __LOG__.Trace("Inserted!")
 
    except Exception as e:
        conn.rollback()
        __LOG__Trace("insert Error : %s" % e)
 
    finally:
        conn.commit()
        if cursor:
            cursor.close()
        if conn:
            conn.close()
 
if __name__ == '__main__':
 
    if len(sys.argv) <5:
        __LOG__.Trace('not enough arguments')
        sys.exit()
    
    __LOG__.Trace("*****DB INSERT START*****")
 
    try:
 
        cfg = ConfigParser.ConfigParser()
        cfg.read("./DBInfo.conf")
        
        
        time = datetime.now().strftime('%Y%m%d%H%M%S')
        nparams = (
            time,
            sys.argv[1],
            sys.argv[2],
            sys.argv[3],
            sys.argv[4]
            
            )
        
        db_insert(nparams,cfg)
        
    except:
        __LOG__.Trace("insert error")
        sys.exit()
 
    __LOG__.Trace("*****complete*****")
 

cs

이 코드는 transaction도 구현하였다. 간단하게
signal은 추후에 정리해서 올리겠다.

프로그램을 작성하다보면 서버 접속정보, DB정보 등 변경 가능한 정보들을 소스에 코딩해 놓는 것은 위험하다.

그래서 설정정보를 분리한 .conf나 .ini를 작성하여 외부에서 설정정보를 가지고 오도록 작성하는 것이 좋다.


python의 경우 ConfigParser모듈을 import해서 외부 설정 정보를 가지고 올 수 있다.


예제)
    getConfig.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python
#-*- codig: utf-8 -*-
 
import ConfigParser
 
 
def get_config(cfg):
    
    host = cfg.get('DB''host'),
    user = cfg.get('DB''user'),
    passwd = cfg.get('DB''passwd'),
    db = cfg.get('DB''db'),
    charset = cfg.get('DB''charset'),
    use_unicode = cfg.getboolean('DB''use_unicode')
    insert_Sql = cfg.get('DB'.'sql_insert')
    
    
    #cfg값 출력
    print host, user, passwd, db, charset, use_unicode, insert_Sql
    
 
if __name__ == '__main__':
 
    cfg = ConfigParser.ConfigParser()
    cfg.read("./DBInfo.conf")            #절대주소를 적어주는게 좋다.
    get_config(cfg)
cs


DBinfo.conf

[DB] 
host= 1.1.1.1
user=ecycle
passwd=ecycle123123
db=testdb
charset=utf8
use_unicode=true
sql_insert = insert into user
                (
                CONNTIME,
                UNO,
                UNAME,
UEMAIL,
                UPASSWORD
                )
                VALUES(
                 str_to_date('%s', '%%Y%%m%%d%%H%%i%%s'),
                '%s',
                '%s',
                '%s',
                '%s'
                );





JAVA구현 코드 보단 python 코드로 구현한 것을 보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
         try:
     
              conn = db_connPool(cfg)     #cfg는 configuration을 의미
              __LOG__.Trace("DB connected")
     
              #cursor = None
     
              #transaction
     
              conn.autocommit = False    #autocommit을 꺼준다.
              cursor = conn.cursor()
              strSql = cfg.get('DB','sql_insert') % params
              cursor.execute(strSql)
              __LOG__.Trace("Inserted!")
     
          except Exception as e:
              conn.rollback()            #Exception발생 시 rollback을 통해 되돌아간다.
              __LOG__Trace("insert Error : %s" % e)
     
          finally:
              conn.commit()                #정상적으로 insert가 이루어지면 commit하여 DB에 반영한다.
              if cursor:
                  cursor.close()
              if conn:
                  conn.close()
 
cs


오라클에서 insert문을 사용하는 메소드에서 int변수를 사용하지 않고 Integer변수를 사용하는 이유

★ 오라클에서 insert문을 사용하는 메소드에서 int변수를 사용하지 않고 Integer변수를 사용하는 이유
        --> insert문의 결과가 없거나 실패할 경우 null값을 리턴받기 위해. int변수를 사용하면 실패하는 경우 리턴되는 값이 없기 때문.



numbering된 sequence 값을 바로 받아 오는 법

Oracle에서 사용

preparedStatement의 생성자중 (sql, String columnName)사용
PreparedStatement ps = conn .prepareStatement(sql, new String[]{"bno" });
ResultSet rs = ps.getGeneratedKeys();
           if(rs .next()){
               bno = rs.getInt(1);
          }

자동 생성된 키를 return해라

Mysql(MsSQL Server)에서 사용
PreparedStatement ps = conn.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);


+ Recent posts