테이블 생성시 auto_increment 설정

CREATE TABLE people 
(
    number INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255)
);

 

AUTO_INCREMENT 확인

다음에 삽입될 Auto_increment(number 컬럼)의 값 확인

SHOW TABLE STATUS WHERE name = '테이블 이름';
SHOW TABLE STATUS LIKE '테이블 이름';

mysql> show table status where name = 'people' \G;
*************************** 1. row ***************************
           Name: _people
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 6
 Avg_row_length: 2730
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 82
    Create_time: 2021-12-31 15:02:42
    Update_time: 2021-12-31 15:10:03
     Check_time: NULL
      Collation: utf8mb4_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

AUTO_INCREMENT  초기값 변경

AUTO_INCREMENT를 초기화(변경)할 때는 변경할 AUTO_INCREMENT의 값이 해당 컬럼에서 가장 큰 값보다 커야 합니다

ALTER TABLE 테이블 이름 AUTO_INCREMENT=변경할 숫자;

mysql> alter table _people auto_increment=5
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show table status where name = 'people' \G;
*************************** 1. row ***************************
           Name: _people
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 6
 Avg_row_length: 2730
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 5
    Create_time: 2021-12-31 15:57:51
    Update_time: 2021-12-31 15:10:03
     Check_time: NULL
      Collation: utf8mb4_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

AUTO_INCREMENT  1부터 순서대로 정렬

레코드 삭제와 업데이트 등과 같은 이유로 AUTO_INCREMENT로 설정된 컬럼의 숫자가 난잡하게 될 수 있습니다. 이때 보기 좋게 1부터 순서대로 정렬할 수 있습니다.

정렬 전 데이터
SET @count=0;
UPDATE 테이블 이름 SET 컬럼 이름=@count:=@count+1;

mysql> SET @count=0;
mysql> UPDATE people SET number=@count:=@count+1;
정렬 후 데이터
# 데이터 정렬 후 AUTO_INCREMENT 값을 변경
ALTER TABLE 테이블 이름 AUTO_INCREMENT=변경할 숫자;

mysql> alter table people AUTO_INCREMENT=4;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

예제

AUTO_INCREMENT5변경

 

 

ex) ALTER TABLE people AUTO_INCREMENT=5;

// people 테이블의 AUTO_INCREMENT 값을 5로 변경

* 변경된 것을 확인(SHOW TABLE STATUS LIKE 'people';)

1) 데이터 삽입

 
 

ex) INSERT INTO people VALUES (NULL, "name_D");

Auto_increment5변경했기 때문에 number에 5삽입됩니다.

삽입을 완료하면 Auto_increment6이 됩니다.

다시 AUTO_INCREMENT4로 변경하려고 하더라도 오류는 발생하지 않지만 number 컬럼의 가장 큰 값5이기 때문에 Auto_increment의 값은 4로 변경되지 않고 6으로 되어있습니다.

 
 

* 현재 5보다 큰 숫자로만 변경 가능

2) 데이터 삭제

 
 

 

ex) DELETE FROM people WHERE number=5;

number가 5인 데이터를 삭제하면 number 컬럼에서 가장 큰 값3이기 때문에 Auto_increment4로 변경 가능합니다.

* 현재 3보다 큰 숫자로 변경 가능

​* 참고

Auto_increment1로 초기화하려면 테이블의 데이터가 없어야 합니다.

 

참고

https://m.blog.naver.com/dldudcks1779/222006115309

 처음과 끝은 각각 ^과 $로 표현할 수 있어요. 예를 들어서, '^a'라면, a로 시작하는 패턴입니다. 그리고 'E$'이라면, E로 끝나는 패턴입니다. 그러면 '^eat$'은 무엇을 의미할까요? "eat"를 찾으라는 거겠네요. 그리고, .은 임의의 문자를 의미하는데요. '^...$'은, 길이가 3인 문자열이 패턴에 매칭된다는 이야기입니다.

 

 

 이 쿼리를 수행해 봅시다. 그러면 문자열이 시작하고 임의의 문자가 3개 나오고 끝납니다. 그 말은, "Tom"이나 "Bob"도 matching이 된다는 소리일 거에요.

 

 

 

 결과는, _name 필드의 문자열 길이가 3인 것들만 출력됩니다.

 

 


 그런데, 우리는 _name이 모음으로 시작하는 것들을 구한다고 해 봅시다. LIKE를 쓰면 대충 10개의 조건절을 and로 연결하거나, 아니면 left 함수로 1개의 문자열을 가져온 것이, IN에 속해있는지. 등 조금 복잡하게 쿼리를 작성해야 할 거에요.

 

 [...] 패턴은 ...에 속하는 문자 집합이 패턴에 걸린다는 의미인데요. 예를 들자면 이런 경우를 봅시다.

 

 

 이 쿼리는 무엇을 의미할까요? 일단 문자열이 시작했다는 ^가 들어와 있고, []가 있네요. 안에 것을 보니까 aAeE가 있는데, 첫 문자의 가능 집합이 a, A, e, E라는 것입니다. 즉, _name 필드가 이 4개의 문자로 시작하는 레코드들을 모두 출력하라는 의미입낟.

 

 

 쿼리의 결과는 다음과 같습니다. 그러면, a, A, e, E라는 문자가, 첫 번째에도 나오고 두 번째에도 나와야 하는 경우는 어떻게 작성해야 할까요? 이 때, {n}이라는 키워드를 씁니다. 해당 패턴이 n회 반복된다.

 

 

 이 문장의 의미는, string이 시작하고 나서, a나 A나 e나 E가 2회 반복되어야 한다는 것입니다. 즉, aa~나 aA~나 ae~나 aE나, ... , EE가 해당 패턴에 걸릴 거에요. 그러면 저 셋 중에는, eat가 있는 필드만 걸리겠네요.

 

 

 하핫. 만약에 1회 이상 2회 미만 그러한 패턴이 나타나는 패턴이 참이 되게 하고 싶다면 어떻게 하면 될까요? {n,m}을 쓰시면 됩니다. 이것은 패턴이 n회 이상, m회 이하 등장한다는 의미입니다. Arie, Asia, eat 셋 중에, 다음 패턴을 만족하는 것이 몇 개나 있을까요?

 

 

 일단, a나 A나 e나 E가 나타나는 패턴이 최소 1회, 최대 1회 반복이 되고, 임의의 문자가 하나 나오면 A?나 A?나 e?나 E?가 저것과 매치가 될 거에요. 그러면, 저 셋 중에서 만족하는 것이 없어요. 그런데, 아래와 같은 경우에는 이야기가 달라집니다.

 

 

 보시면 패턴이 1회 이상 2회 이하 반복되고, 임의의 문자 하나가 들어오고 끝나면 만족을 하는데요.

 

 

 eat는 만족합니다. e가 aAeE 패턴에 만족하고, a 또한 aAeE 조건에 만족합니다. 2회 반복되었고, 다음에 t는 임의의 문자 중 하나입니다. 개행을 제외한. 따라서 eat가 있는 레코드만 출력이 됩니다. [^...]은 무엇을 의미할까요? ...에 속하지 않는 문자 집합을 의미합니다.

 

 

 위 쿼리를 실행해 봅시다. 그러면 문자열이 시작하고, 첫 번째 문자가 a나 A가 아니여야 합니다. _name 필드가 그러한 것만 고르는 query입니다. 한 번 실행을 해 봅시다.

 

 

 Asia랑 Anie는 빠졌음을 알 수 있어요.

 

 


 *과 +이 남았네요. *은 패턴이 0번 이상, +은 1번 이상 나타난다는 것을 의미합니다. 예를 들어서, 다음과 같은 것을 생각해 봅시다.

 

 

 이것은 문자열이 시작했을 때, A,a,E,e가 최소 0회 이상 나오는 패턴과 매칭이 됩니다.

 

 

 실행 결과는 아래와 같이 나옵니다. 시작 문자가 어느 것이던 상관 없다는 겁니다. 그런데 +가 붙으면 이야기가 달라지는데요. 이것은 최소 1회 이상 문제의 패턴이 반복되어야 한다는 겁니다.

 

 

 쿼리를 이렇게 작성해 봅시다.

 

 

 그러면 A나 a나 E나 e로 시작하는 것들만 나올 거에요. 마지막으로, |가 있는데요. 이것은 or를 의미합니다.

 

 

 다음 쿼리는 A로 시작하거나, B로 시작하는 패턴을 찾으라는 겁니다.

 

 

 결과는 3개의 row가 리턴됩니다.

 

 


 그러면 _name이 모음으로 시작하면서, 모음으로 끝나는 것들은 어떻게 구하면 좋을까요? 일단, 저는 다음과 같은 쿼리를 수행해 보겠습니다. 당연하게도, 길이가 1짜리면서 모음인 데이터를 추가한 겁니다.

 

 

 다음에, 쿼리를 생각해 봅시다. 일단 문자열이 시작해야 하고, [aeiouAEIOU] 라는 pattern이 들어와야 할 겁니다. 다음에 임의의 문자가 0개 이상 오고, [aeiouAEIOU] 패턴이 온 다음에 끝나야 겠지요.

 

 

 그러면, 이런 식으로 작성할 수 있을 겁니다. 그런데, 이 경우 길이가 1인 데이터는 매칭이 되지 않을 겁니다.

 

 

 결과를 확인해 보면, "A"라는 것은 matched가 되지 않았음을 알 수 있어요. 그러면 어떻게 작성하면 좋을까요?

 

 

 이렇게 작성하면 어떻게 수행이 될까요? 일단, 첫 패턴이 모음인지 검사합니다. 그 다음에 괄호 안으로 들어갈 건데요. 판단 state를 그려보면 아래와 같습니다.

 

 

 보시면 모음이 나온 후에 바로 Terminate가 되거나, 아니면 임의의 문자가 0회 이상 나온 후에, 모음으로 끝나는 패턴만 regexp에 걸리게끔 하고 있어요. 조금 어려운 예제였습니다. 그러면, 모음으로 시작하거나, 모음으로 끝나는 건 어떻게 작성하면 좋을까요?

 

 

 Conditions를 괄호로 묶고 |를 붙이면 됩니다. 어떤 조건인가요? ^[모음들]이거나, [모음들]$이겠지요. 이 둘을 괄호로 묶어준 다음에 |로 연결해 주시면 됩니다. 정규 표현식을 연습하는 사이트는 여러 곳이 있습니다. 거기에서 연습해 보셔도 좋을 듯 싶습니다.

 

참고

https://codingdog.tistory.com/entry/mysql-regexp-%EB%B3%B5%EC%9E%A1%ED%95%9C-%ED%8C%A8%ED%84%B4-%EB%A7%A4%EC%B9%AD%EC%9D%84-%ED%95%B4-%EB%B4%85%EC%8B%9C%EB%8B%A4

 

mysql regexp : 복잡한 패턴 매칭을 해 봅시다.

 저번에 LIKE 연산자를 배웠습니다. 이번에는 조금 더 복잡한 패턴 매칭에 대해서 다뤄보겠습니다. [관련글] LIKE 연산자 알아봅시다.  눈치 채신 분도 있으실지 모르겠습니다. 자바에서 파싱할

codingdog.tistory.com

has_key

menu = {"ham" : 1, "cucumber" : -12, "egg" : 100}

if menu.has_key("ham"):
    print "네, 찾는 것이 있네요"
else:
    print "그런 메뉴는 없습니다."

 

파이썬 3을 사용중이면 아래 에러 문구가 나오면 처리되지 않음

  AttributeError: 'dict' object has no attribute 'has_key' 

has_key는 파이썬에서 지양하는 함수로, 파이썬 2를 사용하는 분들도 사용하면 안된다.

  http://stackoverflow.com/questions/1323410/has-key-or-in

get / in

1. get

menu = {"ham" : 1, "cucumber" : -12, "egg" : 100}

if menu.get("ham"):
    print "네, 찾는 것이 있네요"
else:
    print "그런 메뉴는 없습니다."
2. in
menu = {"ham" : 1, "cucumber" : -12, "egg" : 100}

if "ham" in menu:
    print "네, 찾는 것이 있네요"
else:
    print "그런 메뉴는 없습니다."

get은 키에 해당하는 값을 넘겨주기 때문에 값이 있다면 True고 없다면 False(...일 것 같지만 실제로는 None을 리턴한다. None False가 아니긴 하지만.... 어차피 키 값 판별이니 True가 아니므로 없는 메뉴에 대해서는 else로 빠진다.) 가 된다.

 

참고

https://www.pymoon.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C-%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC-%ED%82%A4-%EA%B0%92-%EC%B2%B4%ED%81%AC%ED%95%98%EA%B8%B0

 

replace

일반적으로 한 두개 정도의 간단한 치환

# 대문자를 소문자로
> ex = "Korea is Great"
> ex.replace('K','k').replace('G','g')
'korea is great'

translate

여러 문자를 한번에 치환

유의해야 할점은 maketrans 함수 안에 두 개의 인자의 길이(length)가 똑같아야함

# 모음없애기(소문자 외 대문자까지 한방에 가능하다)
> ex = "Korea is Great"
> table = str.maketrans('aieouAIEOU', '          ')
> ex.translate(table)
'K r    s Gr  t'

> table = str.maketrans('aieouAIEOU', '1234567890')
> ex.translate(table)
'K4r31 2s Gr31t'

 

참고

https://velog.io/@keywookim/Python-translate-%ED%95%9C-%EB%B2%88%EC%97%90-%EC%97%AC%EB%9F%AC-%EB%AC%B8%EC%9E%90-%EC%B9%98%ED%99%98%ED%95%98%EA%B8%B0

에러 문구

too many values to unpack

원인

설정한 변수의 개수와 리턴해 주는 변수의 개수가 차이가 날때 발생

예를 들어 리턴 받는 값의 개수가 3개로 맞춰야 정상인 경우
aa, bb, cc = ss.run([a,b,c])

아래 경우는 오류 발생
bb, cc = ss.run([a,b,c])
> too many values to unpack

해결

리턴 받는 값의 개수를 맞춰주면 해결

 

참고 

https://wotres.tistory.com/entry/too-many-values-to-unpack-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%EB%B2%95

 

현상

높은 비중의 Thread State 상태가 유지되면서, CPU사용량이 높아지면서 성능 이슈가 발생

원인

Front-End 서버에서 MySQL에 만들어둔 SP 사용시 SP의 Body 호출이 필요함

MySQL.PROC에 해당 정보가 있지만 권한이 없어 INFORMATION_SCHEMA 정보를 가져가게 되면서 발생

해결 방안

db 접속 계정에 MySQL DB의 PROC 테이블에 SELECT 권한 부여

test_acc 계정에 권한 추가하는 경우

GRANT SELECT ON `mysql`.`proc` TO 'test_acc'@'%';

 

※현상

DB를 single_user에서 multi_user로 변경하는 도중 프로세스 Deadlock 발생

원인

DB 커넥션이 존재하는 상황에서, 사용자 세션이 master를 바라보는 도중 DB  커넥션을 모두 off시켜,

사용자 세션이 DB를 바라보지 않아 system 내부에서 DB의 소유자를 찾지 못하는 상태

deadlock이 발생하는 세션을 끊으려 하여도 사용자 세션이 아닌 시스템 세션이라 kill이 불가한 상태 

해결방안

1번으로 작업해야 하지만, 이미 deadlock이 발생한 상태라면 2번으로 해결

1. 작업하려는 DB를 소유하고 single_user로 변경

use [작업DB]
 
alter database [작업DB] set single_user WITH ROLLBACK IMMEDIATE-- immediate 커넥션 한번에 off
go
  
-- 작업 할 쿼리 내역
  
alter database [작업DB] set multi_user
go

2. Deadlock 발생 시, DB 재기동 후 아래 쿼리 실행

SET DEADLOCK_PRIORITY HIGH -- 교착상태 최상위 레벨로 격상
GO
 
ALTER DATABASE [작업DB] SET MULTI_USER WITH ROLLBACK IMMEDIATE -- 작업 DB multi_user로 변경
GO
  
-- https://myadventuresincoding.wordpress.com/2014/03/06/sql-server-alter-database-in-single-user-mode-to-multi-user-mode/

현상

MySQL의 SP를 사용하는 DB에서 지속적으로 Memory가 상승하는 현상 발생

원인

MySQL 내부적으로 SP 내 Subquery 사용 시 Memory Leak 이 발생

참조: The optimizer sometimes generates an index for a derived table (subquery in the FROM clause).

If this occurred for a statement executed within a stored program, a memory leak could occur. (Bug #76349, Bug #20728894)

해결방안

해당 버그가 5.6.27 이후 fixed 된 것으로 확인되어 MySQL upgrade

upgrade 후 memory leak 현상 해소

 

방법

라인의 마지막 부분에 \ 을 추가한다.

// validation
$(".adjustment, .info input, .includesAndTiming input, \
    .independentAdj, .generalAdj, .executiveAdj \
    #officeExpense, #longDistanceExpense, #digitalImages, #milesReimbursment, #driveTime, #statementTranscription").keypress(function (event) {

 

참고

https://stackoverflow.com/questions/10514873/line-continuation-characters-in-javascript

html

<textarea id="textarea_summernote" name="textarea_summernote">
  textarea 내용 입력
</textarea>

javascript

html에서 생성한 textarea_summernote textarea를 summernote()를 사용하여 초기화 진행

이미지 파일 처리를 위해 onImageUpload 함수 등록

uploadSummernoteImageFile 함수에서 첨부한 파일 정보를 ajax를 이용하여 flask로 전달하여 저장소에 저장

setSummernoteValue 함수는 Summernote에 값을 추가하는 예시

// summernote 초기화
$(function () {
    // Summernote
    $('#textarea_summernote').summernote({
        callbacks : {
            // 이미지 첨부하는 부분
            onImageUpload : function(files){
                uploadSummernoteImageFile(files[0],this);
            },
            onPaste : function(e) {
                var clipboardData = e.originalEvent.clipboardData;

                if(clipboardData && clipboardData.items && clipboardData.items.length){
                    var item = clipboardData.items[0];
                    if(item.kind === 'file' && item.type.indexOf('image/') !== -1){
                        e.preventDefault();
                    }
                }
            }
        }
    });  
});


// summernote - 이미지 파일 업로드
function uploadSummernoteImageFile(file, editor){

    // 프로젝트 코드
    var project_code = 'test'
    
    var data = new FormData();
    data.append('file',file);
    data.append('project_code', project_code);

    //file 정보를 python으로 전달
    $.ajax({
        data: data,
        type : "POST",
        url : "/test/uploadSummernoteImageFile",
        contentType : false,
        processData : false,
        success : function(data){
            alert('File Upload Success')
            $(editor).summernote('insertImage', data.filepath);
        }
    });
}


function setSummernoteValue(value) {

    // value가 문자열인 경우
    $('#textarea_summernote').summernote('insertText', value);
    
    // value가 html 태크 형태인 경우
    $('#textarea_summernote').summernote('pasteHTML', value);
}

python

프로젝트 코드(또는 메뉴등의 그룹)별 파일을 저장하기 위해 폴더에 서비스 코드 추가

파일명이 겹치지 않도록 파일명 앞에 현시간을 추가

@project_blueprint.route('test/uploadSummernoteImageFile', methods =['POST'])
@login_required
def project_test_uploadSummernoteImageFile():

    try :
        file = request.files['file']
        project_code = request.form['project_code']
        default_path = 'test/img/'

        host_path = default_path + project_code + '/'
        if not os.path.exists(host_path):
            os.mkdir(host_path)

        now_date = datetime.datetime.now()
        prefix_date = now_date.strftime('%Y%m%d_%H%M%S_')

        img_name = host_path + prefix_date + file.filename
        file.save(img_name)

        return jsonify(filepath = img_name[3:])

    except (RuntimeError, TypeError, NameError, SQLAlchemyError) as e:
        print("#### img upload Failed !! " + str(e))

        return jsonify(message=str(e))

참고

https://summernote.org/deep-dive/#pastehtml


to Top