Goldilocks JDBC Driver를 이용해 Spring boot 와 maven, Hibernate 를 사용한 구축 환경에서

GOLDILOCKS DB와 연동하는 과정을 설명한다.

 

웹 서버용 Tomcat, JAVA(JDK)가 설치되어 있어야 한다.


Chapter 1. 환경

 

[테스트 환경 - DB]

OS : Ubuntu 16.04.7 LTS
GOLDILOCKS : 22c.1.2

 

[테스트 환경 - Spring Boot]

OS : CentOS Linux release 7.8.2003
GOLDILOCKS Client : 22c.1.2
Spring Boot : 2.7.12
Maven : 3.9.2
Hibernate : 5.6.15 Final
JAVA : 11.0.19
Tomcat : 9.0.75



Chapter 2. Maven 설치

 

다음은 wget으로 maven 을 설치 및 심볼릭 링크를 생성하는 예시이다. 

$ wget http://apache.mirror.cdnetworks.com/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.tar.gz

$ tar -xzf apache-maven-3.9.2-bin.tar.gz 

$ sudo cp -R apache-maven-3.9.2 /usr/local/

$ sudo ln -s /usr/local/apache-maven-3.9.2 /usr/local/maven

 

관련 환경변수를 설정한다.

#maven

export M2_HOME=/usr/local/maven

export PATH=$PATH:$M2_HOME/bin

 

다음과 같은 명령어로 maven 버전 확인을 할 수 있다.

$ mvn -v

Apache Maven 3.9.2 (c9616018c7a021c1c39be70fb2843d6f5f9b8a1c)

Maven home: /usr/local/maven

Java version: 17.0.7, vendor: Oracle Corporation, runtime: /home/spring/package/jdk-17.0.7

Default locale: ko_KR, platform encoding: UTF-8

OS name: "linux", version: "3.10.0-1127.18.2.el7.x86_64", arch: "amd64", family: "unix"

 

.


Chapter 3. Spring boot 예제 생성

 

Spring boot 예제는 https://start.spring.io/ 에서 다운로드 받을 수 있다. 

다운받은 demo.zip 파일을 리눅스 서버로 복사한다.

 

다음은 예제 생성 예시이다.

Project : Maven 체크

Language : Java 체크

Spring Boot : 2.7.12 체크

Packaging : Jar 체크

Java : 17 체크

우측 Dependencies :

    Spring Web - WEB

    Spring Boot DevTools - DEVELOPER TOOLS

    Spring Data JPA - SQL



Chapter 4. Hibernate jar 설치 및 설정

GOLDILOCKS 는 Hibernate ORM 버전에 따라 GoldilocksDialect.java 파일을 제공한다.

($GOLDILOCKS_HOME/app_dev/Hibernate)

 

Hibernate jar 파일 설치하기

Hibernate jar 파일은

https://repo1.maven.org/maven2/org/hibernate/hibernate-core/ 에서 다운로드 받을 수 있으며

GoldilocksDialect.java 컴파일을 위해 

https://repo1.maven.org/maven2/javax/persistence/javax.persistence-api/2.2/ 에서

컴파일용 persistence 패키지를 다운받을 수 있다.

 

본 문서는 hibernate-core-5.6.15.Final.jar, javax.persistence-api-2.2.jar 기준으로 작성한다.

 

 

Hibernate jar 파일에 이식하기

다운로드 받은 Hibernate jar 파일에 Goldilocks 관련 클래스들을 이식하는 방법은 다음과 같다.

 

1. GoldilocksDialect.java 파일을 javac로 컴파일하여 class 파일을 생성한다.

$ javac -cp hibernate-core-5.6.15.Final.jar:javax.persistence-api-2.2.jar  GoldilocksDialect.java

 

다음과 같은 클래스들이 생성된다.
  ├──GoldilocksDialect$1.class

  ├──GoldilocksDialect.class

  └──GoldilocksIdentityColumnSupport.class

 

2. Hibernate jar 파일의 압축을 해제한다.

$ jar -xvf hibernate-core-5.6.15.Final.jar

 

3. 생성된 org/hibernate/dialect 디렉토리로 Goldilocks 관련 클래스들을 복사한다.

$ cp Goldilocks*.class org/hibernate/dialect/

 

4. Hibernate jar 파일로 다시 압축한다. 예시는 구분을 위해 goldilocks 라는 이름을 부여한다.

$ jar -cvf hibernate-goldilocks-5.6.15.Final.jar META-INF/MANIFEST.MF .



Chapter 5. 연동 환경 설정

chapter 3 에서 다운받은 demo 파일을 압축 해제한다.

$ unzip demo.zip 

 

demo 디렉토리에서 lib 디렉토리를 생성해 jar 파일을 복사한다.

goldilocks8.jar 파일은 GOLDILOCKS 패키지의 $GOLDILOCKS_HOME/lib 디렉토리에 동봉되어 있으며

hibernate jar 파일은 chapter 4에서 생성한 jar 파일이다.

$ pwd

/home/spring/sample/demo

 

$ mkdir lib

$ cp goldilocks8.jar /home/spring/sample/demo/lib/

$ cp hibernate-goldilocks-5.6.15.Final.jar /home/spring/sample/demo/lib/

 

$ ls -al /home/spring/sample/demo/lib

goldilocks8.jar

hibernate-goldilocks-5.6.15.Final.jar

 

pom.xml 에 두 jar 파일 디펜던시를 등록한다.

<dependency>

   <groupId>GOLDILOCKS</groupId>

   <artifactId>GOLDILOCKS_test</artifactId>

   <version> 22.1.2</version>

   <scope>system</scope>

   <systemPath>/home/spring/sample/demo/lib/goldilocks8.jar</systemPath>

</dependency>

<dependency>

   <groupId>hibernate</groupId>

   <artifactId>hibernate-goldilocks</artifactId>

   <version>5.6.15</version>

   <scope>system</scope>

   <systemPath>/home/spring/sample/demo/lib/hibernate-goldilocks-5.6.15.Final.jar</systemPath>

</dependency>

 

DB 접속 정보 및 tomcat 포트를 설정한다.

(src/main/resources/application.properties)

 

아래는 192.168.0.113 서버의 GOLDILOCKS DB로 24681 포트를 이용해 접속하는 예시이다.

spring.datasource.driver-class-name=sunje.goldilocks.jdbc.GoldilocksDriver

spring.datasource.url=jdbc:goldilocks://192.168.0.113:24681/test

spring.datasource.username=test

spring.datasource.password=test

 

spring.jpa.database-platform=org.hibernate.dialect.GoldilocksDialect

spring.jpa.properties.hibernate.show_sql=true

spring.jpa.properties.hibernate.format_sql=true

 

spring.jpa.hibernate.ddl-auto=create

 

server.port=9300



sample 예제

간단한 C/R/U/D 용 예제 java 파일은 다음과 같다.

모두 src/main/java/com/example/demo/ 에 위치시킨다.

 

java 파일은 다음과 같다.

  ├──BoardRepository.java

  ├──Board.java

  └──TestController.java



BoardRepository.java

package com.example.demo;

 

import org.springframework.data.jpa.repository.JpaRepository;

 

public interface BoardRepository extends JpaRepository<Board, Long>{

}




Board.java

package com.example.demo;

 

import javax.persistence.Entity;

import javax.persistence.Id;

 

@Entity

public class Board {

    @Id

    private int bno;

    private String subject;

 

    public Board() {

        super();

    }

 

    public Board(int bno, String subject) {

        super();

        this.bno = bno;

        this.subject = subject;

    }

 

    public int getBno() {

        return bno;

    }

    public void setBno(int bno) {

        this.bno = bno;

    }

    public String getSubject() {

        return subject;

    }

    public void setSubject(String subject) {

        this.subject = subject;

    }

    @Override

    public String toString() {

        return "Board [bno=" + bno + ", subject=" + subject + "]";

    }

}




TestController.java

package com.example.demo;

 

import java.util.List;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

 

@RestController

public class TestController {

    

    @Autowired

    private BoardRepository boardRepository;

    

@RequestMapping("/select")

    public List<Board> SelectAll(){

        return boardRepository.findAll();

    }

    @RequestMapping("/insert")

    public Board Insert(){

        Board valueToInsert =new Board(10,"Nam");

        return boardRepository.save(valueToInsert);

    }

    @RequestMapping("/delete")

    public String DeleteAll() {

        boardRepository.deleteAll();

        return "Delete succeeded.";

    }

    @RequestMapping("/count")

    public Long Count() {

        return boardRepository.count();

    }

}

 


Chapter 6. 프로젝트 실행

실행 명령어는 다음과 같다.

$ mvn spring-boot:run

 

..

[INFO] Attaching agents: []

23:21:53.885 [Thread-0] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@56346c86

 

  .   ____          _            __ _ _

 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \

( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \

 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )

  '  |____| .__|_| |_|_| |_\__, | / / / /

 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::               (v2.7.12)

 

..

 

Hibernate: 

    

    drop table if exists board cascade constraints

Hibernate: 

    

    create table board (

       bno number(10,0) not null,

        subject varchar(255) null ,

        primary key (bno)

    )





설정한 tomcat url 에서 다음과 같은 대시보드를 확인할 수 있다.

 

url 에 매핑한 문자를 입력하여 트랜잭션의 수행을 확인할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 


 

블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

Goldilocks JDBC Driver를 이용해서 Goldilocks와 전자정부프레임워크를 연동하고
표준 프레임워크 센터에서 제공 공통 컴포넌트(all-in-one) 개발 환경을 구축과정을 설명한다.

 

웹 서버용 Tomcat, JAVA(JDK)가 설치되어 있어야 한다.

 


Chapter 1. 환경

 

[테스트 환경 - DB]

OS : Ubuntu 16.04.7 LTS
GOLDILOCKS : 22c.1.2

 

[테스트 환경 - 전자정부프레임워크(eGov)]

OS : Windows 64 bit
GOLDILOCKS Client : 22c.1.2
eGovFrameDev : 4.1.0 Window 64 bit
egovframework-all-in-oneAllNew : 4.1.1
JAVA : 11.0.19 64 bit
Tomcat : 9.0.75 Window 64 bit




Chapter 2. 개발환경 및 공통 컴포넌트 설치

 

개발 환경 및 공통 컴포넌트는
https://www.egovframe.go.kr/home/main.do 에서 다운로드 받을 수 있다. 

상단 다운로드에서 원하는 버전을 선택하여 파일을 다운로드 받는다.
아래 화면은  홈페이지에서 개발환경 파일을 다운로드 받는 화면이다.

 

 

아래 화면은 홈페이지에서 공통 컴포넌트 파일을 다운로드 받는 화면이다.

 

 


Chapter 3. 연동 환경 설정

 

전자정부프레임워크 eclipse 실행

 

 

공통 컴포넌트 압축 해제 및 프로젝트 생성

다운로드 받은 배포파일의 압축을 푼다. 이후, 새로운 프로젝트를 생성한다.

[File] -> [Import]

[Maven] -> [Existing Maven Projects]

[Browse] -> all-in-one 압축해제 폴더(egovframework-all-in-oneAllNew)

 

eclipse 설정

이클립스 우측 상단의 퍼스펙티브를 변경한다.

[Open Perspective] -> eGovFrame

 



메이븐 환경을 초기화 한다.

프로젝트 우클릭 -> [Maven] -> [Update Project...]

[Force Update of Snapshots/Releases] 체크

프로젝트 우클릭 -> [Run As] -> [8 Maven install]

 

JRE 환경을 변경한다.

프로젝트 우클릭 -> [Properties] -> [Java Build Path] -> [Libraries]

기존 JRE 1.8 제거

[Add Library] 로 jdk-11.0.19 등록 -> [Apply and Close]

 

DB 접속 관련 환경 설정

글로벌 프로퍼티 값을 변경한다.

(src/main/resources/egovFramework/egovProps/globals.properties)

 

아래는 192.168.0.113 서버의 GOLDILOCKS DB로 24681 포트를 이용해 접속하는 예시이다.

# 운영서버 타입(WINDOWS, UNIX)

Globals.OsType = WINDOWS

 

# DB서버 타입

Globals.DbType = goldilocks

 

#GOLDILOCKS

Globals.goldilocks.DriverClassName=sunje.goldilocks.jdbc.GoldilocksDriver

Globals.goldilocks.Url=jdbc:goldilocks://192.168.0.113:24681/goldilocks

Globals.goldilocks.UserName=com

Globals.goldilocks.Password=xz4fmrSdr1vGGl6UtwPLwA%3D%3D



pom.xml 파일에서 GOLDILOCKS JDBC Driver 정보를 확인할 수 있다.

배포한 GOLDILOCKS Window Client 패키지에 동봉되어있는 goldilocks8.jar 를 사용한다.

($GOLDILOCKS_HOME/lib/goldilocks8.jar)

 

다음은 배포한 GOLDILOCKS JDBC Driver를 버전 정보를 명시하여 설정한 예시이다.

  • 파일명을 다음과 같이 변경한다.
    goldilocks8.jar 를
    goldilocks8-22.1.2.jar 로 변경

 

  • 디렉토리명을 다음과 같이 변경한다.
    src/main/webapp/WEB-INF/lib/project/goldilocks8/8.0.0/ 을
    src/main/webapp/WEB-INF/lib/project/goldilocks8/22.1.2/ 로 변경

pom.xml

        <!-- goldilocks driver -->

        <dependency>

            <groupId>project</groupId>

            <artifactId>goldilocks8</artifactId>

            <version>22.1.2</version>

        </dependency>



GOLDILOCKS 사전작업

테스트를 위해 com DB계정 생성 및 권한을 부여한다.

다음은 테스트를 위해 모든 권한을 com 계정에게 부여하는 예시이다.

create user com identified by com01;

grant all privileges on database to com with grant option;

commit;

 

이후 다음 sql 들을 com 유저로 수행해야 한다.

egovframework-all-in-one/script/ddl/goldilocks/com_DDL_goldilocks.sql

egovframework-all-in-one/script/comment/goldilocks/egov_goldilocks_comment.sql

egovframework-all-in-one/script/dml/goldilocks/com_DML_goldilocks.sql





Chapter 4. 프로젝트 실행

 

프로젝트를 실행한다.

프로젝트 우클릭 -> [Run As] -> [Run On Server]

 

[Apache] -> [Tomcat v9.0 Server] -> [Next >] -> [Browse]

tomcat 디렉토리 설정 -> [Finish]



 

설정한 tomcat url 에서 다음과 같은 대시보드를 확인할 수 있다.

 

 

테스트용 사용자 정보는 다음과 같다. (대소문자 유의)

 

구분 ID PW 비고
일반 사용자 USER rhdxhd12 영문으로 공통12
기업 사용자 ENTERPRISE rhdxhd12 영문으로 공통12
업무 사용자 TEST1 rhdxhd12 영문으로 공통12
  webmaster rhdxhd12 영문으로 공통12

 


 

블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

 

Microservice 와 Spring Cloud 소개

 

본문은 인프런 교육 영상 中

 

이도원 엔지니어님의

"Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)"

강의 기반 내용 정리 이며, 사용된 이미지의 출처는 해당 교육 영상의 이미지임을 밝힙니다.


Spring Cloud

 

Spring

- java 의 웹 프레임워크

프레임워크
어떠한 목적을 달성하기 위한 구조 클래스, 라이브러리, 리포지토리의 집합

 

- JSP, mybatis, jpa 등 java를 쉽게 사용하기 위한 오픈소스 웹 프레임워크

 

Spring Cloud

- MSA 시스템 개발/배포/운영을 지원하는 Spring 기반 개발 도구 및 프레임워크

 

 


History of IT System

 

  • 1960~1980s : Fragile, Cowboys
    • Mainframe, Hardware
    • 하드웨어 중심(사양,성격)에 맞춰 서비스 구성, 고가
    • 서비스 기능 수정 및 변경 어려움, 깨지기 쉬운 시스템
Fragile : 부서지기 쉬운

 

  • 1990~2000s : Robust, Distributed
    • Changes
    • '분산', 시스템 안정화
    • 서비스 변화에도 안정성, 성능높은 서비스
Robust : 강인한

 

  • 2010s~ : Resilient/Anti-Fragile, Cloud Native
    • 로컬->클라우드
    • 확정성, 안정성, 변화에도 탄력적 운영
Resilient : 탄력적인
 

 

Antifragile

 

다른 개발/환경보다 시스템 변화가 적고, 변화에 적용할 수 있고, 비용도 저렴

  • 네 가지 핵심
    1. Auto scaling : 자동 확장성( 리소스 사용량에 따라 자동으로 )
      • 예) 부하 사용량이 예측된다면(계절 쇼핑몰 등) 자동 scaling
    2. Microservices : 클라우드 네이티브 아키텍처/어플리케이션의 핵심
      • 기존의 하나의 거대한 서비스를 개별적인 모듈/기능을 독립적으로 개발/배포
      • 넷플릭스/아마존
    3. Chaos engineering
      • 예견된/예견되지 않은 불확실한 상황에서도 안정적인 서비스
      • 즉 실행 방법/규칙 등
    4. Continuous deployments
      • CICD - pipeline
      • 지속적인 통합/배포
      • 하나의 어플리케이션이 적게는 수십개, 많게는 수백개의 MS
pipeline 
한 데이터 처리 단계의 출력이 다음 단계의 입력으로 이어지는 형태로 연결된 구조
 

Cloud Native Architecture

 

  1. 확장 가능한 아키텍쳐
    • 시스템의 확장에 유연
    • 확장된 서버로 시스템의 부하 분산/가용성 보장
    • 시스템/서비스 애플리케이션 단위의 패키지(컨테이너 기반)
    • 모니터링
  2. 탄력적 아키텍쳐
    • 서비스 생성-통합-배포, 비즈니스 환경 변화에 대응시간 단축
    • 분할 된 서비스 구조
    • 무상태 통신 프로토콜
    • 서비스의 추가와 삭제를 자동으로 감지
    • 변경된 서비스 요청에 따라 사용자 요청을 동적 처리
  3. 장애 격리(Fault Isolation)
    • 특정 서비스에 오류가 발생해도 다른 서비스에 영향을 주지 않음
    • 장애 복구에 뛰어남

Cloud Native Application

1. Microservices

  • 개발 모델

2. CI/CD ( Continuous Integration, Continuous Delivery/Deployment )

  • 자동 통합/빌드/테스트/배포
  • 지속적인 통합(CI)
  • 통합 서버, 형상 관리, 빌드/테스트 도구
    • Jenkins, Team CI, Travis CI
  • 지속적인 배포(CD)
  • Delivery : 운영자의 수동 반영
  • Deployment : 자동 반영
  • Pipe line
  • 카나리배포/블루그린 배포
    • 카나리배포 : 95%는 이전 서비스 / 5%는 새로운 버전 서비스
    • 블루그린 배포 : 이전 버전(블루) -> 새로운 버전(그린) 으로 점진적 이전

3. DevOps

  • 고객이 원하는 최선의 결과물을 만드는 데 목적
  • 문제 발생 시 반영/재배포를 반복
  • 요구사항에 맞게 서비스 설계/구현/테스트/배포
  • 요구사항/개선사항은 언제든 변할 수 있으며 자주 테스트/피드백/업데이트 등을 거쳐 개발 과정동안 끊임없이 소통하며 진행할 수 있음
  • Cloud Native Application은 이러한 데브옵스의 과정을 더 잘 적용할 수 있는 어플리케이션
  • Development + QA + Operations
  • create/plan/verify/package/release/configure/monitor

 

4. Containers 가상화

  • 기존 전통 개발 : 하드웨어->OS->APP
  • 가상화 개발 : 하드웨어->OS->VM->OS->APP
  • 컨테이너 개발 : 하드웨어->OS->컨테이너->APP
  • 하나의 어플리케이션을 구성하는 MSA를 클라우드 환경에 배포하고 사용하기 위해
  • Cloud Native Application의 핵심
    • 하드웨어 가상화보다 적은 리소스를 사용
    • 서비스들은 가볍고 빠르게 운영할 수 있음

 


12 Factors( https://12factor.net/)

 

paas 를 제공하는 Heroku라는 개발회사에서 제시한 12가지로,

cloud native application 개발/운영 시 고려할 항목 정리

 

  1. Base code
    • 형상 관리(버전관리를 위해 코드를 한 곳에서 배포)
    • 코드의 통일적인 관리
  2. Dependency Isolation (종속성)
    • 각 MS는 자체 종속성을 보유
    • 변경 시 전체 시스템에 영향을 주지 않아야 함
  3. Configurations (구성 정보)
    • 코드 외부에서 관리 도구를 통해 필요한 작업들을 제어
    • 동일한 배포가 올바른 구성이 적용된 환경에서 전파될 수 있음
  4. Linkable backing services (서비스 지원)
    • 보조 서비스(DB,캐시,메시지서비스,브로커)를 통해 추가 기능을 지원해야 함
    • 특정 벤더에 코드 디펜던시가 없어야 함
  5. Stages of Creation (빌드/릴리즈/실행환경의 엄격한 분리)
    • 고유한 ID 태그
    • 롤백기능(원복)
    • CI/CD 로 자동화
  6. Stateless Processes
    • 하나의 MS는 다른 MS들과 독립적으로 실행
Stateless : 무상태
각각의 서비스는 클라이언트와 무관하게 요청에 대한 응답만 처리함

 

7. Port Binding

  • 각각의 MS는 다른 MS와의 통신을 위한 포트

8. Concurrency (동시성)

  • 하나의 서비스가 수많은 여러가지 인스턴스에 나뉘어(복사되어) 운영

9. Disposability

  • 서비스 인스턴스를 등록/삭제/확장/종료 가능해야 함

10. Development & Production Parity

  • 개발과 배포단계를 구분
  • 배포 시 다른 작업/환경에 영향이 없어야 함

11. Logs

  • MS에 의해 생성된 로그를 관리하는 도구 필요

12. Admin Processes for Eventual Processes

  • 리소스, 실시간 관리 도구가 있어야 함
  • 모니터링, 리포팅, 데이터 분석

 

 

Pivotal 이 3개의 요소를 추가함

  1. API first
    • API 형태로 서비스 제공
    • 사용자는 어떤 형태로 개발할지 고민
API
정의 및 프로토콜 집합을 사용하여 두 소프트웨어 구성 요소가 서로 통신할 수 있게 하는 메커니즘

 

2. Telementry

  • 모든 지표는 수치화/시각화되어 관리되어야 함

3. Authentication and authorization

  • 인증

 


애플리케이션 방법론 : Monolithic vs MSA

 

Monolith

어플리케이션 개발에 있어 필요한 모든 요소를 하나의 커다란 소프트웨어 안에 포함시켜 개발

DB/비즈니스/프론트엔드 모든 서비스가 하나의 어플리케이션에서 유기적으로 연결되어 작동/배포, 서로 의존성을 가짐

시스템의 일부 수정 시에도 전체 어플리케이션 빌드/테스트/패키징 필요

"하나의 건축물"

 

MSA

  • Netflix의 MSA 구성도
  • 파란색 : 서비스간 연동/통신
  • 초록색 : Netflix 서비스를 구축하는 MS

 

어플리케이션을 구성하는 요소 및 서비스를 분리하여 개발/운영

유지보수, 변경 적용시 유리

잘게 쪼개진 여러 서비스들의 묶음 비즈니스 중심으로 구축, 완전히 자동화되어 배포

최소화된 중앙 집중 관리, 다른 프로그래밍 언어, 다른 db 스토리지

서비스의 기능과 종류에 맞춰 언어를 선택, 각각의 서비스는

각 api를 통해 제어 -> 통일된 언어가 필요없음

서버 사이드 개발 자바 하드웨어 제어 C/C++ 데이터분석/머신러닝 파이썬 서버의 비동기 서비스 노드js

서비스 요청에 대한 통일된 gateway, 서비스들의 등록/검색/부하분산/대처/동기화 등 매커니즘이 필요

Gateway : 네트워크에서 서로 다른 통신망, 프로토콜을 사용하는
네트워크 간의 통신을 가능하게 하는 소프트웨어 즉 다른 네트워크로 들어가는 입구 역할을 하는 네트워크 포인트

 

크로스플랫폼(갤럭시,워치,탭,PC 등)

  • 장비,해상도,입력방식 등 다름
  • 변화가 많은 클라이언트 단말기는 프론트엔드 개발 회사에 맡기고
  • 서버는 서비스/비즈니스를 처리하는 내용을 통일된 폼으로 클라이언트 단말기에 전달만 하면 됨
  • 또한 서비스의 경계에 맞는 형태로 개발/테스트/배포 됨으로써 하나의 어플리케이션을 구성해야하는
  • 서비스들이라 할지라도 서로 다른 서비스들과 독립적으로 관리할 수 있음

Microservice

 

"Everything should be a microservice"

Q1) Multiple Rates of Change : 어느 정도 변화가 생기는가?(공수)

Q2) Independent Life Cycles : 독립적으로 개발/운영 되도록 서비스 경계가 되어 있는가?

Q3) Independent Scalability : 서비스 유지하면서 확장이 가능한가?

Q4) Isolated Failure : 오류 사항에 대해 독립적인가?

Q5) Simplify Interactions with External Dependencies : 외부 종속성과의 상호 작용이 단순한가?

Q6) Polyglot Technology : 여러가지 언어/스토리지 를 지원하는 패러다임(polyglot)기술이 있는가?

 

Microservice Team Structure

  • Two Pizza team (4~5명)
  • 커뮤니케이션 비용
  • 개발/테스트/운영/배포 를 위한 최소 단위

SOA(Service Oriented Architecture) vs MSA

 

SOA

서비스 인터페이스를 통해 소프트웨어 구성 요소의 재사용/상호 운영성을 가능하게 하는 구조

즉, 서비스는 인퍼테이스/아키텍처를 공통적인 것을 사용하므로

기능추가/재개발/복제 등 과정에서 신속하게 통합 가능

 

서비스 공유 지향점

SOA - 재사용을 통한 비용 절감, 서비스 공유 최대화

MSA - 서비스 간의 결합도를 낮추어 변화에 능동적으로 대응

 

기술 방식

SOA - 공통의 서비스를 ESB(Enterprise Service Bus) 에 모아 사업 측면에서 공통 서비스 형식으로 제공

MSA - 독립된 서비스가 노출된 REST API를 사용

Rest API
두 시스템이 인터넷을 통해 정보를 안전하게 교환하기 위한 인터페이스

 

 

'IT > ETC' 카테고리의 다른 글

[ETC] :: JSON  (0) 2020.02.17
블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

[Cluster] :: ClustrixDB

IT/Cluster 2020. 5. 13. 18:14

ClustrixDB

0. INDEX

0. INDEX
1. Concepts
2. Key-Features
3. Query Processing Step
4. Architecture
5. Why we use ClustrixDB?



1. Concepts

ClustrixDB는 Scalable하고, Shared-Nothing의 데이터 분배 구조이며
내결함성을 보유하고 간단한 SQL 인터페이스에 의해 실행 가능한 NewSQL이다.
주로 온라인 트랜잭션(OLTP)에 최적화되어 있으며 MySQL과 호환성도 제공한다.


NewSQL

  • NewSQL의 필요성
    • 용량이 크고 다양한 데이터가 늘어나며 기존의 RDBMS와 NoSQL로 처리하는 데 한계가 나타남.
    • 대용량 데이터 처리와 높은 수준의 데이터 정합성을 필요로 하는 분야에서 적합.
  • NewSQL의 정의
    • 표준으로 내려온 정의는 없으며 가장 많이 언급된 내용을 살펴보면,
      SQL 지원, ACID 준수, 성능 개선을 가지고 NoSQL의 특징인 확장성과 가용성을 갖춘 DBMS
      
      SQL 기반 상호 작용, 트랜잭션에 대한 ACID 지원, 비공유 구조,
      비잠금 동시성 제어, Node단위의 고성능 DBMS
      
  • RDBMS, NoSQL, NewSQL 비교
구분RDBMSNoSQLNewSQL
Scale-outXOO
HAXOO
ReplicationXOO
PerformanceXOO
SQL 지원OXO
RelationalOXO
JoinOXO
ACIDOXO






2. Key-Features

  • Scalable
  • High Concurrency OLTP( Online Transaction Processing )
  • Automatic Data Distribution
  • Fault-Tolerant
  • Flexible Deployment Options
  • MySQL Compatible
  • Easy to Migrate from MySQL


Scalable

shared-nothing architecture이라 선형적으로 노드를 늘릴 수 있다.
또한 각 노드가 각각 다른 데이터를 가진다.
읽기/쓰기는 여러 노드로 분산되어 contention을 줄인다.
게다가 데이터와 쿼리의 실행 모두 자동으로 분산한다.

노드의 add는 Flex Up, reduce는 Flex Down으로 칭한다.
두 연산 모두 백그라운드에서 자동 재분배하기 때문에
온라인 상태인지, DB를 사용 가능 한지에 대해 사용자는 신경쓸 필요 없다.


High Concurrency OLTP

ClustrixDB는 large-scale OLTP에 대해 설계되었다. ACID는 물론이고,
앞서 설명한 바와 같이 단순하게 노드를 추가하는 것만으로 read/write에 대해 high throughput을 가진다.
클러스터 환경에서 데이터와 워크로드를 나눔으로써 단일 인스턴스 DB보다 높은 병렬적 효율을 가진다.


Automatic Data Distribution

ClustrixDB의 핵심 컴포넌트 중 하나인 Rebalancer는 백그라운드에서 데이터의 분배에 대해 manage한다.
예상치 않은 failure에 대해 Rebalancer가 자동으로 처리한다.


Fault-Tolerant

내결함성을 염두하고 설계되었으며, 그렇기 때문에 data loss를 막을 수 있다.


Flexible Deployment Options

다양한 플랫폼에서 유연하게 배포 가능하다.

  • CentOS 7.4 이상
  • 클라우드( AWS, Rackspace, Azure )
  • 기타 하드웨어


MySQL Compatible

SQL, DML, DDL, trigger, stored procedure( PSM )에 대해 MySQL 구문을 사용한다.


Easy to Migrate from MySQL

MySQL을 호환하므로 MySQL 툴을 가지고 ClustrixDB로의 Migration도 쉽게 가능하다.



3. Query Processing Step

http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/111.PNG


  1. 노드가 선택되고, GTM( Global Transaction Manager )이 노드간의 처리를 위해 corrdination을 수행한다.
    ( A node is chosen and the Global Transaction Manager( GTM ) performs coordination for processing across nodes. )
  1. Sierra DB 엔진이 파싱하고, 각 SQL statement를 컴파일 하고 분배 수행의 최적 path를 선택한다.
    ( The Sierra Database Engine parses and compiles each SQL statement and chooses an optimal path for distributed execution. )
  1. Executable한 프로그램 fragment들은 클러스터간에 분산되고 다른 노드들에서 실행된다.
    ( Executable program fragments are distributed across the cluster and executed on different nodes. )
  1. 프로그램 fragments들에 의한 결과가 GTM 노드로 반환된다.
    ( Results from the program fragments are returned to the GTM node. )
  1. GTM 노드는 모으고 쿼리의 결과를 최종 사용자에게 반환한다.
    ( The GTM node assembles and returns query results to the end user. )


Global Transaction Manager

ClustrixDB 에서의 쿼리 처리는 일반적으로 클러스터간 커넥션을 분산하는 Load Balancer를 통해
클러스터의 한 노드가 GTM( Global Transaction Manager )으로 선택될 때 시작한다.

이후 GTM은 쿼리 실행 단계를 지시함으로써 트랜잭션의 모든 측면을 관리하고,
각 단계가 성공적으로 완료되었는지 확인한 뒤 쿼리 결과를 caller에게 반환하기 전 수집, 마무리 한다.

ClustrixDB는 쿼리를 실행가능한 쿼리 fragment들로 컴파일하고 GTM은 실행을 위해 적절한 노드(들)로 분배한다.
중간 결과가 나오면 GTM에 반환한다.
모든 쿼리 fragments들이 성공적으로 실행되면, GTM은 결과를 finalize하고
client 혹은 application 혹은 사용자에게 그 결과를 반환한다.


Rebalancer

ClustrixDB의 데이터가 이전에 클러스터 전체에 분배되지 않았다면, 분배 프로세싱은 불가능하거나 필요하지 않다.
이를 위해 ClustrixDB는 Rebalancer에 의해 관리되는 전매 특허의 데이터 분배 방법을 사용한다.
Rebalancer는 크러스터 내 데이터를 정렬해 read/write가 항상 균형을 유지하도록 한다.
또한 내결함성을 보장하기 위해 클러스터 전체에 여러 데이터 사본(replica)을 유지관리한다.
만약 노드가 예상치 못한 실패로 인해 손상되어도 데이터의 손실은 없다.
Rebalancer가 알아서 replica가 생성 및 유지되도록 자동으로 보장 한다.
또한 데이터베이스가 온라인 상태를 유지하는 동안 데이터가 추가될 새로운 노드로의 데이터를 리밸런싱하고,
제거할 노드에서 데이터를 옮김으로써 클러스터의 사이즈 변경을 수용한다.

Rebalancer는 컨시스턴트 해싱 알고리즘을 사용해 각 테이블 row를 해당 테이블의 주어진 slice로 할당하고,
모든 slice 맵을 모든 노드로 제공한다.
이를 통해 ClustrixDB가 관련된 데이터의 위치를 빠르고 쉽게 확인할 수 있다.
Rebalancer는 진행중인 production processing을 방해하는 일 없이 백그라운드에서 지속적으로 실행된다.

데이터가 sliced되고 클러스터의 수많은 노드에 분산되지만 데이터베이스 테이블은 항상 애플리케이션 상에서
single logical unit으로 나타난다.
Clustrix는 간단한 SQL 인터페이스를 사용하고, 분산 데이터에 액세스하기 위해 특별한 애플리케이션 프로그래밍도 필요하지 않다.


http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/222.PNG


Sierra Database Engine

Sierra는 쿼리 플래닝과 실행을 처리하는 ClustrixDB의 SQL 엔진이다.
Sierra는 분산된 shared-nothing 환경에서 수행할 수 있도록 특별하게 설계되었다.
분산된 데이터에 대한 수행을 최대한 효율적으로 수행할 수 있다.
Sierra DB 엔진은 다음 두 가지 파트를 포함한다.

  • Sierra Parallel Planner(병렬 플래너)는 SQL statement의 최적 수행 플랜을 결정한다.
  • Sierra Distributed Execution Engine(분산 실행 엔진)은 이러한 계획을 기반으로 쿼리 fragment들을 실행하고
    중간 결과를 제공한다.


Sierra Parallel Planner

Sierra Parallel Planner는 확률 통계, 데이터 볼륨,
인덱스 및 쿼리 연산의 오버헤드를 사용해 가장 효율적인 쿼리 플랜을 결정하는 cost-based 옵티마이저이다.
이 Sierra Parallel Planner의 주요 차별화된 특징은 클러스터 전체의 데이터 분배를 고려하며
이 플랜을 결정하는 데에 있다.


http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/333.PNG


Sierra Distributed Execution Engine

Sierra Planner가 최적의 쿼리 플랜을 결정하면, 이 플랜은 machine-executable 쿼리 fragment들로 컴파일된다.
이러한 컴파일된 쿼리 fragment들은 클러스터 내의 다른 노드들 간 실행되고, 효율성과 실행 동시성이 상승한다.
각각의 노드 실행이 완료되면 그 결과가 GTM 노드에 반환되고, 부분 결과들을 종합해 최종 결과 셋을 사용자에게 반환한다.

aggregate 수행 또한 분산된다.
계산은 부분 aggregate( SUM, MAX, MIN, AVG 등 )가 먼저 계산된다는 점을 제외하고
다른 쿼리들과 동일하게 fragmented되고 분산된다.
중간 결과는 GTM에 의해 통합되어 최종 결과를 생성한다.


http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/444.PNG


Conclusion

ClustrixDB는 자동 데이터 분산, 정교한 쿼리 플래너 및 분산 실행 모델을 사용해 ACID 호환 RDBMS에서
확장성(Scalability), 동시성(Concurrency)를 제공한다.

이를 달성하기 위해 ClustrixDB는 다른 MPP( Massively Parallel Processing ) DB에서 사용하는 많은 기술들을 사용한다.
분산 트랜잭션을 해결하기 위해 Paxos를 사용하고, MVCC를 사용해 트랜잭션 충돌을 방지한다.

설명한 주요 구성 요소를 통해 ClustrixDB는 분산 실행에 간단한 SQL 인터페이스를 제공하며 동시에
확장성, 효율성, 내결함성을 제공한다.


4. Architecture

Data Distribution


ClustrixDB Distribution Concepts
 

Representation


각 테이블은 하나 이상의 인덱스를 포함하는데,
Clustrix DB는 내부적으로 이 인덱스들을 참조하며, 해당 인덱스를 테이블의 representation이라 한다.
각 representation은 자신의 distribution key( shard key )를 소유하며, 이는
한 테이블의 데이터를 slice하는 데 여러 독립적인 키들을 사용한다는 것을 의미한다.
이 점은 단일 키로 테이블들을 slice하는 다른 DB 시스템과 사뭇 다르다.

각각 테이블들은 primary key를 소유해야만 한다.
만약 정의하지 않았으면 자동으로 hidden primary key를 생성한다.
base representation은 primary key에 의해 정렬된 테이블들의 모든 column을 포함한다.
Non-base representation은 테이블의 몇몇 column을 포함한다.
 

Slice


ClustrixDB는 consistent hashing을 사용해 각 representation을 논리적 slice의 모음으로 나눈다.
consistent hasing을 사용함으로써, 재해싱 없이 각각 개별 slice로 split 할 수 있다.
 

Replica


ClustrixDB는 fault tolerance와 availability를 위해 다수의 복제본을 유지한다.
분배된 서로 다른 노드들에 각각의 논리적 slice의 replica가 두 개 이상 존재한다.
이 replica의 개수 변경도 지원한다.
(쓰기작업에 대해 중간 정도의 성능 영향, 읽기작업에 대해 무시할 수 있는 성능 영향)
 


  • Representation

http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/11.PNG

  • Slice

http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/22.PNG

  • Replica

http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/33.PNG


Consistency

ClustrixDB는 다음과 같은 일관성 접근을 취한다.

  • 복제의 동기화
    파티셔닝된 모든 노드들은 before/after acknowledge를 제공하며, 쓰기작업은 병렬적으로 수행된다.
  • Paxos 프로토콜이 분산 트랜잭션 해결에 사용된다.
  • read에 lock이 없는 MVCC 지원


Paxos 프로토콜

신뢰할 수 없는 프로세서들의 네트워크에서 합의 문제를 해결하기 위한 프로토콜 그룹


Concurrency Control

ClustrixDB는 MVCC와 2 Phase Locking으로 데이터를 관리한다.

  • Visibility Rules
    • xid : 트랜잭션 스타트 id
    • iid : 호출 시작 id
    • cid : 커밋 id

http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/55.PNG


즉, insert의 cid보다 iid나 xid가 높으면 해당 insert 내용을 볼 수 있다.


Fault Tolerance

  • Built-in Fault Tolerance : 모든 데이터는 2개 이상 복제본을 유지하므로 자동으로 복구가 가능하다.
  • Deploying Across Zones : 복제본을 다른 zone( AWS Availability Zones, 다른 server rack, 다른 네트워크, 파워소스 등 )
    에 구성해 결함을 방지할 수 있다.
  • Using Replication : disaster 복구 사이트를 설정해 치명적인 오류를 복구할 수 있다.
  • MAX_FAILURES : 복제할 replica 갯수를 설정할 수 있다.


Rebalancer

Rebalancer는 클러스터의 healthy한 데이터 분배를 유지보수 하는 자동 시스템이다.
주 용도는 "unhealthy"한 데이터 respond에 대한 modify이다.

  • Healthy Cluster
    • 적절한 수의 slice를 가진 representation
    • 저장 장치에 잘 분배된 Replica
    • decommissioned 노드에 대해 배치하지 않는 Replica
  • 다양한 데이터에 대한 처리
    • 초기 데이터 : 노드에 일률적으로 slice 데이터들을 분배
    • 데이터 증가 : 큰 slice 데이터를 작은 slice로 분할 및 분배
    • Flex Up/Down : 노드 추가/삭제에 따라 slice 데이터 재분배
    • 노드 손상시 : 손상된 노드의 slice 데이터 복제를 통해 손실노드 데이터 재보호
    • 데이터 몰림(Skewed Data) : 각 노드에 균일하게 재배포
    • 자주 사용되는 데이터 : 빈번한 요청이 있는 slice 데이터를 찾아 노드간 재분배
  • Flex up 노드 분배 예시

before
http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/44-1.PNG

after
http://192.168.0.10:8000/intranet/raw-attachment/wiki/anbo_seminar_clustrixDB_investigation/44-2.PNG




5. Why we use ClustrixDB?

ClustrixDB는 여러 서버를 결합하여 강력한 단일 데이터베이스 서버로 만든다.
애플리케이션을 수정하면서까지 샤딩이나 복제를 하기 싫을 때 사용할 수 있다.
기본적으로 데이터베이스 확장에 대해서 다음과 같은 작업들이 필요하다.

  • 더 큰 서버
  • 동기/비동기 복제 클러스터
  • 데이터베이스 샤딩

하지만 ClustrixDB는 복제(Replication) 또는 샤딩(Sharding) 없이 확장할 수 있다.

  • 읽기/쓰기/저장 확장성
  • App 변경 없음
  • 자동 HA
  • 쉬운 설치








마침.

블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

[ETC] :: JSON

IT/ETC 2020. 2. 17. 15:47

JSON( JavaScript Object Notation )

Concepts

  • '속성-값' 쌍 또는 '키-값' 쌍으로 이루어진 개방형 표준( Opened Standard )1) 데이터 포맷이다.
    • 이 값 하나 하나를 리터럴(literal), 키-값 쌍을 프로퍼티(property)라 한다.
  • 브라우저/서버 통신을 위해, 넓게는 XML을 대체하는 주요 데이터 포맷으로.
    특히 인터넷에서 자료를 주고 받을 때 그 자료를 표현하는 방법으로 알려져 있다.
  • 자료의 종류에 큰 제한은 없으며 특히 컴퓨터 프로그램의 변수값을 표현하는 데 적합하다.
  • 자바스크립트 언어로부터 파생되어 자바스크립트의 구문 형식을 따르지만,
    실제로는 프로그래밍 언어나 플랫폼에 독립적이다.


개방형 표준( Opened Standard )1)

기술에 대한 표준 문서가 공개되어 있으며 사용이 자유롭다.
상황에 따라 다른 정의가 존재하며, 표준 단체, 국가마다 서로 다른 정의를 가질 수 있다.


사용 목적

  • 주로 서버에서 클라이언트로 데이터를 보낼 때 사용하는데,
    서버측에서는 클라이언트가 사용하는 언어에 관계 없이 일정한 패턴을 지닌 데이터를 생성해 전송하면
    클라이언트는 그 데이터를 해석해 자기만의 방식으로 가공해 사용할 수 있다.
  • 웹 초기 시절부터 사용한 XML과 비교하자면,
    이 XML은 헤더, 태그 등의 요소들로가독성이 떨어지며, 비교적 용량을 많이 잡아먹는다는 단점이 있다.
    이에 대응해 XML보다 훨씬 간결하고, 가벼운 용량의 양식으로 JSON이 각광을 받고 있다.



Advantage

  • 텍스트로 이루어져 있어 사람이 읽고 쓰기 쉽다.
  • XML에 비해 구문이 더 짧고 배열을 사용할 수 있다.
  • 프로그래밍 언어와 플랫폼에 독립적이므로, 서로 다른 시스템간에 객체를 교환하기에 좋다.



Data type

  • 수(Number) : 정수, 실수, 지수 ( 8진수나 16진수 등의 표현법은 제공하지 않음 )
    12
    -3.14
    1.234e+5
    
  • 문자열(String) : 큰따옴표(")로 구분되는 유니코드 문자
    "anbo"
    "한글"
    
  • 참/거짓(Boolean) : 기본적으로 true와 false를 소문자로만 표기한다.
    true
    false
    
  • NULL : 아무런 값도 가지고 있지 않으며, 소문자로 표기해야 한다.
    null
    
  • 객체(Object) : 프로퍼티의 집합으로, 중괄호{}로 나타낸다.
    이름은 항상 문자열이며, 값은 JSON 데이터 타입이다.
    객체 안에 객체가 포함되는 계층 구조도 가능하며, 모든 값들은 쉼표(,)로 구분한다.
    { string:value [, string:value] [, string:value] ... }
    
    {
        "월": "January",
        "제목": "Survey",
        "참여여부": false
    }
    
  • 배열(Array) : 여러 개의 데이터가 순서를 가지고 나열된 집합이며 대괄호[]로 나타낸다.
    배열의 각 요소는 JSON의 데이터 타입이다.
    객체와 달리 배열은 데이터의 값만을 나열하며, 쉼표(,)로 구분한다.
    배열의 인덱스는 언제나 0부터 시작하며, 여러 타입의 배열 요소를 가질 수 있다.
    [ value [, value] [, value] ... ]
    
    {
        "kpop":[
            "METEOR",
            "아무노래",
            {
                "age": "25",
                "year": "2020",
                "etc": null
            }
        ]
    }
    

Example

Ubuntu 에서 JavaScript로 진행한 간단한 테스트 예제

  • 한 사람에 관한 정보를 갖는 JSON 객체
    • test.js
      console.log( "START" );
      
      var anbo = { "이름": "안보현",
                   "나이": 29,
                   "특기": [
                       "독서",
                       "피아노"
                   ],
                   "가족관계": {
                       "#": 3, 
                       "아버지": "0",
                       "어머니": "1",
                       "형": "2"
                   },
                   "회사": "선재소프트"
                 }
      
      console.log( anbo );
      console.log( "FINISH" );
      
    • terminal
      [anbo@h JavaScript]$ node test.js
      START
      { '이름': '안보현',
        '나이': 29,
        '특기': [ '독서', '피아노' ],
        '가족관계': { '#': 3, '아버지': '0', '어머니': '1', '형': '2' },
        '회사': '선재소프트' }
      FINISH
      



Validation

  • JSON 스키마는 다음과 같은 세 가지 검증(validation) 과정을 거친다.
    1. 데이터 타입이 정확한가
    2. 필수로 받아야 하는 데이터가 포함되어 있는가
    3. 데이터가 유효한 범위 내에 있는가
  • 이러한 검증 기준을 모두 키워드(keyword)를 이용해 직접 명시할 수 있다.
  • 검증 키워드
    • 데이터에 대한 정보를 나타내는 검증 키워드
      • type : 데이터의 타입
      • properties : 데이터 이름-값 쌍
      • required : 배열의 모든 요소를 프로퍼티로 가지고 있는지
      • minimum : 최솟값 이상의 숫자만
      • maximum : 최댓값 이하의 숫자만
      • multipleOf : 명시한 숫자의 배수만
      • maxLength : 명시한 최대길이 이하의 문자열만
      • minLength : 명시한 최소길이 이상의 문자열만
      • pattern : 명시한 정규 표현식
    • 스키마에 대한 정보를 나타내는 메타 데이터 키워드
      • title : 제목
      • description : 설명
      • default : 기본값
    • 예시
      {
          "title": "선재소프트 스키마",
          "description": "이 스키마는 선재소프트에 대한 데이터를 검증하기 위해 작성된 스키마이다.",
          "type": "object",
          "properties": {
                  "name": {"type": "string"},
                  "age": {"type": "integer"}
                  "team": {
                      "teamName": {"type": "string"},
                      "job": {"type": "string"}
                  }
          }
      }
      
  • 문자열 검증의 경우, pattern 키워드를 사용해 정규 표현식 검증을 할 수 있다.
    1개 이상의 영어 소문자인지 검증하는 예제
    
    {
        "type": "string",
        "pattern": "[a-z]+"
    }



스키마 결합

  • JSON 스키마에서 다음과 같은 키워드를 사용해 여러 스키마들을 결합할 수 있다.
    • allOf
      • 명시된 배열에 나열된 모든 JSON 스키마를 검사하며, 배열에 나열된 검증을 모두 통과해야한다.
        해당 문자열의 데이터 길이가 3 이상 5 이하를 검사하는 예제
        
        {
            "allOf": [
                {"minLength": 3},
                {"maxLength": 5}
            ]
        }
        
    • anyOf
      • 명시된 배열에 나열된 모든 JSON 스키마를 검사하며, 배열에 나열된 하나 이상의 검증을 통과해야 한다.
        해당 데이터가 문자열 혹은 숫자인지 검사하는 예제
        
        {
            "anyOf": [
                {"type": "string"},
                {"type": "number"}
            ]
        }
        
    • oneOf
      • 명시된 배열에 나열된 모든 JSON 스키마를 검사하며, 배열에 나열된 오직 하나의 검증을 통과해야 한다.
        해당 데이터가 숫자이면서 3의 배수이거나, 숫자이면서 4의 배수인지 검사하는 예제
        
        {
            "oneOf": [
                { "type": "number", "multipleOf": 3 },
                { "type": "number", "multipleOf": 4 }
            ]
        }
        
    • not
      • 명시된 스키마를 만족하지 않는 데이터만을 검사한다.
        해당 데이터가 문자가 아닌지 검사하는 예제
        
        {
            "not": {
                "type": "string"
            }
        }
        



Examples

  • Basic
    {
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city":           { "type": "string" },
        "state":          { "type": "string" }
      },
      "required": ["street_address", "city", "state"]
    }
    
  • Product 스키마
    { 
      "name":"Product", 
      "properties": 
      { 
        "id": 
        { 
          "type":"number", 
          "description":"Product identifier", 
          "required":true 
        }, 
        "name": 
        { 
          "description":"Name of the product", 
          "type":"string", 
          "required":true 
        }, 
        "price": 
        { 
          "type":"number", 
          "minimum":0, 
          "required":true 
        }, 
        "tags": 
        { 
          "type":"array", 
          "items": 
          { 
            "type":"string" 
          } 
        } 
      } 
    }
    
  • allOf
    스키마 
    {
      "definitions": {
        "address": {
          "type": "object",
          "properties": {
            "street_address": { "type": "string" },
            "city":           { "type": "string" },
            "state":          { "type": "string" }
          },
          "required": ["street_address", "city", "state"]
        }
      },
    
      "allOf": [
        { "properties": {
            "type": { "enum": [ "residential", "business" ] }
          }
        }
      ]
    }
    
  • Data의 추가 및 삭제( Ubuntu 에서 JavaScript로 진행 )
    • test.js
      var movie = {
          "title": "Avengers - End game",
          "actor": [
              "Robert Downey Jr.",
              "Chris Evans",
              "Scarlett Johansson"],        
          "director": "Russo brother"
      }
      
      console.log( "###############################" );
      console.log( "START" );
      console.log( "###############################" );
      console.log( " " );
      
      console.log( "< object movie >" );
      console.log( movie );
      
      console.log( " " );
      console.log( "###############################" );
      console.log( "AVENGERS's 4th series!" );
      console.log( "###############################" );
      console.log( " " );
      console.log( "TITLE : " + movie.title );
      console.log( "ACTOR : " + movie.actor[0] );
      console.log( "        " + movie.actor[1] );
      console.log( "        " + movie.actor[2] );
      
      movie.actor[3] = "Jeremy Renner";
      
      console.log( "        " + movie.actor[3] );
      console.log( "DIRECTOR : " + movie.director );
      
      movie.year = 2019;
      
      console.log( "YEAR : " + movie.year );
      console.log( " " );
      console.log( "###############################" );
      console.log( " " );
      
      console.log( "< object movie >" );
      console.log( movie );
      
      console.log( " " );
      console.log( "###############################" );
      console.log( "FINISH" );
      console.log( "###############################" );
      
    • terminal
      [anbo@h JavaScript]$ node test.js
      ###############################
      START
      ###############################
      
      < object movie >
      { title: 'Avengers - End game',
        actor: [ 'Robert Downey Jr.', 'Chris Evans', 'Scarlett Johansson' ],
        director: 'Russo brother' }
      
      ###############################
      AVENGERS's 4th series!
      ###############################
      
      TITLE : Avengers - End game
      ACTOR : Robert Downey Jr.
              Chris Evans
              Scarlett Johansson
              Jeremy Renner
      DIRECTOR : Russo brother
      YEAR : 2019
      
      ###############################
      
      < object movie >
      { title: 'Avengers - End game',
        actor:
         [ 'Robert Downey Jr.',
           'Chris Evans',
           'Scarlett Johansson',
           'Jeremy Renner' ],
        director: 'Russo brother',
        year: 2019 }
      
      ###############################
      FINISH
      ###############################
      




'IT > ETC' 카테고리의 다른 글

[ETC] :: Spring Cloud 마이크로서비스 애플리케이션  (0) 2023.06.22
블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

POSIX ERE( Extended Regular Expression )

  1. +
  2. ?
  3. |




11. | ( Vertical Bar )

구문 ( Syntax )

<vertical_bar> ::= |
  • 사용 예
    <vertical_bar>
    
    <pattern_expr><vertical_bar>
    
    <vertical_bar><pattern_expr>
    
    <pattern_expr><vertical_bar><pattern_expr>
    

설명 ( Description )

  • '또는', 'or'를 의미한다.
  • 일반적으로, 좌측 <pattern_expr>부터 검사한 뒤, 매칭이 없으면 우측 <pattern_expr>을 검사한다.
    • ex) REGEXP_SUBSTR( 'take', '(m|t)ake' ) => take
    • ex) REGEXP_SUBSTR( 'aaa', 'aa|aaa' ) => aa
    • 예외) PostgreSQL : 예제 확인
  • <patten_expr> 중 하나가 empty string일 경우, 제쳐두고 나머지 <pattern_expr>을 우선적으로 매칭한다.
    • ex) REGEXP_SUBSTR( 'gdb', '|g' ) => 'g'
      • 이 때 그 나머지 <pattern_expr>의 매칭이 없을 경우 zero-length match가 발생한다.
      • ex) REGEXP_SUBSTR( 'abc', '|g' ) => zero-length match
  • 두 <pattern_expr> 모두 empty string일 경우 zero-length match가 발생한다.
    • ex) |
  • <pattern_expr>이 string일 경우, 그 string을 다룬다.
    • ex) trick|treat => trick or treat ( but not trickreat or trictreat )


예제 ( Examples )

SQL> SELECT REGEXP_SUBSTR( 'abc', 'a|b' ) AS RESULT FROM DUAL;

RESULT
--------------------
a

SQL> SELECT REGEXP_SUBSTR( 'abc', 'b|a' ) AS RESULT FROM DUAL;

RESULT
--------------------
a

SQL> SELECT REGEXP_SUBSTR( 'bbb', 'bb|bbb' ) AS RESULT FROM DUAL;

RESULT
--------------------
bb

SQL> SELECT REGEXP_SUBSTR( 'bbb', 'bbb|bb' ) AS RESULT FROM DUAL;

RESULT
--------------------
bbb

SQL> SELECT REGEXP_SUBSTR( 'ababcdcdcd', '(ab){2}|(cd)+' ) AS RESULT FROM DUAL;

RESULT
------------------------------
abab

SQL> SELECT REGEXP_SUBSTR( 'ababcdcdcd', '(ab){2}|(cd)+', 1, 2 ) AS RESULT FROM DUAL;

RESULT
------------------------------
cdcdcd

SQL> SELECT I1, REGEXP_SUBSTR( I1, '(1[0-2]|0?[1-9])/(3[01]|[12][0-9]|0?[1-9])(st|nd|rd|th)?' ) AS RESULT FROM T1;

I1                             RESULT
------------------------------ ------------------------------
12/25                          12/25
02/14                          02/14
11/26th                        11/26th
4/3rd                          4/3rd
10/01st                        10/01st

SQL> SELECT REGEXP_SUBSTR( 'mississippi', 'mi(s|ss)i(s|ss)i(p|pp)i' ) AS RESULT FROM DUAL;

RESULT
--------------------
mississippi

SQL> SELECT REGEXP_SUBSTR( '801010-1234567',
 '[6-9][0-9]([0][1-9]|[1][0-9])([0][1-9]|[1-2][0-9]|[3][0-1])-[1-4][0-9]{6}' ) AS RESULT FROM DUAL;

RESULT
--------------------
801010-1234567

SQL> SELECT REGEXP_SUBSTR( '800010-1234567',
 '[6-9][0-9]([0][1-9]|[1][0-9])([0][1-9]|[1-2][0-9]|[3][0-1])-[1-4][0-9]{6}' ) AS RESULT FROM DUAL;

RESULT
--------------------
NULL

SQL> SELECT REGEXP_SUBSTR( '801010-2234567',
 '[6-9][0-9]([0][1-9]|[1][0-9])([0][1-9]|[1-2][0-9]|[3][0-1])-[1-4][0-9]{6}' ) AS RESULT FROM DUAL;

RESULT
--------------------
801010-2234567

SQL> SELECT REGEXP_SUBSTR( '801010-5234567',
 '[6-9][0-9]([0][1-9]|[1][0-9])([0][1-9]|[1-2][0-9]|[3][0-1])-[1-4][0-9]{6}' ) AS RESULT FROM DUAL;

RESULT
--------------------
NULL

  • zero-length match : PostgreSQL로 테스트
    postgres=# SELECT REGEXP_MATCHES( 'abc', 'a|', 'g' ) AS RESULT;
     result 
    --------
     {a}
     {""}
     {""}
     {""}
    (4 )
    
    postgres=# SELECT REGEXP_MATCHES( 'abc', '|a', 'g' ) AS RESULT;
     result 
    --------
     {a}
     {""}
     {""}
     {""}
    (4 )
    
    postgres=# SELECT REGEXP_MATCHES( 'abc', 'z|', 'g' ) AS RESULT;
     result 
    --------
     {""}
     {""}
     {""}
     {""}
    (4 )
    
    postgres=# SELECT REGEXP_MATCHES( 'abc', '|z', 'g' ) AS RESULT;
     result 
    --------
     {""}
     {""}
     {""}
     {""}
    (4 )
    
    postgres=# SELECT REGEXP_MATCHES( 'abc', '|', 'g' ) AS RESULT;
     result 
    --------
     {""}
     {""}
     {""}
     {""}
    (4 )
    
    


블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

POSIX ERE( Extended Regular Expression )

  1. +
  2. ?
  3. |




10. ? ( Question Mark )

구문 ( Syntax )

<question_mark> ::= ?
  • 사용 예
    <pattern_expr><question_mark>
    

설명 ( Description )

  • 0 or 1
  • 수량자(quantifier)로, <question_mark> 앞의 <pattern_expr>이 없거나 하나 있음을 의미한다.
    • ex) a? =>  , a
  • <question_mark>만 있는 경우
    • ex) ?
    • 결과
      • Oracle : zero-length match
      • PostgreSQL, MySQL, MariaDB : error 처리
  • zero-length match가 발생할 수 있다.


예제 ( Examples )

SQL> SELECT REGEXP_SUBSTR( 'god', 'goo?d' ) AS RESULT FROM DUAL;

RESULT
--------------------
god

SQL> SELECT REGEXP_SUBSTR( 'good', 'goo?d' ) AS RESULT FROM DUAL;

RESULT
--------------------
good

SQL> SELECT REGEXP_SUBSTR( 'goood', 'goo?d' ) AS RESULT FROM DUAL;

RESULT
--------------------
NULL

SQL> SELECT REGEXP_SUBSTR( 'ababc', '(ab)?' ) AS RESULT FROM DUAL;

RESULT
--------------------
ab

SQL> SELECT REGEXP_SUBSTR( 'knight', '.?night' ) AS RESULT FROM DUAL;

RESULT
--------------------
knight

SQL> SELECT REGEXP_SUBSTR( 'abc', 'z?' ) AS RESULT FROM DUAL;

RESULT
--------------------
NULL

SQL> SELECT REGEXP_COUNT( 'abc', 'z?' ) AS RESULT FROM DUAL;

    RESULT
----------
         4

  • <question_mark>만 있는 경우
    < Oracle >
    SQL> SELECT REGEXP_SUBSTR( 'ab', '?' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'ab', '?' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             3
    
    
    < PostgreSQL >
    postgres=# SELECT REGEXP_MATCHES( 'ab', '?', 'g' ) AS RESULT;
    ERROR:  invalid regular expression: quantifier operand invalid
    
    
    < MySQL >
    mysql> SELECT REGEXP_SUBSTR( 'ab', '?' ) AS RESULT;
    ERROR 3688 (HY000): Syntax error in regular expression on line 1, character 1.
    
    
    < MariaDB >
    MariaDB [test]> SELECT REGEXP_SUBSTR( 'ab', '?' ) AS RESULT;
    ERROR 1139 (42000): Got error 'nothing to repeat at offset 0' from regexp
    
    


블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

POSIX ERE( Extended Regular Expression )

  1. +
  2. ?
  3. |



9. + ( Plus )

구문 ( Syntax )

<plus> ::= +
  • 사용 예
    <pattern_expr><plus>
    

설명 ( Description )

  • 1 or MORE
  • 수량자(quantifier)로, <plus> 앞의 <pattern_expr>이 하나 이상 있음을 의미한다.
    • ex) a+ => a, aa, aaa, ...
  • <plus>만 있는 경우
    • ex) +
    • 결과
      • Oracle : zero-length match
      • PostgreSQL, MySQL, MariaDB : error 처리
  • 다른 수량자들과는 달리 zero-length match가 발생하지 않는다.
    • Oracle은 예외적으로 empty string에 대한 +도 zero-length match가 발생한다.
      • ex) +


예제 ( Examples )

SQL> SELECT REGEXP_SUBSTR( 'aaaaabbb', 'a+' ) AS RESULT FROM DUAL;

RESULT
--------------------
aaaaa

SQL> SELECT REGEXP_SUBSTR( 'abababc', '(ab)+' ) AS RESULT FROM DUAL;

RESULT
--------------------
ababab

SQL> SELECT REGEXP_SUBSTR( 'knight', '.+knight' ) AS RESULT FROM DUAL;

RESULT
--------------------
NULL

SQL> SELECT REGEXP_SUBSTR( 'GOLDILOCKS', 'GOLD(.+)' ) AS RESULT FROM DUAL;

RESULT
--------------------
GOLDILOCKS

  • <plus>만 있는 경우
    < Oracle >
    SQL> SELECT REGEXP_SUBSTR( 'ab', '+' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'ab', '+' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             3
    
    
    < PostgreSQL >
    postgres=# SELECT REGEXP_MATCHES( 'ab', '+', 'g' ) AS RESULT;
    ERROR:  invalid regular expression: quantifier operand invalid
    
    
    < MySQL >
    mysql> SELECT REGEXP_SUBSTR( 'ab', '+' ) AS RESULT;
    ERROR 3688 (HY000): Syntax error in regular expression on line 1, character 1.
    
    
    < MariaDB >
    MariaDB [test]> SELECT REGEXP_SUBSTR( 'ab', '+' ) AS RESULT;
    ERROR 1139 (42000): Got error 'nothing to repeat at offset 0' from regexp
    
    




블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

POSIX BRE( Basic Regular Expression )

  1. ^
  2. $
  3. .
  4. *
  5. \
  6. (
  7. {
  8. [




8. [ ] ( Bracket, 대괄호 )

구문 ( Syntax )

<left_bracket> ::= [

<right_bracket> ::= ]
  • 사용 예
    <left_bracket><positive_bracket_expr><right_bracket>
    
    <left_bracket><negative_bracket_expr><right_bracket>
    
    <positive_bracket_expr> ::=
      <bracket_expr>
    
    <negative_bracket> ::=
      <caret><bracket_expr>
    
    <caret> ::= ^
    
    <bracket_expr> ::=
      <specific_character>
    | <range_character>
    | <collation_class>
    | <character_class>
    | <equivalence_class>
    
    <specific_character> ::=
      <pattern_expr>
    
    
    ex) [abc]
    
    <range_character> ::=
      <pattern_expr><hyphen><pattern_expr>
    
    <hyphen> ::= -
    
    
    ex) [0-9]
    
    <collation_class> ::=
      <left_bracket><period><pattern_expr><period><right_bracket>
    
    <period> ::= .
    
    
    ex) [[.Ch.]]
    
    <character_class> ::=
      <left_bracket><colon>alnum<colon><right_bracket>
    | <left_bracket><colon>alpha<colon><right_bracket>
    | <left_bracket><colon>blank<colon><right_bracket>
    | <left_bracket><colon>cntrl<colon><right_bracket>
    | <left_bracket><colon>digit<colon><right_bracket>
    | <left_bracket><colon>graph<colon><right_bracket>
    | <left_bracket><colon>lower<colon><right_bracket>
    | <left_bracket><colon>print<colon><right_bracket>
    | <left_bracket><colon>punct<colon><right_bracket>
    | <left_bracket><colon>space<colon><right_bracket>
    | <left_bracket><colon>upper<colon><right_bracket>
    | <left_bracket><colon>word<colon><right_bracket>
    | <left_bracket><colon>xdigit<colon><right_bracket>
    
    <colon> ::= :
    
    
    ex) [[:alnum:]],  [[:xdigit:]]
    
    <equivalence_class> ::=
      <left_bracket><equal><pattern_expr><equal><right_bracket>
    
    <equal> ::= =
    
    
    ex) [[=e=]]
    

설명 ( Description )

  • 한 문자를 의미하며 사용 방법에 따라 의미가 다양하게 바뀐다.
  • <left_bracket> 이후 다음 문자들을 제외한 나머지 문자들은 모두 일반 문자로 취급한다.
    • ^ ( caret ) : negative
      • ex) [^a]
    • - ( hyphen ) : range
      • ex) [A-Z]
    • [ ( open bracket ) : 각종 클래스
      • 클래스 안에서 : ( colon ).( period )= ( equal )은 각 클래스의 구문으로 쓰인다.
        • ex) [[:cntrl:]]
        • ex) [[.Ch.]]
        • ex) [[=n=]]
    • ] ( close bracket ) : bracket 구문 종료

예를 들어 [*]는 단지 문자 '*'를 의미한다.

  • 종류는 다음과 같다.
    • <specific_character>
    • <range_character>
    • <collation_class>
    • <character_class>
    • <equivalence_class>
<specific_character>
  • <pattern_expr>에 명시된 문자들 중 한 문자를 의미한다.
  • 예시
    [a] : 알파벳 'a'를 의미
    [^a] : 알파벳 'a'가 아닌 다른 한 문자를 의미
    [abc] : 'a' 혹은 'b' 혹은 'c' 중 한 문자를 의미
    [^abc] : 'a', 'b', 'c'를 제외한 한 문자를 의미
    
<range_character>
  • <hyphen>을 사용하며 명시된 <character_1>과 <character_2> 범위 내의 한 문자를 의미한다.
  • 범위의 순서 기준은 ASCII 코드이다.
  • <character_1>의 ASCII 코드 숫자가 <character_2>의 ASCII 코드 숫자보다 크면 error 처리한다.
  • 한글도 가능하며, 한글 순서의 기준은 추후에 다룬다.
  • 예시
    [a-z] : 알파벳 소문자 한 문자를 의미 ( ASCII code 97 ~ 122 )
    [0-9] : 10진 수 0~9중 한 문자를 의미 ( ASCII code 48 ~ 57 )
    [A-Za-z] : 알파벳 대문자 및 소문자 한 문자를 의미
    [a-a] : 알파벳 a를 의미
    [b-a] : error
    
<collation_class>
  • multibyte 문자가 한 문자를 의미할 때, 이 collation class를 사용하여 나타낸다.
  • NLS_LANGUAGE와 NLS_SORT를 사용해야하며, 해당 국가의 문자가 알파벳으로 표현하였을 때 두 개 이상일 때
    그 문자들을 한 문자로 처리한다.
  • 국가별로 해당 예약어가 정해져 있다.
  • 예시
    ALTER SESSION SET NLS_LANGUAGE=SPANISH;
    ALTER SESSION SET NLS_SORT=XSPANISH;
    
    source string : El caballo, Chico come la tortilla
    pattern : [[.ch.]]
    
    matched result : Ch
    
<character_class>
  • 각 문자 클래스가 의미하는 문자들 중 한 문자를 의미한다.
  • 문자 클래스의 종류는 다음과 같다.
클래스 이름설명ASCII CODE range비고
[:alnum:]알파벳과 숫자(48 ~ 57), (65 ~ 90), (97 ~ 122) 
총 62개
[:alpha:]알파벳(65 ~ 90), (97 ~ 122)
총 52개
[:blank:]공백( 스페이스 )(32)
총 1개
[:cntrl:]제어 문자( ^[, ^E 등 )(0 ~ 31), (127)
총 33개
[:digit:]10진수(48 ~ 57)
총 10개
[:graph:]visible한 모든 문자( 공백 제외 )(33 ~ 126)
총 94개
[:lower:]알파벳 소문자(97 ~ 122)
총 26개
[:print:]visible한 모든 문자( 공백 포함 )(32 ~ 126)
총 95개
[:punct:]구두점 문자(33~47), (58~64), (91~96), (123~126)
총 32개
[:space:]모든 공백 문자( [:blank:], newline, carriage return, ... )(9 ~ 13), (32)
총 6개
[:upper:]알파벳 대문자(65 ~ 90)
총 26개
[:word:]알파벳과 숫자,언더바(48 ~ 57), (65 ~ 90), (95), (97 ~ 122) 
총 63개
POSIX 표준이 아님
[:xdigit:]16진수, [A-Fa-f0-9]와 동일함(48 ~ 57), (65 ~ 70), (97 ~ 102)
총 22개
<equivalence_class>
  • equivalence class 는 해당 <pattern_expr>과 동치인 의미를 가진 다른 multibyte 문자들 중 한 문자를 의미한다.
  • 이는 해당 database의 지원 locale 룰에 따라 범주가 달라진다.
  • 예시
    [=n=] : n, N, ñ, El Niño, ...
    

예제 ( Examples )

  • specific character
    SQL> SELECT REGEXP_SUBSTR( 'abc', '[a]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', '[ab]', 1, 1 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', '[ab]', 1, 2 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    b
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', '[^ab]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    c
    
    SQL> SELECT REGEXP_SUBSTR( 'abbccc', '[ab^]+' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    abb
    
    SQL> SELECT REGEXP_SUBSTR( 'ab bccc', '[ab^]+', 1, 1 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SQL> SELECT REGEXP_SUBSTR( 'ab bccc', '[ab^]+', 1, 2 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    b
    
    SQL> SELECT REGEXP_SUBSTR( '^', '[a^]' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    ^
    
    SQL> SELECT REGEXP_SUBSTR( 'b^', '[a^b]' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    b
    
    SQL> SELECT REGEXP_SUBSTR( 'b^', '[^b]' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    ^
    
    SQL> SELECT REGEXP_SUBSTR( 'b^', '[ ^b]' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    b
    
    SQL> SELECT REGEXP_SUBSTR( 'b^', '[ ^b]', 1, 2 ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    ^
    
    SQL> SELECT REGEXP_SUBSTR( 'abbccc', '[^^ab]+' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ccc
    
      앞의 ^ 아니면, 단지 스트링 ^취급한다.
    
    
  • range character
    SQL> SELECT REGEXP_SUBSTR( 'abCD12<>?', '[a-z]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
    
    SQL> SELECT REGEXP_SUBSTR( 'abCD12<>?', '[A-Z]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    C
    
    SQL> SELECT REGEXP_SUBSTR( 'abCD12<>?', '[^a-zA-Z]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    1
    
    SQL> SELECT REGEXP_SUBSTR( 'abCD12<>?', '[a--z]' ) AS RESULT FROM DUAL;
    SELECT REGEXP_SUBSTR( 'abCD12<>?', '[a--z]' ) AS RESULT FROM DUAL
                                       *
    ERROR at line 1:
    ORA-12728: invalid range in regular expression
    
    SQL> SELECT REGEXP_SUBSTR( 'abCD12<>?', '[0-9]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    1
    
    SQL> SELECT REGEXP_SUBSTR( 'abCD12<>?', '[^0-9]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
    
    SQL> SELECT REGEXP_SUBSTR( 'abCD12<>?', '[:-@]' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    <
    
    
  • collation class
    < Oracle >
    SQL> ALTER SESSION SET NLS_LANGUAGE=SPANISH;
    
    Sesión modificada.
    
    SELECT REGEXP_SUBSTR(
       'El caballo, Chico come la tortilla.',
       '[[:alpha:]]*[ch][[:alpha:]]*',1,1,'i') AS RESULT
        FROM dual;
    
    RESULT
    ---------------------
    caballo
    
    SQL> ALTER SESSION SET NLS_SORT=XSPANISH;
    
    Sesión modificada.
    
    SELECT REGEXP_SUBSTR(
       'El caballo, Chico come la tortilla.',
       '[[:alpha:]]*[[.ch.]][[:alpha:]]*',1,1,'i') AS RESULT
        FROM dual;
    
    RESULT
    ---------------
    Chico
    
    < PostgreSQL >
    Note: PostgreSQL currently does not support multi-character collating elements.
    
    < MySQL >
    The Spencer library supports collating element bracket expressions ([.characters.] notation). 
    ICU( International Components for Unicode ) does not.
    
    
  • character class
    < Oracle >
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:ALNUM:]]+' ) AS RESULT FROM DUAL;
    SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:ALNUM:]]+' ) AS RESULT FROM DUAL
                                      *
    ERROR at line 1:
    ORA-12729: invalid character class in regular expression
    
    < PostgreSQL >
    postgres=# SELECT REGEXP_MATCHES( 'aBcD1234', '[[:ALNUM:]]+' ) AS RESULT;
    ERROR:  invalid regular expression: invalid character class
    
    < MySQL >
    mysql> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:ALNUM:]]+' ) AS RESULT;
    +----------+
    | RESULT   |
    +----------+
    | aBcD1234 |
    +----------+
    1 row in set (0.00 sec)
    
    
     case sensitive Oracle PostgreSQL, 문자 클래스를 대문자로 표기하면 에러처리한다.
     반면, case insensitive MySQL 문자 클래스도 대문자로 표기 가능하다.
    
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:alnum:]]+' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    aBcD1234
    
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:alpha:]]+' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    aBcD
    
    SQL> SELECT REGEXP_SUBSTR( 'a b', 'a[[:blank:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    a b
    
    SQL> SELECT REGEXP_SUBSTR( 'a'||CHR(32)||'b', 'a[[:blank:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    a b
    
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(0)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(1)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(2)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(3)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(4)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(5)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(6)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(7)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(8)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    b
    
    SQL> SELECT REGEXP_SUBSTR( 'a'||CHR(9)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a       b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(10)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
    b
    
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(11)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
     b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(12)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
     b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(13)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(14)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(15)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(16)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(17)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(18)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SQL> SELECT REGEXP_SUBSTR( 'a'||CHR(19)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(20)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(21)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(22)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(23)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(24)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(25)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(26)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(27)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(28)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SQL> SELECT REGEXP_SUBSTR( 'a'||CHR(29)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(30)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(31)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(32)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'a'||CHR(127)||'b', 'a[[:cntrl:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    ab
    
    
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:digit:]]+' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    1234
    
    SQL> SELECT REGEXP_SUBSTR( 'Right Now!', '[[:graph:]]+', 1, 1 ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    Right
    
    SQL> SELECT REGEXP_SUBSTR( 'Right Now!', '[[:graph:]]+', 1, 2 ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    Now!
    
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:lower:]]+', 1, 1 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
    
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:lower:]]+', 1, 2 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    c
    
    SQL> SELECT REGEXP_SUBSTR( 'Right Now!', '[[:print:]]+' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    Right Now!
    
    SQL> SELECT I1, REGEXP_SUBSTR( I1, '[[:punct:]]+' ) AS RESULT FROM T1;
    
    I1                                            RESULT
    --------------------------------------------- --------------------
    !"#$%&'()*+,-./                               !"#$%&'()*+,-./
    :;<=>?@                                       :;<=>?@
    [\]^_`                                        [\]^_`
    {|}~                                          {|}~
    
    
    SQL> SELECT REGEXP_SUBSTR( 'a'||CHR(9)||'b', 'a[[:space:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a       b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(10)||'b', 'a[[:space:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
    b
    
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(11)||'b', 'a[[:space:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
     b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(12)||'b', 'a[[:space:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a
     b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(13)||'b', 'a[[:space:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    b
    
    SELECT REGEXP_SUBSTR( 'a'||CHR(32)||'b', 'a[[:space:]]b' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    a b
    
    
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:upper:]]+', 1, 1 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    B
    
    SQL> SELECT REGEXP_SUBSTR( 'aBcD1234', '[[:upper:]]+', 1, 2 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    D
    
    SQL> SELECT REGEXP_SUBSTR( 'AEd019', '[[:xdigit:]]+' ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    AEd019
    
    SQL> SELECT REGEXP_SUBSTR( 'AEGd019', '[[:xdigit:]]+', 1, 1 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    AE
    
    SQL> SELECT REGEXP_SUBSTR( 'AEGd019', '[[:xdigit:]]+', 1, 2 ) AS RESULT FROM DUAL;
    
    RESULT
    --------------------
    d019
    
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', '[[:word:]]+' ) AS RESULT FROM DUAL;
    SELECT REGEXP_SUBSTR( 'abc', '[[:word:]]+' ) AS RESULT FROM DUAL
                                 *
    ERROR at line 1:
    ORA-12729: invalid character class in regular expression
    
    postgres=# SELECT REGEXP_MATCHES( 'abc', '[[:word:]]+' ) AS RESULT;
    ERROR:  invalid regular expression: invalid character class
    
    mysql> SELECT REGEXP_SUBSTR( 'abCD987_', '[[:word:]]+' ) AS RESULT;
    +----------+
    | RESULT   |
    +----------+
    | abCD987_ |
    +----------+
    1 row in set (0.02 sec)
    
     [:word:] character class POSIX 표준이 아닌 Perl 호환 정규 표현식이며 Oracle, PostgreSQL에서 지원하지 않는다.
    
    • 고려사항
      • Bracket 짝이 맞지 않을 때
        < Oracle >
        SQL> SELECT REGEXP_SUBSTR( '[digit]', '[:digit:]]' ) AS RESULT FROM DUAL;
        
        RESULT
        --------------------
        t]
        
        SQL> SELECT REGEXP_SUBSTR( '[digit]', '[[:digit:]' ) AS RESULT FROM DUAL;
        SELECT REGEXP_SUBSTR( '[digit]', '[[:digit:]' ) AS RESULT FROM DUAL
                                        *
        ERROR at line 1:
        ORA-12726: unmatched bracket in regular expression
        
        
        < PostgreSQL >
        postgres=# SELECT REGEXP_MATCHES( '[digit]', '[:digit:]]' ) AS RESULT;
         result 
        --------
         {t]}
        (1 )
        
        postgres=# SELECT REGEXP_MATCHES( '[digit]', '[[:digit:]' ) AS RESULT;
        ERROR:  invalid regular expression: brackets [] not balanced
        
        
        < MySQL >
        mysql> SELECT REGEXP_SUBSTR( '[digit]', '[:digit:]]' ) AS RESULT;
        +--------+
        | RESULT |
        +--------+
        | NULL   |
        +--------+
        1 row in set (0.00 sec)
        
        mysql> SELECT REGEXP_SUBSTR( '[digit1]', '[:digit:]]' ) AS RESULT;
        +--------+
        | RESULT |
        +--------+
        | 1]     |
        +--------+
        1 row in set (0.00 sec)
        
        mysql> SELECT REGEXP_SUBSTR( '[digit]', '[[:digit:]' ) AS RESULT;
        ERROR 3696 (HY000): The regular expression contains an unclosed bracket expression.
        
        
        < MariaDB >
        MariaDB [test]> SELECT REGEXP_SUBSTR( '[digit]', '[:digit:]]' ) AS RESULT;
        ERROR 1139 (42000): Got error 'POSIX named classes are supported only within a class at offset ' from regexp
        MariaDB [test]> SELECT REGEXP_SUBSTR( '[digit1]', '[:digit:]]' ) AS RESULT;
        ERROR 1139 (42000): Got error 'POSIX named classes are supported only within a class at offset ' from regexp
        
        
         MySQL, MariaDB 처리가  다르지만,  벤더 모두 닫히지 않은 bracket 대한 에러 처리는 당연히 동일하다.
        
      • caret의 위치
        • [^[:class_name:]]   [[^:class_name:]]   [[:^class_name:]]   비교
        • Oracle
          # Not digit #
          
          SQL> SELECT REGEXP_SUBSTR( '1d]', '[^[:digit:]]' ) AS RESULT FROM DUAL;
          
          RESULT
          --------------------
          d
          
          
          # specific character & string ']' #
          
          SQL> SELECT REGEXP_SUBSTR( '1d]', '[[^:digit:]]' ) AS RESULT FROM DUAL;
          
          RESULT
          --------------------
          d]
          
          SQL> SELECT REGEXP_SUBSTR( '1d[]', '[[^:digit:]]' ) AS RESULT FROM DUAL;
          
          RESULT
          ------------------------------
          []
          
          
          SQL> SELECT REGEXP_SUBSTR( '1d]', '[[:^digit:]]' ) AS RESULT FROM DUAL;
          SELECT REGEXP_SUBSTR( '1d]', '[[:^digit:]]' ) AS RESULT FROM DUAL
                                       *
          ERROR at line 1:
          ORA-12729: invalid character class in regular expression
          
          
          
        • PostgreSQL
          # Not digit #
          
          postgres=# SELECT REGEXP_MATCHES( '1d]', '[^[:digit:]]', 'g' ) AS RESULT;
           result 
          --------
           {d}
           {]}
          (2 )
          
          
          # specific character & string ']' #
          
          postgres=# SELECT REGEXP_MATCHES( '1d]', '[[^:digit:]]', 'g' ) AS RESULT;
           result 
          --------
           {d]}
          (1 )
          
          postgres=# SELECT REGEXP_MATCHES( '1d[]', '[[^:digit:]]', 'g' ) AS RESULT;
           result 
          --------
           {[]}
          (1 )
          
          
          postgres=# SELECT REGEXP_MATCHES( '1d]', '[[:^digit:]]', 'g' ) AS RESULT;
          ERROR:  invalid regular expression: invalid character class
          
          
        • MySQL
          # Not digit #
          
          mysql> SELECT REGEXP_SUBSTR( '1d]', '[^[:digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | d      |
          +--------+
          1 row in set (0.00 sec)
          
          
          # negative specific character same as [^:digit:] #
          
          mysql> SELECT REGEXP_SUBSTR( '1d]', '[[^:digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | 1      |
          +--------+
          1 row in set (0.01 sec)
          
          mysql> SELECT REGEXP_SUBSTR( '1d]', '[[^:digit:]]', 1, 2 ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | ]      |
          +--------+
          1 row in set (0.01 sec)
          
          mysql> SELECT REGEXP_SUBSTR( ':digit:1d]', '[[^:digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | 1      |
          +--------+
          1 row in set (0.01 sec)
          
          
          # Not digit #
          
          mysql> SELECT REGEXP_SUBSTR( '1d]', '[[:^digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | d      |
          +--------+
          1 row in set (0.03 sec)
          
          
        • MariaDB
          # Not digit #
          
          MariaDB [test]> SELECT REGEXP_SUBSTR( '1d]', '[^[:digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | d      |
          +--------+
          1 row in set (0.001 sec)
          
          
          # specific character & string ']' #
          
          MariaDB [test]> SELECT REGEXP_SUBSTR( '1d]', '[[^:digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | d]     |
          +--------+
          1 row in set (0.000 sec)
          
          MariaDB [test]> SELECT REGEXP_SUBSTR( '1d[]', '[[^:digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | []     |
          +--------+
          1 row in set (0.001 sec)
          
          
          # Not digit #
          
          MariaDB [test]> SELECT REGEXP_SUBSTR( '1d]', '[[:^digit:]]' ) AS RESULT;
          +--------+
          | RESULT |
          +--------+
          | d      |
          +--------+
          1 row in set (0.000 sec)
           
caret의 위치에 따른 문자 클래스의 벤더별 처리
 DBMS  [^[:class_name:]]  [[^:class_name:]]  [[:^class_name:]] 
 Oracle  negative class  normal bracket  error 
 PostgreSQL  negative class  normal bracket  error 
 MySQL  negative class  same as [^:class_name:]  negative class 
 MariaDB  negative class  normal bracket  negative class 
  • equivalence class
    SQL> SELECT REGEXP_SUBSTR('eéëèÉËÈE', '[[=e=]]+') AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------------------
    eéëèÉËÈE
    
    SQL> SELECT REGEXP_SUBSTR('eéëèÉËÈE', '[[=E=]]+') AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------------------
    eéëèÉËÈE
    
    SQL> SELECT REGEXP_SUBSTR('eéëèÉËÈE', '[[=É=]]+') AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------------------
    eéëèÉËÈE
    
     PostgreSQL, MySQL, MariaDB에서는 지원하지 않음.


블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,

POSIX BRE( Basic Regular Expression )

  1. ^
  2. $
  3. .
  4. *
  5. \
  6. (
  7. {
  8. [




7. { } ( Brace, 중괄호 )

구문 ( Syntax )

<left_brace> ::= {

<right_brace> ::= }
  • 사용 예
    <pattern_expr><left_brace><brace_expr><right_brace>
    
    <brace_expr> ::=
      <integer_1>
    | <integer_1><comma>
    | <integer_1><comma><integer_2>
    
    <comma> ::= ,
    
    

설명 ( Description )

  • 수량자(quantifier)로, <left_brace> 앞에 있는 <pattern_expr>의 '개수, 반복 횟수'를 의미한다.
  • <brace_expr>에 하나의 <integer_1> 만 명시한 경우
    • 정확히 <integer>개를 의미한다.
      • ex) a{2} => aa
      • ex) (ab){3} => ababab
  • <brace_expr>에 <integer_1>와 <comma>를 명시한 경우
    • <integer>개 이상을 의미한다.
      • ex) a{3,} => aaa, aaaa, aaaaa, ...
  • <brace_expr>에 <integer_1>, <comma>, <integer_2>를 명시한 경우
    • <integer_1>개 이상 <integer_2>개 이하를 의미한다.
      • ex) go{1, 3} => go, goo, gooo
    • <integer_1> ≤ <integer_2> 를 만족해야 한다. ( <integer_1> > <integer_2> 인 경우 error 처리 )
      • ex) (ab){5,2} => error 처리
  • 지정된 사용법이 아닌 경우
    • <integer_1>에 음수 및 소수가 있는 경우
      • ex) a{-1}
      • ex) z{1.5}
    • <comma>가 아닌 다른 문자가 있는 경우( 숫자 아닌 문자 )
      • ex) g{1~10}
    • <comma> 뒤에 <integer_2>가 아닌 다른 문자가 있는 경우
      • ex) (ab){2,s}
    • 맨 뒤에 <right_brace>가 없는 경우
      • ex) c{3,5
    • 결과
      • Oracle, MariaDB는 전체를 str (일반 문자)로 처리한다.
      • PostreSQL, MySQL은 error 처리한다.
  • <integer_1> 이 0인 경우, zero-length match가 발생할 수 있다.

    • ex) c{0}
    • ex) z{0,}
    • ex) (ab){0, 5}
  • <brace_expr>에 아무것도 명시하지 않은 경우
    • ex) a{}
    • 결과
      • Oracle, PostgreSQL, MariaDB : string 처리
      • MySQL : error 처리
  • <pattern_expr>이 <left_brace> 앞에 명시되어있지 않은 경우
    • ex) {3}
    • 결과
      • Oracle : zero-length match
      • PostgreSQL, MySQL, MariaDB : error 처리


예제 ( Examples )

SQL> SELECT REGEXP_SUBSTR( 'aaaab', 'a{2}' ) AS RESULT FROM DUAL;

RESULT
--------------------
aa

SQL> SELECT REGEXP_SUBSTR( 'aaaab', 'a{1,}' ) AS RESULT FROM DUAL;

RESULT
--------------------
aaaa

SQL> SELECT REGEXP_SUBSTR( 'aaaab', 'a{1,3}' ) AS RESULT FROM DUAL;

RESULT
--------------------
aaa

  • 지정된 사용법이 아닌 경우
    SQL> SELECT REGEXP_SUBSTR( 'aaa', 'a{-1}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'a{-1}', 'a{-1}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    a{-1}
    
    SQL> SELECT REGEXP_SUBSTR( 'aaa', 'a{1~3}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'a{1~3}', 'a{1~3}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    a{1~3}
    
    SQL> SELECT REGEXP_SUBSTR( 'aaa', 'a{1.5}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'a{1.5}', 'a{1.5}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    a{1.5}
    
    SQL> SELECT REGEXP_SUBSTR( 'zzz', 'z{1,a}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'z{1,a}', 'z{1,a}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    z{1,a}
    
    SQL> SELECT REGEXP_SUBSTR( 'zzz', 'z{1, 2}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'z{1, 2}', 'z{1, 2}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    z{1, 2}
    
    SQL> SELECT REGEXP_SUBSTR( 'aaa', 'a{1' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'a{1', 'a{1' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    a{1
    
    SQL> SELECT REGEXP_SUBSTR( 'zzz', 'z{1,' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'z{1,', 'z{1,' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    z{1,
    
    SQL> SELECT REGEXP_SUBSTR( 'zzz', 'z{1,3' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'z{1,3', 'z{1,3' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    z{1,3
    
    
    < MariaDB >
    MariaDB [test]> SELECT REGEXP_SUBSTR( 'a{1~3}', 'a{1~3}' ) AS RESULT FROM DUAL;
    +--------+
    | RESULT |
    +--------+
    | a{1~3} |
    +--------+
    1 row in set (0.001 sec)
    
    
    < PostgreSQL >
    postgres=# SELECT REGEXP_MATCHES( 'a{1,3', 'a{1~3}' ) AS RESULT;
    ERROR:  invalid regular expression: invalid repetition count(s)
    
    
    < MySQL >
    mysql> SELECT REGEXP_SUBSTR( 'aaa', 'a{1~3}' ) AS RESULT FROM DUAL;
    ERROR 3692 (HY000): Incorrect description of a {min,max} interval.
    
    
     Oracle, MariaDB 지정된 사용법이 아니라면 모두 string 처리하는 반면
       PostgreSQL, MySQL error 처리한다.
    
  • <integer>, <integer_1> 이 0인 경우
    SQL> SELECT REGEXP_SUBSTR( 'abc', 'z{0}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'abc', 'z{0}' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             4
    
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', 'z{0,}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'abc', 'z{0,}' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             4
    
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', 'z{0,10}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'abc', 'z{0,10}' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             4
    
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', '(abc){0}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'abc', '(abc){0}' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             4
    
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', '(abc){0,}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    abc
    
    SQL> SELECT REGEXP_COUNT( 'abc', '(abc){0,}' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             2
    
    
    SQL> SELECT REGEXP_SUBSTR( 'abc', '(def){0,}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'abc', '(def){0,}' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             4
    
  • <brace_expr>에 아무것도 명시하지 않은 경우
    < Oracle >
    SQL> SELECT REGEXP_SUBSTR( 'aaa', 'a{}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_SUBSTR( 'a{}', 'a{}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    a{}
    
    
    < PostgreSQL >
    postgres=# SELECT REGEXP_MATCHES( 'aaa', 'a{}', 'g' ) AS RESULT;
     result 
    --------
    (0 )
    
    postgres=# SELECT REGEXP_MATCHES( 'a{}', 'a{}', 'g' ) AS RESULT;
     result  
    ---------
     {"a{}"}
    (1 )
    
    
    < MariaDB >
    MariaDB [test]> SELECT REGEXP_SUBSTR( 'aaa', 'a{}' ) AS RESULT;
    +--------+
    | RESULT |
    +--------+
    |        |
    +--------+
    1 row in set (0.001 sec)
    
    MariaDB [test]> SELECT REGEXP_SUBSTR( 'a{}', 'a{}' ) AS RESULT;
    +--------+
    | RESULT |
    +--------+
    | a{}    |
    +--------+
    1 row in set (0.001 sec)
    
    
    < MySQL >
    mysql> SELECT REGEXP_SUBSTR( 'aaa', 'a{}' ) AS RESULT;
    ERROR 3692 (HY000): Incorrect description of a {min,max} interval.
    
    
     Oracle, PostgreSQL, MariaDB 모두 string 처리하는 반면
       MySQL error 처리한다.
    
  • <pattern_expr>이 <left_brace> 앞에 명시되어있지 않은 경우
    < Oracle >
    SQL> SELECT REGEXP_SUBSTR( 'aaa', '{5}' ) AS RESULT FROM DUAL;
    
    RESULT
    ------------------------------
    NULL
    
    SQL> SELECT REGEXP_COUNT( 'aaa', '{5}' ) AS RESULT FROM DUAL;
    
        RESULT
    ----------
             4
    
    
    < PostgreSQL >
    postgres=# SELECT REGEXP_MATCHES( 'aaa', '{5}', 'g' ) AS RESULT;
    ERROR:  invalid regular expression: quantifier operand invalid
    
    
    < MySQL >
    mysql> SELECT REGEXP_SUBSTR( 'aaa', '{5}' ) AS RESULT;
    ERROR 3688 (HY000): Syntax error in regular expression on line 1, character 1.
    
    
    < MariaDB >
    MariaDB [test]> SELECT REGEXP_SUBSTR( 'aaa', '{5}' ) AS RESULT;
    ERROR 1139 (42000): Got error 'nothing to repeat at offset 2' from regexp
    
    


블로그 이미지

차트

소소한 일상 C코드 DB 항상 행복하게^-^★

,