728x90
반응형

PostgreSQL의 경우, MariaDB와는 다르게 데이터 복구를 위한 여러 가지 옵션이 있지만, 여전히 백업로그의 중요성이 매우 큽니다. PostgreSQL은 복구를 위한 강력한 기능을 제공하고 있으며, 여러 방법으로 삭제된 데이터를 복구할 수 있습니다.

PostgreSQL 데이터 복구 방안

1. WAL (Write-Ahead Logging) 사용

PostgreSQL은 **WAL(Write-Ahead Log)**을 사용하여 트랜잭션을 기록합니다. 이 기능을 통해 온라인 복구가 가능하며, 데이터베이스에서 수행된 모든 트랜잭션을 추적할 수 있습니다. WAL은 PostgreSQL의 강력한 복구 메커니즘으로, 데이터베이스의 완전한 복구와 장애 복구를 지원합니다.

1.1. WAL 로그를 이용한 PITR(Point In Time Recovery)

Point In Time Recovery(PITR)는 특정 시점으로 데이터베이스를 복구하는 방법입니다. 이 기능을 사용하면, 특정 시간에 발생한 문제를 해결하고 그 시점으로 복구할 수 있습니다.

  1. WAL 아카이브 설정: PostgreSQL에서 WAL을 아카이브하려면, postgresql.conf 파일에서 WAL 아카이브를 활성화해야 합니다.
archive_mode = on
archive_command = 'cp %p /path_to_archive/%f'
  1. WAL 로그 아카이브 사용: 데이터베이스가 백업된 후, 트랜잭션 로그(WAL 로그)가 아카이브됩니다. 이 로그를 사용하여 특정 시점으로 데이터베이스를 복구할 수 있습니다.
  2. PITR 복구:
    • 데이터를 백업한 후, WAL 로그를 사용해 특정 시점으로 복구할 수 있습니다. 예를 들어, 데이터베이스에서 삭제된 데이터를 복구하려면 WAL 로그가 삭제 작업 이전 시점까지 포함되어 있어야 합니다.
    • PITR 복구를 설정하려면 restore_command와 recovery_target_time 등을 설정하여 복구 대상 시점을 지정합니다. 예를 들어:
restore_command = 'cp /path_to_archive/%f %p'
recovery_target_time = '2025-07-10 10:00:00'

1.2. WAL 파일 덤프 사용

pg_waldump와 같은 도구를 사용하여 WAL 로그에서 발생한 쿼리를 추출하고, 이를 기반으로 복구를 시도할 수 있습니다. 이 방법은 삭제된 데이터를 복구하려는 시점 이후의 WAL 로그가 있어야 합니다.

pg_waldump /path_to_wal_log
 

1.3. pg_restore로 복구

백업이 있거나, WAL 로그 아카이브를 통해 복구를 시도할 수 있습니다. pg_restore 명령어를 사용하여 덤프된 데이터베이스를 복구할 수 있습니다.

pg_restore -U postgres -d mydb /path_to_backup/backup_file.dump

2. PostgreSQL 로그를 통한 복구

2.1. PostgreSQL의 Error Log / General Log

PostgreSQL의 General Query LogError Log를 통해 실행된 쿼리를 확인하고, 삭제된 데이터를 추적할 수 있습니다. 일반적으로 PostgreSQL에서는 log_statement와 log_duration을 설정하여 로그에 쿼리 및 실행 시간을 기록할 수 있습니다.

  1. 로그 설정: postgresql.conf 파일에서 로그 설정을 조정할 수 있습니다.
log_statement = 'all'  # 모든 쿼리 로그 기록
log_duration = on  # 쿼리 실행 시간 기록

 

  1. 로그 확인: 로그 파일을 통해 삭제된 데이터를 찾을 수 있는 쿼리를 추적할 수 있습니다.
shared_preload_libraries = 'pg_stat_statements'

2.2. pg_stat_statements 사용

pg_stat_statements는 PostgreSQL에서 쿼리 실행 통계를 기록하는 뷰입니다. 특정 쿼리가 실행된 후 데이터베이스에서 어떤 변화를 일으켰는지 추적할 수 있습니다.

  1. pg_stat_statements 활성화:
shared_preload_libraries = 'pg_stat_statements'
  1. 쿼리 통계 확인:
SELECT * FROM pg_stat_statements WHERE query LIKE '%DELETE%';​

2.3. 복구된 쿼리 적용

로그에서 삭제된 데이터를 복구할 수 있는 쿼리를 찾았다면, 해당 쿼리를 다시 실행하여 데이터 복구를 시도할 수 있습니다. 예를 들어, 삭제된 데이터를 INSERT INTO 형태로 복구할 수 있습니다.

3. 트리거와 외부 툴 사용

3.1. 트리거 기반 복구

PostgreSQL에서 트리거(Trigger)는 데이터의 변화를 추적하는 데 유용할 수 있습니다. 예를 들어, 데이터를 삭제할 때마다 삭제된 데이터를 별도의 테이블에 백업하는 트리거를 설정할 수 있습니다.

예시 트리거:

CREATE OR REPLACE FUNCTION backup_deleted_data() RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO deleted_data_log (old_data)
  VALUES (ROW(OLD.*));
  RETURN OLD;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER track_deletions
  BEFORE DELETE ON my_table
  FOR EACH ROW EXECUTE FUNCTION backup_deleted_data();

위와 같이 트리거를 사용하면, 이후 데이터를 삭제하는 작업이 있을 때마다 삭제된 데이터가 deleted_data_log 테이블에 백업됩니다. 이 데이터를 이용해 복구할 수 있습니다.

3.2. 외부 복구 툴

PostgreSQL의 경우, 여러 외부 툴을 통해 데이터 복구를 시도할 수 있습니다. 예를 들어, pg_rewind를 사용하여 마스터와 리플리카 간에 데이터 동기화 및 복구를 할 수 있습니다.

4. PostgreSQL 데이터 복구 도구

일부 서드파티 도구나 서비스는 PostgreSQL 데이터를 복구할 수 있도록 지원합니다. 예를 들어, Stellar Data Recovery for PostgreSQL과 같은 도구는 삭제된 데이터를 복구하는 데 사용할 수 있습니다.

결론

PostgreSQL에서 데이터가 삭제된 경우에도, WAL 로그, PITR(Point-In-Time Recovery), 로그 파일 등을 활용하여 데이터를 복구할 수 있습니다. 중요한 점은 WAL 아카이브백업이 설정되어 있어야만 효과적인 복구가 가능하다는 점입니다.

728x90
반응형
728x90
반응형

MariaDB 데이터베이스가 삭제된 경우, 복구는 백업이 없다면 매우 어려운 작업이 될 수 있지만, 완전한 삭제가 아니었다면 복구가 가능할 수도 있습니다. 또한, MariaDB는 다양한 로그 파일을 기록하기 때문에, 로그를 활용한 복구 시도도 가능합니다.

1. MariaDB 복구 시도 방법

1.1. InnoDB 복구 모드 활용 (데이터가 InnoDB 엔진에 저장된 경우)

MariaDB에서 데이터를 관리하는 기본 엔진인 InnoDB는 몇 가지 복구 방법을 제공합니다. 데이터가 InnoDB 엔진을 사용하는 경우라면, 이를 활용할 수 있습니다.

  • InnoDB 복구 모드: MariaDB 서버의 my.cnf 설정 파일에서 InnoDB 복구 모드를 활성화하여 데이터 복구를 시도할 수 있습니다.

복구 모드 활성화 방법:

  1. MariaDB를 중지합니다.
  2. MariaDB의 설정 파일 (/etc/my.cnf 또는 /etc/mysql/my.cnf 등)을 열고 [mysqld] 섹션에 다음 줄을 추가합니다:
  3.  
     
[mysqld]
innodb_force_recovery = 1

 

  1. 복구 모드 값을 1에서 6까지 변경하여 복구를 시도할 수 있습니다. 기본적으로 innodb_force_recovery는 1부터 시작하여 점차적으로 높여가며 시도합니다. 값이 커질수록 더 많은 위험을 동반하므로 주의해야 합니다.
    • 1: InnoDB를 최소한의 기능으로 복구
    • 2: 트랜잭션 로그를 건너뜀
    • 3: 인덱스 재구성
    • 4: 외부 테이블 접근 비활성화
    • 5: 데이터 파일을 강제로 재구성
    • 6: 모든 외부 체크를 건너뜀
  2. MariaDB를 다시 시작하여 복구를 시도합니다.
systemctl start mariadb

복구 모드에서 서버를 시작하면 데이터를 읽을 수 없는 상태로도 테이블을 덤프할 수 있으며, 이를 통해 데이터를 외부로 내보낼 수 있습니다.

1.2. MySQL Binary Log 사용

MariaDB는 Binary Log (이진 로그) 를 기록합니다. 이진 로그는 데이터베이스에 대한 모든 수정 작업을 기록하고 있기 때문에, 로그에서 데이터를 복구할 수 있는 가능성이 있습니다.

Binary Log를 통한 복구 절차:

  1. Binary Log 확인: SHOW BINARY LOGS; 명령어로 사용할 수 있는 이진 로그 파일 목록을 확인합니다.
  2. 이진 로그 덤프: 삭제된 데이터가 포함된 구간을 찾아서 복구를 시도할 수 있습니다. 예를 들어, mysqlbinlog 도구를 사용해 이진 로그 파일을 덤프할 수 있습니다.

3. 

mysqlbinlog /var/lib/mysql/mysql-bin.000001 > dump.sql

 

  1. 덤프한 SQL 파일을 데이터베이스에 적용하여 삭제된 데이터를 복구할 수 있습니다.

2.

mysql -u root -p your_database < dump.sql

이 방법은 이진 로그 파일에 해당 데이터의 수정 내용이 포함되어 있을 때만 유효합니다. 따라서 이진 로그가 활성화되어 있어야 하며, 데이터 삭제가 발생하기 전에 로그 파일이 기록되어 있어야 합니다.

1.3. MariaDB Undo Logs 활용

InnoDB 엔진은 Undo Logs를 사용하여 트랜잭션을 롤백할 수 있습니다. 이 로그를 통해 일부 데이터를 복구할 수 있는 가능성이 있지만, 보통의 경우에는 이 Undo 로그가 오래된 데이터에 대해서는 충분히 유효하지 않을 수 있습니다. 그러나 InnoDB 테이블의 데이터 변경 전후를 추적할 수 있는 경우, 이를 활용하여 일부 복구를 시도할 수 있습니다.

2. 로그 파일을 통한 복구

2.1. General Query LogError Log 확인

MariaDB에서 General Query LogError Log를 활성화해두었다면, 해당 로그에서 일부 유용한 정보를 얻을 수 있습니다. 예를 들어, 데이터가 삭제되거나 수정된 쿼리가 기록되어 있을 수 있습니다. 이를 바탕으로 어떤 쿼리가 실행되었는지 추적하고, 데이터 복구를 위한 SQL을 작성할 수 있습니다.

  • General Query Log가 활성화되어 있으면, 실행된 SQL 쿼리들이 기록됩니다.활성화 상태라면, 해당 로그 파일에서 삭제된 데이터를 복구할 수 있는 SQL을 찾을 수 있습니다
  • 활성화 상태라면, 해당 로그 파일에서 삭제된 데이터를 복구할 수 있는 SQL을 찾을 수 있습니다.
SHOW VARIABLES LIKE 'general_log%';
  • Error Log에서는 MariaDB의 실행 에러와 관련된 중요한 정보가 기록됩니다. 시스템에서 발생한 오류나 비정상적인 종료가 기록되어 있어, 삭제된 데이터를 복구하기 위한 단서를 찾을 수 있습니다.

2.2. Slow Query Log

만약 삭제된 데이터가 복잡한 쿼리로 인해 발생한 경우라면 Slow Query Log를 확인하여, 실행된 시간이 오래 걸린 쿼리를 찾아내어 분석할 수 있습니다.

2.3. 트리거와 이벤트 확인

데이터베이스에 트리거(Trigger)가 설정되어 있었다면, 트리거 로그를 통해 데이터가 어떻게 변경되었는지 추적할 수 있습니다. 이벤트 로그(Event Log)나 트리거가 데이터 삭제와 관련이 있을 수 있습니다.

3. 데이터베이스 복구 도구 활용

외부에서 제공하는 데이터베이스 복구 도구를 사용해 볼 수도 있습니다. 다양한 서드파티 툴들이 MariaDB의 데이터를 복구할 수 있는 기능을 제공하기도 합니다.

  • Percona XtraBackup: InnoDB 데이터베이스의 백업 및 복구를 지원하는 오픈 소스 도구입니다.
  • Stellar Data Recovery for MySQL: MariaDB 및 MySQL 데이터베이스에서 삭제된 데이터를 복구할 수 있는 도구입니다.

4. 백업이 없을 경우 할 수 있는 일

백업이 없고, 이진 로그나 트랜잭션 로그 등이 제대로 설정되어 있지 않았다면 복구는 매우 어려울 수 있습니다. 이 경우 전체 시스템을 복구하기 위해서는 물리적인 복구 작업을 시도할 수 있습니다. 예를 들어, 삭제된 파일이 물리적으로 디스크에 남아 있는 경우 디스크 복구 도구를 사용할 수 있습니다. 그러나 이 방법은 보장되지 않으며, 전문 복구 서비스를 의뢰하는 것이 좋습니다.


결론

현재 상황에서 데이터 복구가 가능한지 여부는 다음과 같은 요소에 따라 달라집니다:

  • 이진 로그Undo 로그가 활성화되어 있느냐
  • InnoDB 복구 모드를 활용할 수 있는지
  • General Query Log, Error Log, Slow Query Log 등의 로그 파일을 활용할 수 있는지

따라서, 가능한 방법을 하나씩 시도해 보되, 최종적으로 복구가 어려운 경우라면 전문적인 데이터 복구 업체에 의뢰하는 방법을 고려해야 할 수 있습니다.

728x90
반응형
728x90
반응형

🔧 사용 방법 요약

1. DataSource 등록 예시

@Bean
public DataSource dataSource() {
    Map<String, DataSource> dataSourceMap = Map.of(
        "mysql", mysqlDataSource(),
        "oracle", oracleDataSource()
    );

    return DynamicRoutingDataSource.build(dataSourceMap, "mysql");
}

 

 

2. 요청 전에 데이터소스 선택

 

DynamicRoutingDataSource.setDataSourceKey("oracle");

someRepository.save(...);

DynamicRoutingDataSource.clear(); // 꼭 해제해야 함!

 

3. 트랜잭션/서비스 계층에서 AOP로 설정 가능

 

⚠️ 주의사항


 

항목 설명
반드시 요청 직전 setDataSourceKey(...) 호출 그렇지 않으면 default만 사용됩니다
요청 후 clear() 호출 필요 다음 요청에 키가 남아 있을 수 있음
다중 트랜잭션 주의 각 DB는 별도 트랜잭션 컨텍스트를 가짐

 

 RoutingDatasource (동적 선택) 구현 예제

package com.example.multidb.config;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

public class DynamicRoutingDataSource extends AbstractRoutingDataSource {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSourceKey(String key) {
        contextHolder.set(key);
    }

    public static void clear() {
        contextHolder.remove();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return contextHolder.get();
    }

    public static DynamicRoutingDataSource build(Map<String, DataSource> dataSources, String defaultKey) {
        DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource();
        routingDataSource.setTargetDataSources(new HashMap<>(dataSources));
        routingDataSource.setDefaultTargetDataSource(dataSources.get(defaultKey));
        routingDataSource.afterPropertiesSet();
        return routingDataSource;
    }
}
728x90
반응형
728x90
반응형

교착 상태(Deadlock)의 원인 중 하나인 "Lock 경합"의 핵심 원리와 관련이 있습니다. 특히 rowlock과 tablelock의 차이를 이해하면 왜 락을 오래 잡고 있으면 위험한지 명확히 알 수 있습니다.


✅ 1. Row Lock vs Table Lock의 개념 비교

대상 1개의 행 (ROW) 테이블 전체
범위 선택된 레코드 해당 테이블에 있는 모든 행
동시성 ✅ 매우 높음 (다른 행 접근 가능) ❌ 낮음 (전체 잠금)
사용 시점 WHERE 조건이 정확하고 인덱스 존재 조건이 넓거나, 인덱스 없거나, 대량 DML 시 자동 확장
성능 가장 좋음 느림, 병렬성 저하
 

🔍 예시

-- Row Lock 발생
UPDATE TB_ITEM SET QTY = QTY - 1 WHERE ITEM_ID = 123;
  • ITEM_ID에 인덱스가 있다면 해당 ROW 하나만 락 걸림 → Row Lock
 
  • 조건 범위가 넓고, ITEM_NAME에 인덱스가 없거나 통계가 부정확 → Page Lock → Table Lock 확장

⚠️ A가 락을 오래 잡고 있고 B가 같은 자원에 접근할 때 문제

시나리오

세션 A세션 B
UPDATE TB_ITEM WHERE ITEM_ID = 123 → Row Lock 획득, 오래 점유 (예: 30초) UPDATE TB_ITEM WHERE ITEM_NAME LIKE '전%' → Table Lock 시도
계속 실행 중 A가 가진 Row Lock 때문에 전체 Table Lock 못 잡음
  💥 교착 상태 또는 대기 발생
 

 


🔒 Lock Escalation (락 확장) 개념

  • SQL Server는 기본적으로 Row Lock → Page Lock → Table Lock으로 자동 확장합니다.
  • 기준: 5,000개 이상의 Row Lock이 잡히면 Page/Table Lock으로 확장 가능
확장 트리거설명
많은 행 업데이트 수천 개 Row Lock → Page Lock 필요
조건 없이 UPDATE, DELETE 테이블 전체 → 바로 Table Lock
인덱스 없음 WHERE 조건에서 적절한 ROW 대상 식별 불가 → 범위 Lock 발생
 

🧨 교착 상태가 발생하는 원인 요약

상황설명
세션 A가 Row Lock을 오래 보유 B가 해당 Row를 포함하는 더 넓은 범위에 락을 걸려함
락 확장(에스컬레이션) 시도 이미 락 보유 중인 Row가 있어 Table Lock 실패
서로 반대 순서로 테이블 접근 A: TB_ITEM → TB_LOG, B: TB_LOG → TB_ITEM
 

✅ 예방 전략 요약

전략설명
✅ 인덱스 최적화 WHERE 조건에 맞는 인덱스 있어야 Row Lock 가능
✅ 락 순서 고정 트랜잭션마다 테이블 접근 순서 동일하게 유지
✅ 트랜잭션 시간 최소화 DB 작업 외 로직은 트랜잭션 밖으로 이동
✅ read-only 쿼리는 NOLOCK 예: SELECT ... WITH (NOLOCK)
✅ 대량 작업은 오프타임 처리 밤이나 분산 배치 처리로 충돌 방지
 

💡 보너스: 강제로 Row Lock만 쓰는 방법

SELECT * FROM TB_ITEM WITH (ROWLOCK) WHERE ITEM_ID = 123;

주의: 직접 명시하지 않으면 SQL Server는 상황에 따라 락을 "자동으로 확장"할 수 있습니다.


✅ 결론

질문요약 답변
A가 락을 오래 잡고 있고 B가 접근하면? B는 Row Lock or Table Lock을 시도하다 충돌하거나 교착 상태에 빠질 수 있음
Row Lock vs Table Lock Row Lock은 정확하고 인덱스 있을 때 발생, Table Lock은 조건 넓거나 Row가 많을 때 발생
교착 방지하려면? 락 순서 통일, 인덱스 보장, 트랜잭션 최소화가 핵심
728x90
반응형
728x90
반응형

Toad for MySQL은 MySQL 데이터베이스를 관리할 때 많은 개발자가 선호하는 GUI 도구 중 하나입니다. 직관적인 인터페이스로 쿼리 실행부터 데이터 관리까지 다양한 작업을 편리하게 지원합니다. 이번 글에서는 Toad for MySQL을 더욱 효율적으로 사용하는 유용한 팁을 소개합니다.


📌 1. 자동완성(Autocomplete) 기능 적극 활용하기

쿼리를 작성할 때, 자동완성 기능을 활용하면 시간을 크게 단축할 수 있습니다.

  • 단축키 활용: Ctrl + Space로 자동완성 목록을 활성화할 수 있습니다.
  • 컬럼 및 테이블 이름 자동 추천: 몇 글자만 입력하면 Toad가 자동으로 가능한 테이블과 컬럼을 추천합니다.

📌 2. 쿼리 히스토리(Query History) 관리

이전에 실행한 쿼리를 다시 찾고 싶다면, 쿼리 히스토리를 활용하세요.

  • 메뉴에서 View → SQL Recall을 선택하면 최근 실행한 쿼리를 쉽게 다시 불러올 수 있습니다.
  • 원하는 쿼리를 즐겨찾기 형태로 관리할 수도 있습니다.

📌 3. 데이터 내보내기(Export) 기능

테이블 데이터를 Excel이나 CSV로 내보낼 때 유용한 기능입니다.

  • 원하는 테이블이나 쿼리 결과 위에서 우클릭 후 Export를 선택하여 손쉽게 내보낼 수 있습니다.
  • 내보내기 옵션에서 형식과 인코딩 등을 상세하게 설정 가능합니다.

📌 4. 데이터 비교(Data Compare) 기능

두 데이터베이스 또는 테이블의 데이터를 쉽게 비교하고 차이를 찾을 수 있습니다.

  • 메뉴에서 Tools → Compare → Data Compare를 선택하여, 빠르게 차이점을 확인할 수 있습니다.
  • 동기화 옵션을 통해 데이터를 손쉽게 맞출 수도 있습니다.

📌 5. ERD 다이어그램 자동 생성

ERD(Entity-Relationship Diagram)를 빠르게 생성하고 확인할 수 있습니다.

  • 메뉴에서 Database → Diagram을 선택하면 자동으로 ER 다이어그램을 만들어 줍니다.
  • 관계 및 구조 파악이 직관적으로 가능하여 DB 설계 및 유지보수에 큰 도움이 됩니다.

📌 6. 쿼리 결과 필터링 및 정렬

쿼리 결과 창에서 추가 필터링과 정렬 기능을 적극적으로 활용하면 편리합니다.

  • 결과창 헤더의 필터 아이콘을 클릭하면 특정 값만 빠르게 볼 수 있습니다.
  • 컬럼 헤더 클릭 시 간단히 오름차순/내림차순 정렬이 가능합니다.

📌 7. 단축키 활용으로 생산성 향상

자주 사용하는 단축키를 기억하면 더욱 빠르게 작업을 처리할 수 있습니다.

단축키설명
F5 쿼리 실행
Ctrl + D 선택한 줄 복제
Ctrl + Shift + F 쿼리 자동 정렬(포맷)
Ctrl + N 새 에디터 창 열기
Ctrl + F9 선택한 쿼리만 실행

📌 8. 다중 탭 환경 활용

Toad는 여러 탭으로 동시에 다양한 작업을 할 수 있습니다.

  • 탭을 활용하여 여러 쿼리와 데이터베이스를 동시에 작업하면, 작업 효율이 증가합니다.
  • 탭을 드래그하여 재정렬하거나 분리 창으로 볼 수도 있습니다.

🐸 정리하며

Toad for MySQL은 매우 강력하고 유연한 툴입니다. 위에서 소개한 팁들을 활용하여 보다 효율적이고 편리하게 데이터베이스 작업을 수행해 보세요. 작은 기능 하나도 적극적으로 사용하면 큰 생산성의 차이를 만들어낼 수 있습니다. 💡✨

728x90
반응형
728x90
반응형

안녕하세요

 

★ 테이블 생성쿼리

USE [test_db]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TB_TEST](
	[SEQ] [int] IDENTITY(1,1) NOT NULL,
	[TYPE] [varchar](5) NULL,
	[TITLE] [varchar](100) NULL,
	[CONTENTS] [varchar](2000) NULL,
	[ORDR] [varchar](5) NULL,
	[USE_AT] [varchar](1) NULL,
	[FRST_REGISTER_NM] [varchar](10) NULL,
	[FRST_REGISTER_PNTTM] [datetime] NULL,
	[LAST_UPDUSR_NM] [varchar](10) NULL,
	[LAST_UPDUSR_PNTTM] [datetime] NULL
) ON [PRIMARY]
GO

 

★ 다중 인서트 ( SEQ 컬럼은 1씩 자동 생성되게 했으므로 인서트구문에서 빠짐)

USE [test_db]
GO

INSERT INTO [dbo].[TB_TEST]
           ([TYPE]
           ,[TITLE]
           ,[CONTENTS]
           ,[ORDR]
           ,[USE_AT]
           ,[FRST_REGISTER_NM]
           ,[FRST_REGISTER_PNTTM]
           ,[LAST_UPDUSR_NM]
           ,[LAST_UPDUSR_PNTTM])
     VALUES
           ('TYPE_1', 'TITLE_1', 'CONTENTS_1', 1, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_1', 'TITLE_2', 'CONTENTS_2', 2, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_2', 'TITLE_3', 'CONTENTS_3', 3, 'N', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_2', 'TITLE_4', 'CONTENTS_4', 4, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_2', 'TITLE_5', 'CONTENTS_5', 5, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE())
GO

 

결과 (실패)

메시지 8152, 수준 16, 상태 30, 줄 4
문자열이나 이진 데이터는 잘립니다.
문이 종료되었습니다.

TYPE 컬럼길이가 varchar(5) 인데 insert 구문에서 길이값을 넘겨서 insert실패

DROP TABLE을 해서 새롭게 테이블을 재생성하거나

컬럼 길이값을 수정하는 방법 두가지가 있습니다.

 

★ 컬럼 길이값을 수정하는 방법

ALTER TABLE TB_TEST ALTER COLUMN TYPE varchar(10);

 

★ DROP & CREATE

USE [test_db]
GO


IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TB_TEST]') AND type in (N'U'))
DROP TABLE [dbo].[TB_TEST]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TB_TEST](
	[SEQ] [int] IDENTITY(1,1) NOT NULL,
	[TYPE] [varchar](10) NULL,  /* 변경 */
	[TITLE] [varchar](100) NULL,
	[CONTENTS] [varchar](2000) NULL,
	[ORDR] [varchar](5) NULL,
	[USE_AT] [varchar](1) NULL,
	[FRST_REGISTER_NM] [varchar](10) NULL,
	[FRST_REGISTER_PNTTM] [datetime] NULL,
	[LAST_UPDUSR_NM] [varchar](10) NULL,
	[LAST_UPDUSR_PNTTM] [datetime] NULL
) ON [PRIMARY]
GO

 

INSERT 구문 시작

USE [test_db]
GO

INSERT INTO [dbo].[TB_TEST]
           ([TYPE]
           ,[TITLE]
           ,[CONTENTS]
           ,[ORDR]
           ,[USE_AT]
           ,[FRST_REGISTER_NM]
           ,[FRST_REGISTER_PNTTM]
           ,[LAST_UPDUSR_NM]
           ,[LAST_UPDUSR_PNTTM])
     VALUES
           ('TYPE_1', 'TITLE_1', 'CONTENTS_1', 1, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_1', 'TITLE_2', 'CONTENTS_2', 2, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_2', 'TITLE_3', 'CONTENTS_3', 3, 'N', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_2', 'TITLE_4', 'CONTENTS_4', 4, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE()),
           ('TYPE_2', 'TITLE_5', 'CONTENTS_5', 5, 'Y', 'ADMIN',GETDATE(),'ADMIN2',GETDATE())
GO
728x90
반응형
728x90
반응형

DROP PROCEDURE IF EXISTS `TEST_STORED_PROCEDURE`;


DELIMITER //

-- 일반적으로 세미콜론(;)이 구문의 종료문자


-- DELIMITER 명령어로 구분문자(//)로 변경하고 

-- END;

-- //

-- DELIMITER; 종료선언


-- DELIMITER 명령어로 구분 문자(//)를 변경하고 나서 세미콜론을 넣어도 해당 명령어가 끊기지 않고 계속 이어집니다.



CREATE PROCEDURE `TEST_STORED_PROCEDURE`

(

  INOUT i_test_id             VARCHAR(20),              /* test ID */

  OUT o_result_cd               VARCHAR(2),            /* 응답코드 */

  OUT o_result_msg             VARCHAR(100)          /* 응답메시지 */

)


BEGIN

/******************************************************************************

   NAME:       TEST_STORED_PROCEDURE

   PURPOSE:    테스트 프로시저 

******************************************************************************/


  DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN

    SET o_result_cd   = '01';

    SET o_result_msg = '조회 요청 중 오류가 발생하였습니다.';

  END;

  

  DECLARE EXIT HANDLER FOR NOT FOUND BEGIN

    SET o_result_cd   = '02';

    SET o_result_msg = '요청한 id가 유효하지 않습니다.';

  END;

  

  SELECT TEST_NAME

  INTO o_name

  FROM TEST_TABLE

  WHERE TEST_ID = i_test_id;


  SET o_result_cd   = '00';

  SET o_result_msg = '정상처리되었습니다.';

  

END;

//

DELIMITER;




SQL 실행 테스트

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

SET @id= ' TEST';       


CALL TEST_STORED_PROCEDURE(

  @id

, @cd

      , @message

)

SELECT@id, @cd, @message;

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

728x90
반응형

+ Recent posts