|
'DB2'에 해당되는 글 16건
- 2008.12.15 db2 스크립트 모음
- 2008.12.15 DB2 Express-C
- 2008.11.26 DB2 제약조건
- 2008.11.03 DB2 UTF-8로 변환할 때...
- 2008.10.30 DB2 재미있는 시간 날짜 컨트롤
- 2008.10.20 DB2 컬럼 변경
- 2008.09.26 DB2 기초 정리
- 2008.09.19 [DB2]효과적인 SQL 작성법
- 2008.09.18 DB2 기초: 재미있는 날짜와 시간
- 2008.09.18 DB2 와 오라클의 차이점
개발자 친화적인 대안, DB2 Express-C (한글) |
난이도 : 초급 Grant Hutchison, Senior Product and Release Manager, IBM 2006 년 3 월 14 일 요즘 무료 RDBMS (관계형 데이터베이스 관리 시스템) 옵션들이 많이 있다. 이 중 몇몇은 오픈 소스이고, 어떤 것은 상용이지만 무료로 사용할 수 있다. C/C++, Java™, .NET, PHP를 사용하여 애플리케이션을 개발하고 있고 혁신적인 기술과 탄탄한 개발자 커뮤니티 기반을 갖춘 믿을 수 있는 데이터 서버를 찾고 있다면, 새로운 DB2 Express-C를 주목하기 바란다. 이 글에서 DB2® Express-C를 사용하는 방법을 설명하고 애플리케이션 최적화를 위한 자동화 및 튜닝 시나리오를 제공한다. DB2 Express-C는 DB2 Universal Database™ (UDB) Express Edition V8.2.2와 같은 핵심 기술에 기반하고 있다. DB2 Express-C는 리눅스와 Windows® 플랫폼 (32-bit와 64-bit)에서 사용 가능하며 IBM에서 무료 다운로드를 제공한다. IBM은 DB2 Universal Database Express Edition (DB2 Express) 버전인 DB2 Universal Database Express Edition (DB2 Express)을 2006년 1월 30일 발표했다. C/C++, 자바, .NET, PHP 등 모든 애플리케이션들을 구현하고 전개할 수 있는 강력한 기반을 제공한다. IBM Cloudscape™와 Express-C는 이제 IBM에서 무료 라이센스로 사용할 수 있으며 애플리케이션 개발과 전개에 사용될 수 있다. 이 두 개의 데이터베이스 서버 모두 SQL과 JDBC 같은 오픈 표준에 기반한 것이기 때문에 두 데이터 서버 간에 자바 애플리케이션과 데이터베이스를 마이그레이션 하기도 편하다. Cloudscape나 Apache Derby를 사용하고 있다면 무료 유틸리티인 Cloudscape Workbench를 사용하여 데이터베이스를 DB2로 마이그레이션 하고 새로운 DB2 Express-C를 실행시킬 수 있다. DB2 Express-C는 Cloudscape 보다 더 큰 다운로드와 디스크 풋프린트를 갖고 있지만 DB2 Express는 더 많은 툴들을 제공한다. 또한, .NET 애플리케이션도 완전히 지원하고 PHP 애플리케이션에는 이상적이다. DB2 Express-C는 최대 두 개의 CPU와 4GB 메모리 까지 활용할 수 있고 데이터베이스의 크기는 제한이 없다. DB2는 많은 디스크에 걸쳐 데이터베이스를 분산하여 확장성과 퍼포먼스를 높이고 있다. DB2 Express-C는 제품화 준비가 된 데이터베이스 서버로서 매 새로운 릴리스 마다 향상된 혁신적인 기술에 기반하고 있다. DB2는 1995년 이후 Windows에서, 1999년 부터는 리눅스에서 사용 가능하다. DB2의 역사를 알고싶다면 "The Big Picture: IBM DB2 Information Management Software and DB2 Universal Database" (developerWorks, 2003년 1월)을 읽어보기 바란다. "만약 내 데이터베이스 서버가 4GB 메모리와 2 CPU 이상을 필요로 한다면?" 리눅스, Windows, UNIX®용 UDB Enterprise Server Edition (ESE)으로 바꾸면 된다. DB2 ESE는 테라바이트의 데이터를 지원할 수 있는 입증된 플랫폼이다. DB2 ESE는 Database Partitioning Feature (DPF)를 추가하여 데이터베이스 병렬 연산을 수행할 수 있다. DB2 Express-C에서 다른 DB2 에디션으로 전향하는 일은 간단하다. 핵심 데이터베이스 엔진이 같기 때문이다. DB2 Express-C의 등장과 함께 IBM DB2 전문가들로 구성된 새로운 포럼이 만들어졌다. 이 포럼은 이 새로운 무료의 데이터 서버에 대한 궁금증을 해소할 수 있는 좋은 장소이다. DB2 Express-C는 완벽한 매뉴얼도 갖추고 있고, PDF 포맷이나 DB2 Information Center에서 검색도 가능하다. DB2 Information Center는 온라인 상에서 지속적으로 업데이트 되며 최신 버전을 다운로드 할 수 있고 전용 서버에 설치할 수도 있다. DB2 UDB 제품 매뉴얼 모두 사용할 수 있다. DB2 Information Center는 리눅스, UNIX, Windows용 DB2 UDB의 모든 에디션 공통이기 때문에, Database Partitioning Feature (DPF) 같은 고급 기능들은 DB2 Express-C 환경에는 적용할 수 없다. 리눅스에서 DB2 Express-C를 사용하려면 검증된 최신 리눅스 배포판을 점검해보는 것이 좋다. 리눅스용 DB2에 대한 좋은 참고자료로는 DB2 Universal Database Version 8.2 for 리눅스 HOWTO가 있다. (참고자료)
DB2 Express-C 설치하기 DB2 Express-C의 최소 메모리 조건은 그래픽 툴이 없는 256MB 또는 그래픽 툴을 가진 512MB이다. 이 글에서 설명하는 머신은 2GB 메모리에 적합하다. 나는 Windows(32-bit)용 DB2 Express-C를 다운로드 했다. 다운로드는 391MB였고 설치는 매우 간단했다. ZIP 파일의 압축이 풀리면(내 시스템 상에서 압축이 풀린 디렉토리는 그렇게 크지 않은 412MB에 불과하다.) 그림 1. DB2 Express-C Launchpad 설치를 계속해 나가다 보면 새로운 윈도우(그림 2)가 디스플레이 된다. 계속 진행하여 첫 번째 DB2 데이터베이스를 만든다. 그림 2. DB2 First Steps
DB2 Express-C는 관리하기 수월한 데이터 베이스이다. 완벽한 그래픽 툴과 명령행 툴이 데이터베이스 관리자(DBA)를 돕는다. 가장 일반적으로 사용되는 그래픽 툴은 DB2 Control Center이고 가장 많이 사용되는 명령행 툴은 DB2 CLP(Command Line Processor)이다. 툴 이름을 보면 특징적인 것은 없지만 매력적인 기능을 갖고 있다. DB2 Express-C에서 제공하는 그래픽 툴은 다양한 범주로 나뉜다. (그림3) General Administration Tools 목록에 DB2 Control Center가 있다. 대부분의 다른 그래픽 툴들은 DB2 Control Center내에서 접근할 수 있다. 그림 3. DB2 툴 DB2 Control Center( 그림 4)는 DBA에게 데이터베이스의 운영 상황을 제공한다. 이 예제를 보면, SAMPLE 데이터베이스 크기는 25MB이고 아직 백업되지 않았다. 자동 관리 역시 설정되지 않았다. 그림 4. DB2 Control Center – 자동화 되기 전 SAMPLE 데이터베이스 DB2 그래픽 툴 위자드로는 DB2의 일반적인 관리 작업들을 수행하는 방법을 빠르게 배울 수 있다. DB2 Control Center의 각 객체는 객체 트리의 객체를 오른쪽 클릭하여 조작한다. 많은 위자드들은 새로운 DB2 DBA가 백업 데이터베이스 이미지를 만들고 이전 이미지들을 복구하는 등의 일반적인 태스크를 수행할 때 쓰인다. (그림 5) 그림 5. DB2 툴 위자드 그림 6을 보면, SAMPLE 데이터베이스가 537MB로 늘어났다. 이 데이터베이스에는 백업 자동화와 관리가 설정되었다. DB2 Express-C가 규정한 alert 상황이 있다. ( 그림 6) 이제 이 상황을 파악하고 해결하는 방법을 알아보자. 그림 6. DB2 Control Center – 자동화 후 SAMPLE 데이터베이스 DB2만의 유일한 기능은 환경을 실시간으로 모니터링하고 DBA에게 비정상적인 상황들을 공지하는 기능이다. 그림 7에서, DB2가 SAMPLE 데이터베이스에서 시간 당 많은 잠금(lock) 에스컬레이션을 탐지했다. DB2는 데이터베이스 객체에 대한 잠금을 사용하여 트랜잭션 일관성을 보장한다. 이 예제에서 DB2는 한 시간 내에 1150 잠금 에스컬레이션을 수행했다. DB2는 DB2 서버에 할당된 메모리를 가지고 그렇게 많은 잠금 열을 관리할 수 없었다. 이 상황은 잠금 관리용 DB2 서버 메모리를 늘려서 쉽게 해결될 수 있다. DBA가 직접 수정하거나 자동화 처리된다. DB2의 상태 모니터링 기능은 규모가 큰 DB2 Enterprise Server Edition (ESE)을 통해서 DB2 Express-C에도 적용된다. DB2 Express-C가 여러분의 애플리케이션의 트랜잭션 일관성을 보장할 것이다. 각 트랜잭션은 기록되어 데이터베이스 내의 데이터 무결성을 보장한다. 그림 7. DB2 Health Center – 잠금 에스컬레이션 데이터베이스 애플리케이션 퍼포먼스는 고객의 솔루션 만족도에 직접적인 영향을 미친다. 최적의 퍼포먼스를 이룩하는 것은 거의 예술의 경지로 취급 받는다. DB2 Express-C는 완벽한 툴(그래픽과 비 그래픽)을 제공하여 고성능의 신뢰성 있는 애플리케이션을 만들 수 있도록 한다. 이 시나리오에서 우리는 우리 회사에서 가장 봉급을 많이 받는 부서를 결정할 것이다. 최적의 퍼포먼스를 이룩하기 위해 DB2 Express-C에서 제공하는 툴 조합을 사용할 것이다. 이 시나리오에서 사용되는 툴은 다음과 같다.
db2batch 유틸리티는 쿼리의 런타임 퍼포먼스를 분석하는데 적합한 툴이다. 이 시나리오에서 다음과 같은 SQL 문장을 사용하여 분석을 수행한다.
그림 8. db2batch – 쿼리 실행 그림 9는 값비싼 테이블 스캔이 STAFF 테이블에 대해 수행되고 Hash Join 연산이 ORG와 STAFF 테이블의 데이터에 근거하여 수행되었다는 것을 보여주고 있다. 이 테이블에 대한 인덱스가 없기 때문에 DB2는 쿼리 실행 중에 사용할 것이다. 우리는 DB2 Design Advisor를 사용할 것이고 DB2에게 적절한 새로운 인덱스를 ORG와 STAFF 테이블에 붙여서 쿼리 퍼포먼스를 높일 것을 요청한다. 그림 9. 쿼리 분석 그림 10은 DB2 Design Advisor로부터 온 피드백이다. DEPT와 SALARY 칼럼을 사용하여 STAFF 테이블에 인덱스를 생성할 것을 권고하고 있다. Design Advisor용 쿼리 워크로드는 파일에 제공되거나 애플리케이션 실행 중에 캡쳐될 수 있다. 그림 10. DB2 Design Advisor – 인덱스 권고 그림 11은 이 인덱스가 쿼리 실행에 도움이 되었다는 것을 보여주고 있다. 쿼리의 경과 시간이 현격하게 향상되었다. 이제는 7초 밖에 안 걸린다. 그림 11. db2batch – 쿼리 실행 향상 그림 12는 STAFF 테이블의 새로운 인덱스가 쿼리 액세스 계획에 사용되고 있다는 것을 확인하는 모습이다. 쿼리의 실행 비용 역시 줄어든다. 그림 12. 쿼리 계획 변경 마지막으로, 이 쿼리의 실행 중에 사용될 전체 시스템 리소스를 결정하는 방법도 궁금할 것이다. DB2 UDB V8.2에 추가된 새로운 툴인 Activity Monitor는 다양한 SQL 함수와 프로시저를 사용하여 실행 시스템에 대한 퍼포먼스 데이터를 가져온다. 그림 13을 보면, 쿼리가 두 개의 소트를 수행하는데 걸리는 시간이 12초 미만이라는 것을 알 수 있다. Activity Monitor에는 DB2 Express-C 환경을 분석하는데 사용할 수 있는 리포트가 많이 있다. 그림 13. Activity Monitor – 런타임 분석
전형적인 DB2 Express-C는 C/C++, 자바, .NET 애플리케이션을 개발할 때 사용할 필수 드라이버와 인터페이스를 제공한다. PHP나 Perl 애플리케이션을 개발하는 것에 관심이 있다면 여기에 사용할 수 있는 드라이버가 있다. PHP와 Perl 인터페이스가 개발되어 DB2 팀 내 엔지니어들이 관리한다. DB2는 저장 프로시저, 트리거, 함수(테이블과 스칼라)를 포함하여 많은 서버측 프로그래밍 언어를 지원한다. DB2 저장 프로시저는 C/C++, COBOL, Java (JDBC 또는 SQLJ), .NET (CLR 호환 언어), SQL Procedure Language (SQL PL)를 사용하여 작성될 수 있다. 저장 프로시저 언어에 따라 선택은 다양하지만 가장 일반적으로 사용되는 언어는 자바와 SQL PL이다. SQL Procedure Language (SQL PL) 저장 프로시저는 원시 프로시저로 간주된다. 리눅스와 Windows 상의 DB2 데이터베이스 내의 객체로서 저장되기 때문이다. SQL PL은 유일한 ANSI SQL 표준 기반의 저장 객체 언어로서 진화해 왔다. SQL PL은 전체 DB2 데이터베이스 서버 제품군에서 지원된다. (리눅스, UNIX, Windows, iSeries, z/OS 용). DB2 Express-C는 매우 유용한 그래픽 툴인 Development Center를 제공하여 자바와 SQL PL 프로시저를 비롯하여 SQL 저장 프로시저의 개발, 테스트, 전개를 관리한다. 그림 14 는 SQL PL 프로시저의 구현, 테스트, 전개에 사용되는 DB2 Development Center의 모습이다. 이 그림에서 보이는 프로시저는 high_rollers이고 DB2 Express-C 내에서 저장 및 실행된다. 저장 프로시저 실행은 DB2 내에서 엄격히 제어되기 때문에 DB2 데이터로의 액세스를 보안화 하는 기술이라고 할 수 있다. 그림 14. Development Center - SQL PL DB2에서 자바 애플리케이션을 개발하기는 쉽다. 모든 DB2 클라이언트와 서버가 JDBC 3 순응 (type-4) 드라이버를 제공하기 때문이다. 현재 DB2에 포함된 두 개의 다른 JDBC가 있다. 원래 드라이버(db2java.zip)는 Application (type 2)과 Network (type 3) 드라이버로 알려져 있다. 새롭고 보다 유연한 JDBC 드라이버(db2jcc.jar)는 type 2 또는 type 4 모드에서 사용될 수 있고, 최신 자바 클라이언트/서버 산업 벤치마크에서 사용되었다. (SPECjAppServer 2004 with DB2 and WebSphere® Application Server – 참고자료). JDBC (db2jcc.jar)용 DB2 드라이버는 DB2 런타임 클라이언트에 번들 된다. 애플리케이션이 순수 자바이면 CLASSPATH에 PHP("PHP: Hypertext Preprocessor")는 광범위하게 사용되는 오픈 소스의 범용 스크립팅 언어로서 웹 개발에 이상적이고 HTML에 삽입될 수 있다. PHP는 확장성 있는 웹 애플리케이션을 위한 선택으로서 전 세계적으로 빠르게 채택되고 있다. PHP의 DB2 지원은 PHP용 IBM DB2 확장(참고자료")까지 이르렀다. PHP는 수 백만 개의 웹 애플리케이션을 움직일 수 있는 오픈 소스 스크립팅 언어이고 PHP는 1995년 도입된 이래 꾸준히 진화해 오고 있다. PHP용 DB2 확장은 소스 코드로 제공된다. 코드를 컴파일 하지 않고 Windows에서 이 확장을 사용하고 싶다면 Windows용 필수 라이브러리도 있다. (참고자료) DB2 환경을 설치 및 실행하는 가장 쉬운 방법 중 하나는 IBM과 Zend Technologies에서 개발한 무료 Zend Core™ for IBM을 다운로드 하는 것이다. Zend Core for IBM는 PHP 개발 및 제품 환경으로서 IBM Cloudscape 데이터베이스 서버와 긴밀히 통합되어 있다. 이것은 데이터베이스 기반 애플리케이션의 개발 및 전개 토대가 된다. PHP 지원 및 DB2 지원 등 전체적인 웹 스택 지원이 필요하면 지원 옵션도 사용할 수 있다. Zend Core for IBM은 Cloudscape 데이터베이스 서버와 무료 DB2 Express를 삽입하여 전개를 용이하게 한다. 나중에 전체 DB2 Express Edition 라이센스를 구매하면 DB2 Express 제품 번들에도 지원이 가능하다. 그림 15 는 DB2용 PHP 확장 모습을 보여주고 있는 Zend Core for IBM 관리 웹 콘솔 모습이다. 그림 15. Zend Core for IBM DB2 Express-C는 DB2 .NET 1.1 Data Provider와 Microsoft Visual Studio .NET 2003용 애드인(add-in)을 제공한다. IBM 익스플로러와 통합 DB2 도움말이 Visual Studio내에 있다. ( 그림 16) DB2 Express-C가 설치되면 Visual Studio .NET 2003의 존재 여부를 검사하고, 존재할 경우에 DB2 기능을 Visual Studio에 추가한다. 이러한 애드인으로 .NET 애플리케이션의 개발 시간이 줄어든다. DB2 UDB v8.2의 릴리스로 인해, .NET(CLR - Common Language Runtime) 저장 프로시저 지원이 새로운 옵션으로서 추가되었다. 그림 16. Visual Studio .NET 2003용 DB2 애드인(add-in) DB2 add-ins for Visual Studio 2005 - Developer Release용 DB2 애드인을 무료로 다운로드 할 수 있다. Developer Release에는 DB2 .NET 2.0 Data Provider와 최근에 릴리스 된 Microsoft Visual Studio 2005 IDE용 애드인 세트가 포함되어 있다. DB2 Express-C는 데이터 액세스, DB2 CLI, Embedded SQL에 두 개의 기본적인 C API를 제공한다. 가장 일반적으로 사용되는 C/C++ API는 DB2 Call Level Interface (CLI)이고, 이것은 X/Open CLI 표준에 근거하고 있다. 이 API는 Windows 애플리케이션에 사용되는 Microsoft ODBC (Open Database Connectivity) API를 매우 닮아있다. DB2 데이터에 대한 Embedded SQL의 접근 방식은 애플리케이션 프로세서를 사용하여 모든 SQL 레퍼런스들을 DB2 서버에 대한 원시 액세스 인터페이스로 대체하는 것이다. Embedded SQL은 SQL 문이 잘 정의도어 있고 애플리케이션 개발 동안에 알려져 있다면 매우 큰 효력을 발휘할 수 있다. SQL은 타당성 검사를 할 수 있고 액세스 계획은 개발 동안에는 잠기기 때문에 애플리케이션 퍼포먼스가 높아진다. SQL 문은 기본적으로 역동적이고, DB2 CLI API 같은 역동적인 SQL 액세스 기술을 많이 선호하고 있다. COBOL, Perl, Python 같은 DB2 Express-C용 옵션들이 많이 있다. Perl 드라이버는 오픈 소스 Perl 커뮤니티에서 사용할 수 있고 IBM에서 전적으로 관리 및 지원한다. SourceForge.net ( 참고자료 )에서 DB2에 사용할 수 있는 Python 드라이버가 업데이트 되어 있다. Perl, PHP, Python 드라이버 모두 전개에는 DB2 Run-time이, 컴파일과 구현에는 DB2 Application Development Client (DB2 Express-C)가 필요하다.
데이터베이스 애플리케이션을 전개하려면 고려해야 할 사항들이 있다.
DB2 서버 환경을 설치는 DB2 그래픽 인스톨러( DB2 Run-Time Client는 모든 애플리케이션 프로그래밍 인터페이스(API)와 네트워크 클라이언트 드라이버를 제공하여 리눅스, 유닉스, Windows 상의 DB2에 직접 액세스 한다. Windows의 경우 보다 단순한 클라이언트가 있다. (DB2 Run-Time Client Lite) 풋프린트가 더 적다. DB2 Run-Time Client Lite는 Windows Installer 기반 설치에서 사용될 수 있는 Merge Module도 제공하여 Windows 애플리케이션에서 DB2에 연결을 쉽게 삽입할 수 있다. 애플리케이션 전개 까지는 이 글에서는 설명하지 않겠다. 데이터베이스의 전개는 DB2 백업 이미지를 사용하거나 데이터베이스는 로드 파일로 추출된 데이터에서 구현될 수 있다. 저장 프로시저, 트리거, 뷰, 사용자 정의 함수 같은 애플리케이션 객체들이 알맞게 정의되고 액세스 가능한지를 확인하라.
DB2 Express-C는 리눅스, 유닉스, Windows용 전체 DB2 서버와 같은 데이터베이스 서버 핵심 기술을 바탕으로 하고, DB2 UDB V8.1과 V8.2에 도입된 많은 기능들은 DBA의 관리 작업을 돕는다. DB2 DBA는 테라바이트의 DB2 시스템 또는 DB2 서버를 관리한다. DB2 Express-C에서는 자가 관리와 자가 튜닝 기능도 사용할 수 있기 때문에 최소한의 DB2 DBA의 기술로도 DB2 Express-C 데이터베이스 서버를 사용하는 애플리케이션의 가용성을 최대화 할 수 있다.
Cloudscape는 순수 자바 데이터베이스 서버이고 자바 애플리케이션이나 중간 규모의 웹 애플리케이션용 임베디드 데이터베이스 엔진으로서 이상적이다. Cloudscape V10은 2004년 IBM에서 처음 릴리스 되었다. 당시에는 무료의 데이터베이스 서버 라이센스로 릴리스 되었다. 동시에 같은 코드 베이스를 가진 Apache Derby Project가 Apache Software Foundation의 인큐베이터 프로젝트로서 시작되었다. ( 참고자료 ) Cloudscape V10은 2005년 8월에 업데이트 되었다. Cloudscape V10.1 릴리스 이전에 Apache Software Foundation의 Derby Project가 인큐베이션 단계에서 벗어나서 Apache DB 프로젝트의 정식 멤버가 되었다. 매우 활동적인 커뮤니티가 있고 데이터베이스 서버는 많은 고객, 연구원, 비즈니스 파트너들이 사용하고 있다. Cloudscape V10.1은 Derby 10.1 코드 베이스에 인스톨러, 드라이버, 툴 등이 추가된 것이다. IBM은 Cloudscape V10.1 고객을 위해 지원 옵션을 제공한다.
IBM Virtual Innovation Center( 그림 17)에서는 ISV(독립 소프트웨어 벤더)와 비즈니스 파트너를 위한 애플리케이션을 제공하고 있다. 솔루션에 DB2 Express Edition V8.2.2를 사용할 계획이 있다면 반드시 등록해야 한다. 그림 17. IBM Virtual Innovation Center - DB2 Express
DB2 Express-C는 독특한 기능을 가진 데이터 서버의 새로운 대안이다. DB2 Express-C를 다운로드 하여 사용하고 DB2 사용자 커뮤니티에도 참여하기 바란다. 교육
제품 및 기술 얻기
토론 |
난이도 : 초급
Roman Melnyk, DB2 Information Development, IBM Canada Ltd.
2004 년 1 월 01 일
DB2 UDB에서 사용되는 제약조건은 데이터에 대해 비즈니스 규칙을 시행하고 데이터베이스 무결성을 유지하는데 도움이 된다. 이 글에서는 DB2 UDB에서 지원하는 다양한 제약조건 유형들을 설명한다. 각 제약조건 유형들을 예제를 통해 설명한다. 또한 기본적인 제약조건 관리(명령행 또는 DB2 Control Center 사용)를 설명한다.
DB2 UDB에서 사용되는 제약조건은 데이터에 대해 비즈니스 규칙을 시행한다. 이 글에서는 다음과 같은 유형의 제약조건을 설명한다.
- NOT NULL
- 유일(unique)
- 기본 키
- 외래 키
- 테이블 체크
새로운 테이블을 만들 때 한 개 이상의 DB2 UDB 제약조건을 정의하거나, 테이블을 나중에 변경하여 몇 가지 제약조건을 정의할 수 있다. CREATE TABLE 문은 매우 복잡하다. 사실 너무 복잡해서 이 옵션들 중 일부가 제약조건 정의에 사용되더라도 신택스 다이어그램에서 볼 때에는 옵션들 자체로도 매우 복잡해보인다. (그림 1, 그림 2) 제약조건 관리는 DB2 Control Center를 통해 수행될 때 보다 편리하고 단순해질 수 있다.
그림 1. CREATE TABLE 문의 신택스 일부– 제약조건을 정의하는데 사용되는 구문을 보여주고 있다.
제약조건 정의는 이 정의가 적용될 데이터베이스와 제휴되고 데이터베이스 카탈로그에 저장된다.(표 1) 데이터베이스 카탈로그를 쿼리하여 정보들을 가져와서 검사한다. 명령행에서 직접 수행할 수 있고(물론, 데이터베이스에 먼저 연결해야 한다.), 또는 Control Center를 통해서 보다 편리하게 정보에 액세스 한다.
여러분이 만든 제약조건은 데이터베이스 객체들 처럼 다루어진다. 이름이 붙여지며, 제휴 스키마(생성자 ID)를 갖게 되며, 어떤 경우에는 제거(삭제)될 수도 있다.
그림 2. CREATE TABLE 문의 신택스 일부 – 제약조건을 정의하는데 사용되는 구문을 보여주고 있다. (계속)
표 1. 데이터베이스 카탈로그에 있는 제약조건 정보. 성공적으로 실행하려면 그 카탈로그에 대한 쿼리에는 데이터베이스 연결이 필요하다.
Catalog View | View Column | 설명 | 쿼리 예제 |
SYSCAT.CHECKS | 각 테이블 체크 제약조건에 대한 열이 포함된다. | db2 select constname, tabname, text from syscat.checks | |
SYSCAT.COLCHECKS | 테이블 체크 제약조건에 의해 참조되는 각 칼럼에 대한 열을 포함하고 있다. | db2 select constname, tabname, colname, usage from syscat.colchecks | |
SYSCAT.COLUMNS | NULLS | 칼럼이 무효인지(Y), 무효가 아닌지(N)를 나타낸다. | db2 select tabname, colname, nulls from syscat.columns where tabschema = 'MELNYK' and nulls = 'N' |
SYSCAT.CONSTDEP | 몇 가지 다른 객체에 해당하는 제약조건의 종속성에 대한 열을 포함하고 있다. | db2 select constname, tabname, btype, bname from syscat.constdep | |
SYSCAT.INDEXES | 각 인덱스에 대한 열을 포함하고 있다. | db2 select tabname, uniquerule, made_unique, system_required from syscat.indexes where tabschema = 'MELNYK' | |
SYSCAT.KEYCOLUSE | 유일 키, 기본 키, 외래 키 제약조건으로 정의된 키에 참여한 각 칼럼에 대한 열을 포함하고 있다. | db2 select constname, tabname, colname, colseq from syscat.keycoluse | |
SYSCAT.REFERENCES | 각각의 참조 제약조건에 대한 열을 포함하고 있다. | db2 select constname, tabname, refkeyname, reftabname, colcount, deleterule, updaterule from syscat.references | |
SYSCAT.TABCONST | 유일 키(U), 기본 키 (P), 외래 키 (F), 테이블 체크 (K) 제약조건에 대한 열을 포함하고 있다. | db2 select constname, tabname, type from syscat.tabconst | |
SYSCAT.TABLES | PARENTS | 이 테이블의 부모 테이블의 수(이 테이블이 종속되어 있는 참조 제약조건의 수). | db2 "select tabname, parents from syscat.tables where parents > 0" |
SYSCAT.TABLES | CHILDREN | 이 테이블의 종속 테이블의 수(이 테이블이 부모가 되는 참조 제약조건의 수). | db2 "select tabname, children from syscat.tables where children > 0" |
SYSCAT.TABLES | SELFREFS | 이 테이블에 대한 자가 참조 제약조간의 수(이 테이블이 부모이기도 하고 종속 테이블인 참조 제약조건의 수). | db2 "select tabname, selfrefs from syscat.tables where selfrefs > 0" |
SYSCAT.TABLES | KEYUNIQUE | 이 테이블에 정의된 (기본 키 외의) 유일 제약조건의 수. | db2 "select tabname, keyunique from syscat.tables where keyunique > 0" |
SYSCAT.TABLES | CHECKCOUNT | 이 테이블에 정의된 체크 제약조건의 수. | db2 "select tabname, checkcount from syscat.tables where checkcount > 0" |
NOT NULL 제약조건으로 인해 무효(null) 값이 칼럼에 추가될 수 없다. 이것 때문에 칼럼은 테이블의 각 열에 값을 갖게 된다. 예를 들어, SAMPLE 데이터베이스에 있는 EMPLOYEE 테이블의 정의에는 LASTNAME VARCHAR(15) NOT NULL
이 포함된다. 이로 인해 각 열에는 사원(EMPLOYEE)의 성(last name)이 포함된다.
칼럼의 무효성 여부를 결정하기 위해서 그 테이블에 대한 데이터 정의 언어(DDL)를 참조할 수 있다. (db2look 유틸리티를 호출하여 생성한다.) DB2 Control Center(그림 3과 4)를 사용해도 된다. 또는 데이터베이스 카탈로그를 쿼리 할 수도 있다. (Listing 1)
그림 3. 특정 데이터베이스와 연결된 테이블은 DB2 Control Center의 컨텐츠 패인에 객체 트리에서 선택된 테이블과 함께 나타난다. 이 리스트는 melnyk 스키마에서 걸려졌다.
DB2 Control Center에서는 테이블 같은 데이터베이스 객체에 편리하게 액세스 할 수 있다. 그림 3은 SAMPLE 데이터베이스의 사용자 테이블 모습이다. Table이 객체 트리에서 선택될 때 컨텐츠 패인에 나타난다. EMPLOYEE 테이블을 선택하면 Alter Table 창을 열어 칼럼 애트리뷰트 등 테이블 정보를 볼 수 있다. (그림 4)
그림 4. Alter Table 윈도우에서는 테이블의 애트리뷰트를 편리하게 볼 수 있다.
Listing 1. 데이터베이스 카탈로그를 쿼리하여 어떤 데이터베이스 칼럼이 무효인지를 파악하기
db2 select tabname, colname, nulls from syscat.columns where tabschema = 'MELNYK' and nulls = 'N' |
|
유일 제약조건(unique constraint)은 테이블의 특정 칼럼에 값이 한번 이상 나타나지 않도록 한다. 또한 특정 칼럼 세트 내에 값 세트가 한 번 이상 나타나지 않도록 한다. 유일 제약조건에서 참조되는 칼럼들은 NOT NULL로 정의되어야 한다. 유일 제약조건은 CREATE TABLE 문에서 UNIQUE 구문을 사용하여 정의되거나(그림 1과 2), ALTER TABLE 문으로 정의될 수 있다.
Listing 2. 유일 제약조건 만들기. SAMPLE 데이터베이스에서 ORG_TEMP 테이블은 ORG 테이블과 동일하다. 단, ORG_TEMP의 LOCATION 칼럼은 무효가 될 수 없고 유일 제약조건이 정의된다.
db2 create table org_temp ( deptnumb smallint not null, deptname varchar(14), manager smallint, division varchar(10), location varchar(13) not null) db2 alter table org_temp add unique (location) db2 insert into org_temp values (10, 'Head Office', 160, 'Corporate', 'New York') DB20000I The SQL command completed successfully. db2 insert into org_temp values (15, 'New England', 50, 'Eastern', 'New York') SQL0803N One or more values in the INSERT statement, UPDATE statement, or foreign key update caused by a DELETE statement are not valid because the primary key, unique constraint or unique index identified by "1" constrains table "MELNYK.ORG_TEMP" from having duplicate rows for those columns. SQLSTATE=23505 |
유일 제약조건은 의도하지 않은 중복을 방지하여 데이터 무결성을 유지시킨다. 우리 예제에서, New York을 그 회사의 지사로 지정하는 두 번째 기록이 삽입되는 것을 방지한다. 유일 제약조건은 유일 인덱스(unique index)를 통해 실행된다.
|
|
기본 키 제약조건은 테이블에 대한 기본 키를 구성하고 있는 칼럼이나 칼럼 세트의 모든 값들이 유일(unique)한 값이라는 것을 보장한다. 기본 키는 테이블의 특정 열을 구분하는데 사용된다. 테이블은 한 개 이상의 기본 키를 가질 수 없지만 여러 유일 키를 가질 수는 있다. 기본 키 제약조건은 유일 제약조건의 특별한 경우이며 기본 인덱스(primary index)를 통해 실행된다.
기본 키 제약조건에 참조된 칼럼들은 NOT NULL로 정의되어야 한다. 기본 키 제약조건은 PRIMARY KEY 구문을 사용하여 CREATE TABLE 문으로 정의되거나(그림 1과 2), ALTER TABLE 문으로 정의된다.
Listing 3. 기본 키 제약조건 만들기. EMPLOYEE 테이블에 있는 EMPNO 칼럼은 무효가 될 수 없고, 여기에 기본 키 제약조건이 정의되어야 한다.
db2 alter table employee add primary key (empno) |
대안으로는, DB2 Control Center를 사용하여 테이블에 기본 키 제약조건을 정의하는 방법이 있다. (그림 5)
그림 5. Alter Table 윈도우에서는 테이블에 기본 키 제약조건을 편리하게 정의할 수 있다. 칼럼 리스트에서 한 개 이상의 칼럼을 선택한 다음 push 버튼을 누르고, 그렇게 선택된 칼럼 이름을 기본 키 칼럼 리스트로 이동시킨다. 선택된 칼럼은 무효가 될 수 없다.
|
외래 키 제약조건은 참조 제약조건이라고도 불린다. 참조 무결성(Referential integrity)은 "데이터베이스에서 모든 외래 키들의 값이 유효한 상태”로 정의된다. 그렇다면 외래 키는 무엇인가? 외래 키(foreign key)는 테이블에 있는 칼럼이나 칼럼 세트의 값이 부모 테이블의 열에 있는 적어도 한 개의 기본 키나 유일 키 값과 매치하는 것을 의미한다. 더 정확히 말한다면? 테이블(T2)에 있는 칼럼(C2)이 또 다른 테이블(T1)에 있는 칼럼(C1)의 값들과 매치하는 값을 갖고 있고, C1은 T1에 대한 기본 키 칼럼이 되고, C2는 T2의 외래 키 칼럼이 된다는 것을 의미한다. 기본 키(기본 키 또는 유일 키)를 포함하고 있는 테이블을 부모 테이블(parent table)이라 하고, 외래 키를 포함하고 있는 테이블을 종속 테이블(dependent table)이라고 한다.
SAMPLE 데이터베이스에 있는 PROJECT 테이블은 RESPEMP라는 칼럼을 갖고 있다. 이 칼럼에 있는 값은 이 테이블에 수록되어 있는 각 프로젝트를 담당하는 사원들의 수를 나타낸다. RESPEMP는 무효가 될 수 없다. 이 칼럼은 EMPLOYEE 테이블의 EMPNO 칼럼에 상응하고, 우리는 EMPNO가 이제는 EMPLOYEE 테이블에 대한 기본 키라는 것을 알고, RESPEMP는 PROJECT 테이블에서 외래 키로 정의될 수 있기 때문이다.(Listing 4) 따라서 EMPLOYEE 테이블에서 삭제가 실행되면 프로젝트 담당 사원이 없는 PROJECT 테이블은 존재하지 않는다.
외래 키 제약조건은 FOREIGN KEY 구문(그림 1과 2)을 사용하는 CREATE TABLE 문으로 정의되거나, ALTER TABLE 문으로 정의된다.
Listing 4. 외래 키 제약조건 만들기
db2 alter table project add foreign key (respemp) references employee on delete cascade |
REFERENCES 구문은 이 참조 제약조건에 대한 부모 테이블을 가리킨다. 외래 키 제약조건을 정의하는 신택스에는 rule-clause가 포함되는데, 바로 여기에서 무결성의 관점에서 업데이트나 삭제 방식을 DB2에 명령할 수 있다.(그림 1)
삽입 작동은 표준 방식으로 다루어진다. 여러분은 이에 대한 제어권이 없다. 참조 제약조건의 삽입 규칙(insert rule)은 외래 키의 삽입 값이 부모 테이블의 부모 키의 값 일부와 매치해야 한다는 것을 지정하고 있다. 새로운 기록이 PROJECT 테이블에 삽입되면 그 기록에는 EMPLOYEE 테이블의 기존 기록에 대한 (부모-외래 키 관계를 통해) 참조를 포함하고 있어야 한다.
참조 제약조건의 업데이트 규칙(update rule)은 외래 키의 업데이트 값이 부모 테이블의 부모 키의 일부 값과 매치해야 하고, 부모 키에 대한 업데이트 작동이 완료할 때 모든 외래 키 값은 매칭하는 부모 키 값을 갖고 있어야 한다는 것을 지정하고 있다. 다시 말하면, 어떤 "고아"도 없어야 한다. 모든 종속들은 부모가 있어야 한다.
참조 제약조건의 삭제 규칙(delete rule)은 부모 테이블에서 열이 삭제될 때 적용되고, 참조 제약조건이 정의될 때 지정되었던 옵션에 의존한다. RESTRICT나 NO ACTION 구문이 지정되면 어떤 열도 삭제되지 않는다. SET NULL 구문이 지정되면 외래 키의 무효가 가능한 칼럼들이 무효로 설정된다. 하지만 참조 제약조건을 만들 때 CASCADE 옵션을 지정했다면 삭제 작동은 부모 테이블의 자식들에게로 퍼진다.
다음 예제는 위에 설명한 것들을 나타낸 것이다.
Listing 5. 외래 키 제약조건에서의 업데이트 규칙과 삭제 규칙
db2 update employee set empno = '350' where empno = '000190' DB20000I The SQL command completed successfully. db2 update employee set empno = '360' where empno = '000150' SQL0531N The parent key in a parent row of relationship "MELNYK.PROJECT.SQL040103212526610" cannot be updated. SQLSTATE=23504 db2 "select respemp from project where respemp < '000050' order by respemp" RESPEMP ------- 000010 000010 000020 000030 000030 db2 delete from employee where empno = '000010' DB20000I The SQL command completed successfully. db2 "select respemp from project where respemp < '000050' order by respemp" RESPEMP ------- 000020 000030 000030 |
부모 테이블(EMPLOYEE)에 있는 EMPNO 값 '000190'은 변경될 수 있다. 종속 테이블(PROJECT)에 '000190' RESPEMP 값이 없기 때문이다. 하지만 EMPNO 값 '000150'는 경우가 다르다. 이것은 PROJECT 테이블에 매칭하는 외래 키 값을 갖고 있고 따라서 업데이트 될 수 없다. CASCADE 옵션을 지정한 삭제 규칙으로 인해 기본 키 값 '000010'이 EMPLOYEE 테이블에서 삭제되면 삭제 연결된(delete-connected) PROJECT 테이블은 매칭하는 외래 키 값을 포함하고 있는 모든 열을 잃게 된다.
|
테이블 체크 제약조건(table check constraint)은 데이터에 정의된 제한들이 테이블에 추가될 수 있도록 한다. 예를 들어, 테이블 체크 제약조건은 EMPLOYEE 테이블에 내선 번호가 추가 및 업데이트 될 때 정확히 4자리 수가 되도록 한다. 테이블 체크 제약조건은 CHECK 구문을 사용하여 CREATE TABLE 문으로 정의되거나(그림 1과 2), ALTER TABLE 문으로 정의된다.
Listing 6. 테이블 체크 제약조건 만들기. PHONENO_LENGTH 제약조건은 EMPLOYEE 테이블에 추가되는 내선번호를 4자리 숫자로 지정한다.
db2 alter table employee add constraint phoneno_length check (length(rtrim(phoneno)) = 4) |
대안으로는 DB2 Control Center를 사용하여 테이블 체크 제약조건을 정의할 수 있다. (그림 6)
그림 6. Alter Table 윈도우에서 테이블 체크 제약조건을 편리하게 정의할 수 있다.
Add 버튼을 클릭하여 새로운 제약조건(Add Check Constraint 옵션)을 정의하거나, Change 버튼을 눌러 기존 제약조건을 변경한다.(그림 7)
그림 7. Change Check Constraint 창에서 기본 체크 조건을 변경할 수 있다.
이 테이블의 기존 열의 값이 새로운 제약조건을 위반한다면 테이블 체크 제약조건을 만들 수 없다.(그림 8) 이렇게 비 호환되는 값이 적절히 업데이트 된 후에 제약조건을 추가하거나 수정할 수 있다.
그림 8. 새로운 테이블 체크 제약조건이 테이블의 기본 값과 호환되지 않는다면 에러가 리턴된다.
|
테이블 체크 제약조건은 SET INTEGRITY 문을 사용하여 실행되거나 실행되지 않는다. 테이블에 대해 대규모의 데이터 부하가 걸려있는 동안 퍼포먼스를 최적화 할 때 매우 유용하다. Listing 7은 SET INTEGRITY 문을 사용하는 시나리오이다. 이 예제에서 EMPLOYEE 테이블의 무결성 체크가 비활성 된 후에, 사원 '000100 '의 내선 번호는 123 값으로 업데이트 된다. 4자리 숫자의 내선 번호 값이 필요한 체크 제약조건은 EMPLOYEE 테이블에서 정의된다. EMPL_EXCEPT 라고 하는 예외 테이블이 만들어 진다. 이 새로운 테이블의 정의는 EMPLOYEE 테이블의 정의를 모방한 것이다. 무결성 체크가 활성화 되면, 이러한 테이블에 대한 쿼리는 해당 열이 예외 테이블에만 존재하는지를 확인한다.
Listing 7. SET INTEGRITY 문을 사용하여 제약조건 체크 연기하기
db2 update employee set phoneno = '123' where empno = '000100' db2 set integrity for employee off db2 alter table employee add constraint phoneno_length check (length(rtrim(phoneno)) = 4) db2 create table empl_except like employee db2 set integrity for employee immediate checked for exception in employee use empl_except SQL3602W Check data processing found constraint violations and moved them to exception tables. SQLSTATE=01603 db2 select empno, lastname, workdept, phoneno from empl_except EMPNO LASTNAME WORKDEPT PHONENO ------ --------------- -------- ------- 000100 SPENSER E21 123 1 record(s) selected. |
|
지금까지 DB2 Universal Database에서 지원하는 여러 가지 제약조건 유형들을 살펴보았다. 이러한 제약조건들이 DB2 UDB에 사용되어 데이터에 대해 비즈니스 규칙을 실행하고 데이터 무결성을 유지하는 방법도 알았다. 또한, 제약조건을 효과적으로 관리하는 방법으로 명령행과 DB2 Control Center의 사용법에 대해서도 배웠다.
|
|
Roman Melnyk, DB2 Information Development, IBM |
[출처] [한글]DB2 기초: 제약조건 |작성자 미운오리
개인 홈페이지라면 별 신경 안쓰는데 회사 홈페이지 작업시 그냥
utf-8로 바꾸었다가 글씨 다 깨지면 난리나니까 걱정입니다. OTL
[애로사항]
1. 현재 작업중인 사이트가 euc-kr 인코딩으로 저장된 것들인데
utf-8로 바꾸려면 파일들 전부 열어서 utf-8로 저장해야 되죠? ㅠ_ㅠ
2. 사이트 제작시 사용하는 엔진프로그램이 있는데 이것도 당연히
euc-kr로 되어 있으므로 전부 열어서 새로 저장해야 할텐데 이럴경우
어떤 프리랜서 디자이너가 euc-kr로 작업해서 가져올경우 대략 난감
해집니다. 프로그램을 euc-kr, utf-8 두가지 버전으로 가지고 있어야
할까요? ㅡ0ㅡ;
3. euc-kr로 저장된 파일을 utf-8로 저장하면 한글 다 깨지는거 아닐
까요?
4. 어차피 지금 euc-kr로 작업한 사이트는 지나가고 다음부터 utf-8로
작업할시 주의해야 할 사항이 있다면 가르쳐주세요. 하지만 위의
엔진프로그램은 앞으로도 계속 사용해야 하기 때문에 위와같은 문제
발생시 난감해집니다. 파일을 열지않고 모두 인코딩 변환해주는거
없을까요?
이번에 css레이아웃 기반의 사이트를 2개 오픈하였는데 정말 너무
힘들었습니다. 아직 디자이너들이 css레이아웃을 잘 사용하지 못해서
제가 코딩을 거의 다했거든요. 교육은 수시로 하지만 테이블 레이아웃
개념에서 잘 못빠져 나오고 id와 class의 조합등 여러 응용력이 너무
부족한게 현실입니다. 이 상태에서 euc-kr을 utf-8로 바꾸는 작업
했다가는 저 죽을지도 모릅니다. ㅡㅡ; 과로사!
그리고 이번에 오픈한 사이트중 하나는 다국어 사이트 입니다.
뭐 해봤자 중국어, 영어, 일본어 일텐데 영어는 문제 없을 것 같지만
중국어, 일본어는 euc-kr로 작업하면 안되겠죠? 큰일이다 ㅠ_ㅠ
겁나서 손을 못대고 있습니다. euc-kr에서 utf-8로 옮겨가는 것에
대한 허와 실을 가르쳐 주십시오. .(__).
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
일반적인 리눅스 배포본에는 iconv라고 거의 있을겁니다.(glibc패키지에 딸려있는)
- Code: Select all
$ iconv --from-code=cp949 --to-code=utf-8 원하는파일.txt --output=바뀐파일.txt
이런식으로 인코딩을 변경해서 씁니다.
저런 툴이 윈도우즈 환경에도 있을겁니다. 정적인 페이지의 경우는 일괄적으로 변경하고 헤더에 인코딩 지정을 utf-8로 바꿔주시면 될것 같습니다.
동적으로 생성되는 페이지들의 경우는 잘 모르겠습니다.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
뭐, 그렇게 길게 쓰셔도 상관 없습니다만, 짧은 옵션을 쓸 수도 있습니다.
- Code: Select all
iconv -f cp949 -t UTF-8 input > output
iconv -f cp949 -t utf-8 -o output input
Windows용으로도 libiconv를 이식해 놓은 것이 있으므로 거기에 들어 있는 iconv를 쓸 수 있습니다. 또 다른 방법은 Win32 API인 MultiByteToWideChar와 WideCharToMultiByte를 써서 변환하는 C 프로그램을 하나 짤 수도 있습니다.
(Perl 5.8 이상이나 Python 2.4 이상에 들어 있는 인코딩 변환 모듈을 써도 물론 되고요)
아니면, JDK에 들어 있는 native2ascii를 2개 연결해서 쓰는 수도 있습니다.
- Code: Select all
native2ascii -encoding MS949 inputfile tempfile
native2ascii -encoding UTF-8 -reverse tempfile outputfile
html 파일 뿐 아니라 php, jsp. javascript 등도 파일에서 한글을 'raw string'(literal string)으로 쓰고 있었다면 위와 같은 식으로 일단 바꾸십시오. 그 후에 각 파일에서 euc-kr로 charset 선언을 한 부분도 모두 utf-8로 바꿔야겠지요. 혹시, 웹 서버 설정으로 (apache와 tomcat 등) http header를 통해 'charset=EUC-KR'을 내보내도록 된 부분이 있으면 명시적으로 http header를 통해 charset을 내보내지 않도록 하거나, UTF-8를 내보내도록 바꾸십시오.
jsp의 경우 다음처럼 문자 인코딩 설정을 해 주세요:
- Code: Select all
<%@ page contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
%>
contentType은 http 헤더를 통해 내보낼 C-T의 값일 뿐 아니라 실제로 밖으로 나가는 문서의 인코딩입니다. pageEncoding은 jsp 파일의 인코딩입니다. jsp 파일은 EUC-KR이면서 밖으로 나가는 (jsp를 컴파일한 후에 servlet engine이 내보내는) 문서의 인코딩은 UTF-8일 수 있습니다. 그 경우에는 다음과 같이 선언하면 됩니다.
- Code: Select all
<%@ page contentType="text/html; charset=UTF-8"
pageEncoding="EUC-KR"
%>
jsp나 servlet을 써서 form processing을 할 때에는 또 다른 값을 설정해 주어야 합니다.
- Code: Select all
javax.servlet.ServletResponse.setCharacterEncoding("UTF-8")
- Code: Select all
request.setCharacterEncoding("UTF-8")
이렇게 해도 get으로 받은 form의 인코딩이 이상할 것입니다. (post는 이상 없습니다).
http://okjsp.pe.kr/bbs?act=VIEW&seq=410 ... word=&pg=5
('KSC5601'을 쓰라고 한 자리에 'UTF-8'을 쓰세요)애 았는 방법도 쓸 수 있지만, 다음을 server.xml에 넣는 것이 더 나을 것입니다.
- Code: Select all
<Connector port="8080" maxThreads="150" minSpareThreads="25"
maxSpareThreads="75" enableLookups="false" redirectPort="8443"
acceptCount="100" debug="0" connectionTimeout="20000"
disableUploadTimeout="true"
useBodyEncodingForURI="true">
http://java.sun.com/developer/technical ... ingualJSP/
php라면 mbstring, iconv 모듈이 포함되어 있는 것을 쓰시는 것이 좋습니다.
어느 경우라도 한글은 2byte, 라틴 글자는 1byte라는 가정 하에 바이트 수를 세어서 글자 수를 계산하던 방식은 통하지 않는다는 것에도 유의하십시오.
DB backend에서도 UTF-8 혹은 다른 Unicode transformation form을 쓰도록 설정하셔야겠지요. MySQL이라면 필히 4.x 이상을 쓰셔야 multibyte encoding을 제대로 지원해 줍니다. posgresql은 최근 몇 년 사이에 나온 것은 다 잘 지원합니다. Oracle, Sybase, DB2 등도 잘 지원하고요. (단, Oracle에서 UTF8은 진짜 UTF-8이 아니므로 - Oracle이 유니코드 표준을 잘못 이해해서 만든 이상한 인코딩임- altutf8을 쓰셔야 합니다. Unicode의 첫번째 65,536자만 쓸 경우에 차이가 없기는 하지만, 혹시 나중에 그 이후의 글자를 써야할 일이 있을 때 생길 문제를 미리 방지하기 위함입니다.)
JDBC로 DB에 연결할 때에도 문자 인코딩을 지정하는 것을 잊지 마십시오.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
txt 파일이야...다시 만드는 거니까 문제가 없지만...DB 가 문제더군요.
저같은 경우 리뉴얼작업을 주로 해왔는데 DB 가 utf-8 로 되어 있는 경우는 한번도 못봤습니다.
서버를 새로 까는 경우는 한번도 없었어요.
기존의 서버 설정을 따라야 하는데...그러한 것들이 utf-8 로 넘어가는데 큰 걸림돌인것 같아요.
제가 개발쪽을 잘 몰라서 어렵게 느껴지는 것일 지도...ㅎㅎ
제 개인 홈페이지는 아주 간단하게 utf-8 로 바꿨습니다.
파일 다 열어서 utf-8 로 바꾸고, Data 파일(저는 text data 만 사용합니다. --;;) 다 열어서 바꾸고....끝
제 생각인데 utf-8 을 사용하려면 server level 을 마음대로 수정 할 수 있을 때에나 가능 할 것 같네요.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
hyeonseok 님의 글:txt 파일이야...다시 만드는 거니까 문제가 없지만...DB 가 문제더군요.
저같은 경우 리뉴얼작업을 주로 해왔는데 DB 가 utf-8 로 되어 있는 경우는 한번도 못봤습니다.
서버를 새로 까는 경우는 한번도 없었어요.
기존의 서버 설정을 따라야 하는데...그러한 것들이 utf-8 로 넘어가는데 큰 걸림돌인것 같아요.
기존의 DB를 UTF-8로 바꾸는 가장 쉬운 방법은 현재 내용을 모두 덤프한 다음에 그 덤프한 파일을 iconv나 다른 인코딩 변환 도구로 UTF-8로 바꾸고, 그 결과를 DB에 다시 넣는 것입니다. 즉, 벡업으로부터 복구하는 과정과 비슷한데, 다만 인코딩을 바꾸는 과정이 중간에 들어간 셈입니다. 물론, DBMS에 따라서 필드 크기 등을 조절할 필요가 있을 수도 있습니다.
DBMS에 따라 다르지만, 전체 DBMS 수준의 인코딩, 그 안에서 개별 DB의 인코딩, 개별 DB 안의 table 인코딩(심지어 테이블 안의 field 별 인코딩도 따로 지정할 수 있는 DBMS도 있지요)을 독립적으로 지정할 수 있으므로 DBMS 전체의 설정을 변경할 필요(혹은 그런 변경을 하는데 필요한 권한을 가질 필요)는 없을 것입니다.
참, UTF-8을 쓸 경우 DBMS의 데이터 저장 방식에 따라 다르겠지만, EUC-KR에 비해 크기가 늘어난다는 점은 유의해야할 것입니다. 따라서, 한글이나 한자가 차지하는 비중이 매우 높다면, UTF-8 대신 UTF-16을 쓰는 것도 고려해 볼 수 있습니다. DB에서 UTF-16을 쓰는 경우라도 바깥 세상과 소통을 할 때에는 (html을 만들어 내보낼 때) UTF-8을 쓰는 것이 더 나을 것입니다.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
한국 웹의 현실을 개선하기 위해 일선 현장에서 실천하시면서 결과물을 내놓고 계셔서 제가 오히려 감사 드려야 할 듯 싶습니다.참, 위에 적을 때 깜박 잊었는데, 혹시 UTF-8 편집기(윈도우즈용)를 고르고 계신다면 다음 글에서 언급한 jEdit가 꽤 괜찮은 것 같아 보입니다.
http://www.ktug.or.kr/jsboard/read.php? ... 558&page=2
UTF-8을 잘 지원하는 Windows용 ssh client로는 putty가 있습니다.
(Appearance | Translation에서 UTF-8을 고를 수 있습니다)
http://www.chiark.greenend.org.uk/~sgtatham/putty/
한국에서 개발한 token도 ssh를 지원하면서 UTF-8도 지원했던 것 같은데, 확실하지 않습니다.
Paul Yip, Database Consultant, IBM Toronto Lab
2003 년 8 월 28 일
Windows, UNIX, 리눅스 플랫폼용 DB2 Universal Database에서 SQL을 사용하여 날짜, 시간, 타임스탬프를 조작하는 방법을 설명한다.
© 2002 International Business Machines Corporation. 저작권 소유.
알림:이 글을 읽기 전에 디스클레이머를 읽기 바란다.
IBM® DB2® Universal DatabaseTM에 관한 글이다.
머리말
DB2 UDB에 익숙하지 않은 사람들에게 날짜와 시간을 조작하는 방법을 설명한다. 다른 데이터베이스를 다뤄본 많은 사람들에게 DB2 UDB가 얼마나 쉬운지를 설명하겠다.
기초
SQL을 사용하여 날짜, 시간, 타임스탬프를 파악하려면 해당 DB2 레지스터리를 참조하라.
SELECT current date FROM sysibm.sysdummy1
SELECT current time FROM sysibm.sysdummy1
SELECT current timestamp FROM sysibm.sysdummy1
sysibm.sysdummy1 테이블은 위에서 설명한 대로 DB2 레지스터의 값을 찾는데 사용할 수 있는 특별한 인메모리(in-memory) 테이블이다. VALUES 키워드를 사용하여 레지스터나 식을 계산할 수 있다. 예를 들어, DB2 Command Line Processor (CLP)에서 다음 SQL 문장에는 비슷한 정보들이 나타난다.
VALUES current date
VALUES current time
VALUES current timestamp
남아있는 예제에는 SELECT ... FROM sysibm.sysdummy1을 반복하거나 VALUES 구문을 사용하지 않고 함수 또는 식을 제공하도록 하겠다.
GMT/CUT에 맞춘 현재 시간이나 현재 타임스탬프를 얻으려면 현재 시간 또는 타임스탬프에서 현재 타임존 레지스터를 제거한다.
current time - current timezone
current timestamp - current timezone
날짜 시간, 타임스탬프의 경우, 적절한 함수를 사용하여 년도, 달, 요일, 시간, 분, 초, 마이크로초를 추출할 수 있다.
YEAR (current timestamp)
MONTH (current timestamp)
DAY (current timestamp)
HOUR (current timestamp)
MINUTE (current timestamp)
SECOND (current timestamp)
MICROSECOND (current timestamp)
타임스탬프와 관계없이 날짜와 시간을 추출하는 것 역시 매우 쉽다.
DATE (current timestamp)
TIME (current timestamp)
영어로도 날짜와 시간 계산을 할 수 있다. :
current date + 1 YEAR
current date + 3 YEARS + 2 MONTHS + 15 DAYS
current time + 5 HOURS - 3 MINUTES + 10 SECONDS
두 날짜 간에 날수가 얼마나 되는지를 계산하려면 날짜를 빼면 된다.
days (current date) - days (date('1999-10-22'))
다음은 마이크로초 부분을 0으로 재설정하고 현재 타임스탬프를 얻는 방법이다.
CURRENT TIMESTAMP - MICROSECOND (current timestamp) MICROSECONDS
날짜 또는 시간 값을 다른 텍스트와 연결시키려면 그 값을 문자열로 변환해야 한다. CHAR() 함수를 사용한다.
char(current date)
char(current time)
char(current date + 12 hours)
문자열을 날짜 또는 시간 값으로 변환하려면 다음과 같이 한다.
TIMESTAMP ('2002-10-20-12.00.00.000000')
TIMESTAMP ('2002-10-20 12:00:00')
DATE ('2002-10-20')
DATE ('10/20/2002')
TIME ('12:00:00')
TIME ('12.00.00')
TIMESTAMP(), DATE(), TIME() 함수는 여러 포맷들을 허용한다. 위 포맷은 단순한 예제일 뿐이다. 독자 여러분이 스스로 해 보길 바란다.
경고:
DB2 UDB V8.1 SQL Cookbook (Graeme Birchall) 발췌 (http://ourworld.compuserve.com/homepages/Graeme_Birchall).
DATE 함수에서 쿼트를 없애면 어떻게 될까? 함수는 여전히 작동하겠지만 정확하지 않은 DATE가 나올 것이다.
SELECT DATE(2001-09-22) FROM SYSIBM.SYSDUMMY1;
결과:
======
05/24/0006
위 결과에서 어떻게 2000년 이나 차이가 났을까? DATE 함수가 입력으로 문자열을 취하면 DB2 날짜의 유효 문자로 간주되고, 따라서 이를 변환하는 것이다. 반대로, 입력이 숫자라면 이 함수는 현재 년도(0001-01-01)에서 1을 제한 날 수를 나타내는 것으로 간주한다. 위 쿼리에서 입력은 2001-09-22였고 이것은 (2001-9)-22과 동일하다. 또한 이것은 1970이다.
위로
날짜 함수
가끔씩, 두 개의 타임스탬프들이 어떻게 차이가 있는지 알아야 한다. 이를 위해 DB2는 TIMESTAMPDIFF()라고 하는 빌트인 함수를 제공한다. 하지만 리턴된 값은 근사값이다. 윤년을 고려하지 않고 한 달을 30일로만 가정하기 때문이다. 다음은 두 날짜들 간 차이를 찾아내는 방법이다.
timestampdiff (
timestamp('2002-11-30-00.00.00')-
timestamp('2002-11-08-00.00.00')))
1 = 초의 소수부분
2 = 초
4 = 분
8 = 시간
16 = 요일
32 = 주
64 = 달
128 = 분기
256 = 년
timestampdiff()를 사용하면 날짜가 비교적 가까이 있을 때 더 정확한 결과가 나온다. 보다 정확한 계산을 원하면 다음을 사용하여 시간 단위로(초 단위로) 차이를 결정한다.
(DAYS(t1) - DAYS(t2)) * 86400 +
(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))
SQL의 사용자 정의 함수를 사용할 수도 있다.
CREATE FUNCTION secondsdiff(t1 TIMESTAMP, t2 TIMESTAMP)
RETURNS INT
RETURN (
(DAYS(t1) - DAYS(t2)) * 86400 +
(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))
)
@
윤달일 경우 날 수를 결정할 때 쓸 수 있는 유용한 SQL 함수가 있다.
CREATE FUNCTION daysinyear(yr INT)
RETURNS INT
RETURN (CASE (mod(yr, 400)) WHEN 0 THEN 366 ELSE
CASE (mod(yr, 4)) WHEN 0 THEN
CASE (mod(yr, 100)) WHEN 0 THEN 365 ELSE 366 END
ELSE 365 END
END)@
마지막으로 다음은 날짜 조작에 쓰이는 빌트인 함수들이다. 여러분의 필요에 맞는 함수를 빠르게 선택하는데 사용하기 바란다. 보다 자세한 정보는 SQL 레퍼런스를 참조하기 바란다.
SQL 날짜와 시간 함수
DAYNAME 인자에 요일 이름(예, 금요일)이 포함된 혼합 문자열을 리턴.
DAYOFWEEK 1에서 7까지 정수 값으로 요일을 나타낸다. 여기에서 1은 일요일을 의미한다.
DAYOFWEEK_ISO 1에서 7까지 정수 값으로 요일을 나타낸다. 여기에서 1은 월요일이다.
DAYOFYEAR 1에서 366 까지의 정수로 날(day)을 리턴.
DAYS 날짜를 정수로 리턴.
JULIAN_DAY January 1, 4712 B.C. (Julian 달력의 시작)부터 인자에 지정된 날짜 값까지 정수로 날수를 나타냄.
MIDNIGHT_SECONDS 0에서 86400 까지의 정수 값으로 자정(midnight)과 인자에서 지정된 시간 값 사이의 초의 값을 나타냄.
MONTHNAME 달의 이름(예를 들어, January)을 포함하고 있는 혼합 문자열 리턴.
TIMESTAMP_ISO 날짜, 시간, 타임스탬프 인자에 기반한 타임스탬프 값을 리턴.
TIMESTAMP_FORMAT 문자 템플릿을 사용하여 인터프리팅 된 문자열에서 타임스탬프를 리턴.
TIMESTAMPDIFF 두 타임스탬프들 간 차이에 기반하여, 첫 번째 인자에서 정의된 유형의 인터벌 수를 리턴.
TO_CHAR 문자 템플릿을 사용하여 포맷된 타임스탬프의 문자 구현을 리턴. TO_CHAR는 VARCHAR_FORMAT의 동의어이다.
TO_DATE 문자 템플릿을 사용하여 인터프리팅 된 문자열에서 타임스탬프를 리턴. TO_DATE는 TIMESTAMP_FORMAT의 동의어이다.
WEEK 1에서 54까지 정수 값으로 주(week)를 리턴함. 주는 Sunday로 시작한다.
WEEK_ISO 1에서 53까지 정수 값으로 주를 리턴함.
위로
날짜 포맷 변경
날짜 표현에 관한 질문을 자주 받는다. 날짜에 사용되는 기본 포맷은 데이터베이스의 영역(territory) 코드로 결정된다. (이것은 데이터베이스 생성 때 지정될 수 있다.) 예를 들어, 데이터베이스가 territory=US를 사용하여 만들어졌다면 날짜 포맷은 다음과 같을 것이다.
values current date
1
----------
05/30/2003
1 record(s) selected.
말하자면 이것은 MM/DD/YYYY 포맷이다. 이 포맷을 변경하려면 db2 유틸리티 패키지 컬렉션을 다른 날짜 포맷으로 바인딩한다. 다음은 포맷 종류이다.
DEF 영역 코드와 관련된 날짜 포맷과 시간 포맷을 사용.
EUR IBM 유럽 표준의 날짜와 시간 포맷을 사용함.
ISO International Standards Organization의 날짜와 시간 포맷을 사용.
JIS Japanese Industrial Standard의 포맷 사용.
LOC 해당 데이터베이스의 영역 코드와 관련된 로컬 형식의 날짜와 시간 포맷을 사용함.
USA IBM U.S. 표준을 사용함.
ISO (YYYY-MM-DD)로 디폴트 포맷을 변경하려면 다음과 같이 한다.
명령행에서, 현재 디렉토리를 sqllib\bnd로 변경한다.
예:
On Windows: c:\program files\IBM\sqllib\bnd
On UNIX: /home/db2inst1/sqllib/bnd
SYSADM 권한을 가진 사용자로서 OS 쉘에서 데이터베이스로 연결한다
db2 connect to DBNAME
db2 bind @db2ubind.lst datetime ISO blocking all grant public
(여러분의 상황에 적용할 때에는 데이터베이스 이름과 선호하는 날짜 포맷으로 대체한다.)
이제 데이터베이스가 ISO 날짜 포맷을 사용한다.
values current date
1
----------
2003-05-30
1 record(s) selected.
위로
날짜/시간 포맷 커스터마이징
마지막 예제에서는 DB2가 로컬 포맷으로 날짜를 나타내는 방식을 어떻게 변경하는지를 설명하였다. 하지만 'yyyymmdd'처럼 커스텀 포맷으로 하고싶다면? 최선의 방법은 커스텀 포맷팅 함수를 다시 작성하는 것이다.
UDF:
create function ts_fmt(TS timestamp, fmt varchar(20))
returns varchar(50)
return
with tmp (dd,mm,yyyy,hh,mi,ss,nnnnnn) as
(
select
substr( digits (day(TS)),9),
substr( digits (month(TS)),9) ,
rtrim(char(year(TS))) ,
substr( digits (hour(TS)),9),
substr( digits (minute(TS)),9),
substr( digits (second(TS)),9),
rtrim(char(microsecond(TS)))
from sysibm.sysdummy1
)
select
case fmt
when 'yyyymmdd'
then yyyy || mm || dd
when 'mm/dd/yyyy'
then mm || '/' || dd || '/' || yyyy
when 'yyyy/dd/mm hh:mi:ss'
then yyyy || '/' || mm || '/' || dd || ' ' ||
hh || ':' || mi || ':' || ss
when 'nnnnnn'
then nnnnnn
else
'date format ' || coalesce(fmt,'
' not recognized.'
end
from tmp
이 함수 코드는 복잡해보인다. 하지만 자세히 살펴보면 매우 단순하면서도 좋은 코드임을 알 수 있다. 우선, common table expression (CTE)를 사용하여 타임스탬프(첫 번째 입력 매개변수)를 개별 컴포넌트에서 분리한다. 그런 다음, 제공된 포맷(두 번째 입력 매개변수)을 검사하고 요청된 포맷과 부분을 사용하여 타임스탬프를 다시 정렬한다. 이 함수는 매우 유연하다. 또 다른 패턴을 추가하려면 원하는 포맷과 함께 WHEN 구문을 붙이면 된다. 예상하지 못했던 패턴이 나타났다면 에러메시지가 리턴된 것이다.
사용 예제:
values ts_fmt(current timestamp,'yyyymmdd')
'20030818'
values ts_fmt(current timestamp,'asa')
'date format asa not recognized.'
VARCHAR만 잘 된다고 한다..
다른 건 테이블 깨질 가능성 50%이상??
DB2 이상하다...ㅜ.ㅡ
출처 : http://myoung76.tistory.com/60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 사용법 기초 정리 | |
This article comes from dbakorea.pe.kr (Leave this line as is) |
효과적인 SQL 작성 가이드
- 실제로 필요한 칼럼들만 가져오도록 SQL을 작성하십시오.
- select * 문은 사용하지 마십시오. 칼럼 수가 많아질수록 CPU 사용률이 높아집니다.
- WHERE 절을 적절히 사용하여 필요한 데이터를 적절히 제한하도록 합니다.
- Host 변수를 사용할 경우 테이블 칼럼 Type과 길이와 동일하게 정의하여 사용하십시오.
- SQL 문장에 Order by 절을 사용하게 되면 모든 cursor 프로세싱을 수행해야 하므로,
- Select 수행 결과로 반환되는 행의 수가 한 건일 경우에는 SELECT INTO 절을 사용하는 것이 Cursor를 사용하는 것보다 성능에 좋습니다.
만약 그렇지 않다면, DB2가 인덱스를 사용할 수 없어서 성능에 부정적인 영향을 미치게 됩니다.
예를 들어, CHAR(6)으로 정의된 칼럼을 CHAR(4)나 CHAR(7)인 필드와 비교하게 되면
데이터 변환이 일어나고 DB2가 인덱스를 사용하는 대신 데이터 스캔을 하게 되어 성능이 저하됩니다.
꼭 필요한 컬러만 Order by를 사용하십시오.
하지만, 결과 데이터를 변경해야 하는 경우에는 FOR UPDATE OF를 이용하는 Cursor로 선언하는 것이 갱신되는 Row에 Exclusivce Lock을 걸어 데이터 무결성을 보장해주므로 더 좋습니다.
조회 전용일 경우에는 Select 문에 FOR FETCH ONLY 절을 사용합니다.
- DISTINCT의 사용을 피합니다. DISTINCT를 사용하면 Sort가 발생하므로, 중복에 별 문제가 없다면 사용하지 않도록 합니다.
- JOIN 은 특별한 상황을 제외하면 5개 이내로 제한하는 것이 좋습니다.
만약 그 이상 테이블을 사용해야 하면, Subquery 대신에 Join 을 사용하십시오.
Optimizer 가 Join을 사용할 때 데이터 접근 방법을 더 많이 가지고 있기 때문입니다.
그러나 예외도 있으므로 쿼리 별로 테스트가 필요합니다.
- ORDER BY, GROUP BY, DISTINCT, UNION 을 사용할 경우 해당 칼럼에 Index 를 추가하는 것이 좋습니다.
- 대안이 있다면 SQL 조건 내에서 SUBSTR 함수의 사용을 피하는 것이 좋습니다.
예를 들어 다음과 같은 경우 substr 대신 like를 사용하십시오.
like를 사용하는 경우 index를 사용하게 됩니다.
예) select custinfo from sales where substr(serial,1,4) = ‘1333’
select custinfo from sales where serial like ‘1333%’
- SQL의 기존 함수(AVG,COUNT,MAX,MIN,SUM)를 사용하십시오.
SQL의 기존 함수를 사용하는 것이 이런 함수를 응용프로그램으로 만들어 사용하는 것보다 더 효과적입니다.
- 대안이 있다면 SQL의 Scalar 함수의 사용을 피합니다.
데이터 형태의 변경, 문자열의 조작, 그리고 날짜/시간의 변경들을 위해 사용되는 SQL Scalar 함수(INTEGER, DECIMAL, HEX, SUBST등)는 사용을 피하십시오.
- 자주 갱신되지 않는 칼럼들은 테이블의 초입에 두고, 반면에 자주 갱신되는 칼럼들은 테이블 끝에 둡니다.
이것은 DB2 LOG에 어떻게 DB2가 변화한 것을 기록하는지를 연관 지어서 효과적으로 고려한 것입니다.
- 일반적으로, VARCHAR 칼럼은 테이블 끝에 둡니다. 만약 자주 갱신되는 칼럼이 있다면 자주 갱신되는 칼럼을 VARCHAR 칼럼보다 우선적으로 테이블의 끝에 둡니다.
- <=, >= 보다는 BETWEEN을 사용합니다.
BETWEEN은 Optimizer에게 더 효과적인 접근 경로를 선택하게 해줍니다.
- 배치 프로그램 수행 시, 처리되는 input data의 순서를 Access 하는 테이블의 데이터 순서와 동일하게 맞추어 주십시오.
이렇게 하면 DB2 가 sequential prefetch를 수행하기 때문에 성능을 높일 수 있습니다.
- multicolumn index의 경우 Index의 Matching 칼럼 수가 많도록 쿼리를 작성합니다.
- Commit을 자주하면, 수행시간에 영향을 미칩니다. Commit을 적절히 조절하십시오.
- LIKE 대신 IN을 사용합니다.
만약 일어날 수 있는 특정 수만 알고 있다면, LIKE를 사용하는 것보다 IN에 목록을 나열하는 것이 더 효과적입니다.
예를 들어, 만약 Last Name이 M으로 시작하는 모든 근로자를 찾는다면,
LIKE ‘m%’ 대신에 BETWEEN ‘maaaaaaaaaaaaaa’ and ‘mzzzzzzzzzzzzzz’를 사용하십시오.
- NOT의 사용(EXISTS는 제외)을 피합니다. NOT은 단지 매우 복잡한 조건에서만 선택적으로 사용해야 합니다.
- 만약 응용프로그램 내의 칼럼 값을 이미 알고 있다면, SELECT 절에 칼럼의 사용을 피합니다.
예) select c1,c2,c3 into :c1, :c2,:c3 from t1 where c1 = :c1
- SELECT 문의 결과 중복된 행이 없다고 알고 있거나, 중복된 데이터가 있어도 된다면,
- 부정의 논리로 Subquery를 작성할 때, SQL문의 효율성을 높이기 위하여,
- JOIN은 Subquery 보다 더 효율적입니다.
UNION 대신 UNION ALL을 사용합니다.
가능하면 NOT IN 대신 NOT EXISTS를 사용합니다.
NOT EXISTS를 사용할 때 DB2는 단지 존재하지 않는 것만 확인하지만,
NOT IN조건을 포함하면, DB2는 완벽한 결과 집합을 구성해서 조건을 비교하게 됩니다.
예) select eno,ename from emp , proj where workdept = deptno and empno = respemp (O)
select eno, ename from emp
where workdept = ( select deptno from proj where respemp = emp.empno) (X)
원본 위치 <http://www.iteg.co.kr/a/b/content.asp?tb=i2&page=4&num=16>
출처 : http://www.ibm.com/developerworks/kr/library/0211yip/0211yip3.html
*********************************************************************************************************
머리말
DB2 UDB에 익숙하지 않은 사람들에게 날짜와 시간을 조작하는 방법을 설명한다. 다른 데이터베이스를 다뤄본 많은 사람들에게 DB2 UDB가 얼마나 쉬운지를 설명하겠다.
SQL을 사용하여 날짜, 시간, 타임스탬프를 파악하려면 해당 DB2 레지스터리를 참조하라.
SELECT current date FROM sysibm.sysdummy1 SELECT current time FROM sysibm.sysdummy1 SELECT current timestamp FROM sysibm.sysdummy1 |
sysibm.sysdummy1 테이블은 위에서 설명한 대로 DB2 레지스터의 값을 찾는데 사용할 수 있는 특별한 인메모리(in-memory) 테이블이다. VALUES 키워드를 사용하여 레지스터나 식을 계산할 수 있다. 예를 들어, DB2 Command Line Processor (CLP)에서 다음 SQL 문장에는 비슷한 정보들이 나타난다.
VALUES current date VALUES current time VALUES current timestamp |
남아있는 예제에는 SELECT ... FROM sysibm.sysdummy1
을 반복하거나 VALUES 구문을 사용하지 않고 함수 또는 식을 제공하도록 하겠다.
GMT/CUT에 맞춘 현재 시간이나 현재 타임스탬프를 얻으려면 현재 시간 또는 타임스탬프에서 현재 타임존 레지스터를 제거한다.
current time - current timezone current timestamp - current timezone |
날짜 시간, 타임스탬프의 경우, 적절한 함수를 사용하여 년도, 달, 요일, 시간, 분, 초, 마이크로초를 추출할 수 있다.
YEAR (current timestamp) MONTH (current timestamp) DAY (current timestamp) HOUR (current timestamp) MINUTE (current timestamp) SECOND (current timestamp) MICROSECOND (current timestamp) |
타임스탬프와 관계없이 날짜와 시간을 추출하는 것 역시 매우 쉽다.
DATE (current timestamp) TIME (current timestamp) |
영어로도 날짜와 시간 계산을 할 수 있다. :
current date + 1 YEAR current date + 3 YEARS + 2 MONTHS + 15 DAYS current time + 5 HOURS - 3 MINUTES + 10 SECONDS |
두 날짜 간에 날수가 얼마나 되는지를 계산하려면 날짜를 빼면 된다.
days (current date) - days (date('1999-10-22')) |
다음은 마이크로초 부분을 0으로 재설정하고 현재 타임스탬프를 얻는 방법이다.
CURRENT TIMESTAMP - MICROSECOND (current timestamp) MICROSECONDS |
날짜 또는 시간 값을 다른 텍스트와 연결시키려면 그 값을 문자열로 변환해야 한다. CHAR() 함수를 사용한다.
char(current date) char(current time) char(current date + 12 hours) |
문자열을 날짜 또는 시간 값으로 변환하려면 다음과 같이 한다.
TIMESTAMP ('2002-10-20-12.00.00.000000') TIMESTAMP ('2002-10-20 12:00:00') DATE ('2002-10-20') DATE ('10/20/2002') TIME ('12:00:00') TIME ('12.00.00') |
TIMESTAMP(), DATE(), TIME() 함수는 여러 포맷들을 허용한다. 위 포맷은 단순한 예제일 뿐이다. 독자 여러분이 스스로 해 보길 바란다.
경고: DATE 함수에서 쿼트를 없애면 어떻게 될까? 함수는 여전히 작동하겠지만 정확하지 않은 DATE가 나올 것이다.
결과:
위 결과에서 어떻게 2000년 이나 차이가 났을까? DATE 함수가 입력으로 문자열을 취하면 DB2 날짜의 유효 문자로 간주되고, 따라서 이를 변환하는 것이다. 반대로, 입력이 숫자라면 이 함수는 현재 년도(0001-01-01)에서 1을 제한 날 수를 나타내는 것으로 간주한다. 위 쿼리에서 입력은 2001-09-22였고 이것은 (2001-9)-22과 동일하다. 또한 이것은 1970이다. |
가끔씩, 두 개의 타임스탬프들이 어떻게 차이가 있는지 알아야 한다. 이를 위해 DB2는 TIMESTAMPDIFF()라고 하는 빌트인 함수를 제공한다. 하지만 리턴된 값은 근사값이다. 윤년을 고려하지 않고 한 달을 30일로만 가정하기 때문이다. 다음은 두 날짜들 간 차이를 찾아내는 방법이다.
timestampdiff (<n>, char( timestamp('2002-11-30-00.00.00')- timestamp('2002-11-08-00.00.00'))) |
<n>의 자리에, 다음 값들을 사용하여 시간 단위를 나타낸다.
- 1 = 초의 소수부분
- 2 = 초
- 4 = 분
- 8 = 시간
- 16 = 요일
- 32 = 주
- 64 = 달
- 128 = 분기
- 256 = 년
timestampdiff()를 사용하면 날짜가 비교적 가까이 있을 때 더 정확한 결과가 나온다. 보다 정확한 계산을 원하면 다음을 사용하여 시간 단위로(초 단위로) 차이를 결정한다.
(DAYS(t1) - DAYS(t2)) * 86400 + (MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2)) |
SQL의 사용자 정의 함수를 사용할 수도 있다.
CREATE FUNCTION secondsdiff(t1 TIMESTAMP, t2 TIMESTAMP) RETURNS INT RETURN ( (DAYS(t1) - DAYS(t2)) * 86400 + (MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2)) ) @ |
윤달일 경우 날 수를 결정할 때 쓸 수 있는 유용한 SQL 함수가 있다.
CREATE FUNCTION daysinyear(yr INT) RETURNS INT RETURN (CASE (mod(yr, 400)) WHEN 0 THEN 366 ELSE CASE (mod(yr, 4)) WHEN 0 THEN CASE (mod(yr, 100)) WHEN 0 THEN 365 ELSE 366 END ELSE 365 END END)@ |
마지막으로 다음은 날짜 조작에 쓰이는 빌트인 함수들이다. 여러분의 필요에 맞는 함수를 빠르게 선택하는데 사용하기 바란다. 보다 자세한 정보는 SQL 레퍼런스를 참조하기 바란다.
SQL 날짜와 시간 함수 | ||
DAYNAME | 인자에 요일 이름(예, 금요일)이 포함된 혼합 문자열을 리턴. | |
DAYOFWEEK | 1에서 7까지 정수 값으로 요일을 나타낸다. 여기에서 1은 일요일을 의미한다. | |
DAYOFWEEK_ISO | 1에서 7까지 정수 값으로 요일을 나타낸다. 여기에서 1은 월요일이다. | |
DAYOFYEAR | 1에서 366 까지의 정수로 날(day)을 리턴. | |
DAYS | 날짜를 정수로 리턴. | |
JULIAN_DAY | January 1, 4712 B.C. (Julian 달력의 시작)부터 인자에 지정된 날짜 값까지 정수로 날수를 나타냄. | |
MIDNIGHT_SECONDS | 0에서 86400 까지의 정수 값으로 자정(midnight)과 인자에서 지정된 시간 값 사이의 초의 값을 나타냄. | |
MONTHNAME | 달의 이름(예를 들어, January)을 포함하고 있는 혼합 문자열 리턴. | |
TIMESTAMP_ISO | 날짜, 시간, 타임스탬프 인자에 기반한 타임스탬프 값을 리턴. | |
TIMESTAMP_FORMAT | 문자 템플릿을 사용하여 인터프리팅 된 문자열에서 타임스탬프를 리턴. | |
TIMESTAMPDIFF | 두 타임스탬프들 간 차이에 기반하여, 첫 번째 인자에서 정의된 유형의 인터벌 수를 리턴. | |
TO_CHAR | 문자 템플릿을 사용하여 포맷된 타임스탬프의 문자 구현을 리턴. TO_CHAR는 VARCHAR_FORMAT의 동의어이다. | |
TO_DATE | 문자 템플릿을 사용하여 인터프리팅 된 문자열에서 타임스탬프를 리턴. TO_DATE는 TIMESTAMP_FORMAT의 동의어이다. | |
WEEK | 1에서 54까지 정수 값으로 주(week)를 리턴함. 주는 Sunday로 시작한다. | |
WEEK_ISO | 1에서 53까지 정수 값으로 주를 리턴함. |
날짜 표현에 관한 질문을 자주 받는다. 날짜에 사용되는 기본 포맷은 데이터베이스의 영역(territory) 코드로 결정된다. (이것은 데이터베이스 생성 때 지정될 수 있다.) 예를 들어, 데이터베이스가 territory=US
를 사용하여 만들어졌다면 날짜 포맷은 다음과 같을 것이다.
values current date 1 ---------- 05/30/2003 1 record(s) selected. |
말하자면 이것은 MM/DD/YYYY 포맷이다. 이 포맷을 변경하려면 db2 유틸리티 패키지 컬렉션을 다른 날짜 포맷으로 바인딩한다. 다음은 포맷 종류이다.
DEF | 영역 코드와 관련된 날짜 포맷과 시간 포맷을 사용. |
EUR | IBM 유럽 표준의 날짜와 시간 포맷을 사용함. |
ISO | International Standards Organization의 날짜와 시간 포맷을 사용. |
JIS | Japanese Industrial Standard의 포맷 사용. |
LOC | 해당 데이터베이스의 영역 코드와 관련된 로컬 형식의 날짜와 시간 포맷을 사용함. |
USA | IBM U.S. 표준을 사용함. |
ISO (YYYY-MM-DD)로 디폴트 포맷을 변경하려면 다음과 같이 한다.
- 명령행에서, 현재 디렉토리를
sqllib\bnd
로 변경한다.예:
On Windows:c:\program files\IBM\sqllib\bnd
On UNIX:/home/db2inst1/sqllib/bnd
- SYSADM 권한을 가진 사용자로서 OS 쉘에서 데이터베이스로 연결한다
db2 connect to DBNAME db2 bind @db2ubind.lst datetime ISO blocking all grant public
(여러분의 상황에 적용할 때에는 데이터베이스 이름과 선호하는 날짜 포맷으로 대체한다.)
이제 데이터베이스가 ISO 날짜 포맷을 사용한다.
values current date 1 ---------- 2003-05-30 1 record(s) selected. |
마지막 예제에서는 DB2가 로컬 포맷으로 날짜를 나타내는 방식을 어떻게 변경하는지를 설명하였다. 하지만 'yyyymmdd'처럼 커스텀 포맷으로 하고싶다면? 최선의 방법은 커스텀 포맷팅 함수를 다시 작성하는 것이다.
UDF:
create function ts_fmt(TS timestamp, fmt varchar(20)) returns varchar(50) return with tmp (dd,mm,yyyy,hh,mi,ss,nnnnnn) as ( select substr( digits (day(TS)),9), substr( digits (month(TS)),9) , rtrim(char(year(TS))) , substr( digits (hour(TS)),9), substr( digits (minute(TS)),9), substr( digits (second(TS)),9), rtrim(char(microsecond(TS))) from sysibm.sysdummy1 ) select case fmt when 'yyyymmdd' then yyyy || mm || dd when 'mm/dd/yyyy' then mm || '/' || dd || '/' || yyyy when 'yyyy/dd/mm hh:mi:ss' then yyyy || '/' || mm || '/' || dd || ' ' || hh || ':' || mi || ':' || ss when 'nnnnnn' then nnnnnn else 'date format ' || coalesce(fmt,' <null> ') || ' not recognized.' end from tmp </null> |
이 함수 코드는 복잡해보인다. 하지만 자세히 살펴보면 매우 단순하면서도 좋은 코드임을 알 수 있다. 우선, common table expression (CTE)를 사용하여 타임스탬프(첫 번째 입력 매개변수)를 개별 컴포넌트에서 분리한다. 그런 다음, 제공된 포맷(두 번째 입력 매개변수)을 검사하고 요청된 포맷과 부분을 사용하여 타임스탬프를 다시 정렬한다. 이 함수는 매우 유연하다. 또 다른 패턴을 추가하려면 원하는 포맷과 함께 WHEN 구문을 붙이면 된다. 예상하지 못했던 패턴이 나타났다면 에러메시지가 리턴된 것이다.
사용 예제:
values ts_fmt(current timestamp,'yyyymmdd') '20030818' values ts_fmt(current timestamp,'asa') 'date format asa not recognized.' |
날짜와 시간에 관련된 질문들에 답이 되었기 바란다. 더 많은 예제들로 글을 업데이트 하겠다. (사실 독자들 덕분에 벌써 세 번씩이나 업데이트 했다.)
Bill Wilkins, DB2 Partner Enablement
Randy Talsma
이 글에는 샘플 코드가 포함되어 있습니다. IBM은 여러분 모두가 "로열티 " 없이 이 샘플 코드를 사용할 수 있도록 허용하고 있습니다. 하지만 이 샘플 코드는 그대로 제공되며 특정 목적에 맞춰 상용으로 사용해서는 안됩니다. IBM은 이 소프트웨어를 사용함으로써 초래된 어떤 손해에도 책임을 지지 않습니다. IBM은 손실, 영리 또는 데이터, 직접적인 손해, 간접적인 손해, 특별한 손해, 결과적인 손해, 일시적인 손해, 징벌로 인한 손해 등에 책임이 없습니다. IBM이 그와 같은 손실의 가능성을 만들었더라도 소프트웨어의 사용 또는 미사용에서 발생한 손실에는 책임이 없습니다.
Paul Yip, 데이터베이스 컨설턴트, IBM 토론토 연구실. |
****************************************************************************************************
사용자를 위한 DB2 Conversion 프로젝트, Part 4: DB2 애플리케이션
김명훈, DB2 프리랜서 DBA
현재 DB2 프리랜서로 일하고 있으며 근래 주요 DB2 프로젝트는 POSCO 열연 생산관리 시스템 구축, K-Power DSS 시스템 설계 구축, 삼성 DB2 Monitoring 컨설팅 등을 담당하였다.
이번 회에는 DB2 애플리케이션 개발 중에 오라클 DB와 상이한 구문과 SQL 차이점에 대해서 설명하도록 하겠다. 곧 출시될 DB2 Viper 2에서는 오라클 DB에서만 사용하는 outer join의 + 구문이나 connect by의 Recursive SQL, row number, 오라클 DB 전용 함수들이 DB2의 레지스터리 값 변경 이후에 오라클 DB와 동일하게 사용할 수 있어져서 오라클 DB 사용자들의 DB2 사용이 용이해 졌다.
Data Type
오라클 DB와 DB2의 데이터 타입의 차이점은 DB2에서의 데이터 타입은 사용자 편의보다는 옵티마이저가 가장 잘 해석할 수 있도록 세분화 되어 있다는 점이다. 이는 DB2는 기본적으로 오라클 DB와 달리 Rule base 옵티마이저 모드를 지원하지 않기에 옵티마이저가 최대한 잘 해석할 수 있도록 만들어 주기 위함으로 보인다.
예를 들어 오라클 DB에서의 number와 같이 정수, 소수를 대표하는 Data Type은 DB2에서는 크기에 따라 SMALLINT, INTEGER, BIGINT, DECIMAL(p,s)등으로 세분화 되어 쓰여지게 되어 있다.
DB2는 오라클 DB에서와 같이 숫자와 문자간 자동 형 변환을 지원하지 않는다 따라서 문자와 숫자간 비교나 조인시 반드시 CAST, INT, CHAR 함수 등으로 형 변환을 해주어야 한다.
예>
select * from tab1 where col1 = int(‘1’)
select * from tab1 where col1 = cast (‘1’ as int)
DB2에서의 날짜 연산
1. to_char() 함수: DB2에도 오라클 DB의 to_char()와 동일한 이름의 함수는 있으나 오라클 DB에서와 같이 날짜 형식의 다양한 포멧팅을 지원하지는 않는다. 오라클 DB의 TO_CAHR() 함수를 쓰기 위해서는 별도의 UDF가 필요하다.(오라클/MS-SQL Built in Function에 대한 DB2 UDF는 첨부되어 있는 zip 파일을 참조해서 사용하기 바란다.)
2. sysdate(oracle) => current date(현재 날짜), current timestamp (현재 시간소인)
3. hex(current date) 문자열 YYYYMMDD 형식 예> 20080101
4. date / year / month / day 함수 입력된 시간소인(혹은 날짜형식 문자열)에 날짜(date yyyy-mm-dd), 년도(year –yyyy), 월(month – mm 2월인 경우 02가 아니고 2로 표시됨), 일(day – dd)로 변환하는 scalar 함수
5. 날짜 더하기/ 빼기 “+/- n days”, “+/- months”, “+/- years” 예>current date + 1 months
6. 날짜끼리 뺄 경우 결과는 YYYYMMDD(decimal(8,0))형식으로 두 일자 사이의 기간을 나타내게 된다. 예) values(date('2008-02-10') -date('2007-01-01')); 00010109 (1년 1개월 9일)
7. 날짜 포멧 변경
char(current date, iso) – 2008-01-01
char(current date, eur) – 01.01.2008
char(current date, usa) – 01/01/2008
Page navigation을 위한 Row Number
OLAP 함수인 row_number() over(order by 컬럼이름)로 대체해서 사용해야 한다.
Select empno, fullname
From (select empno
, firstnme || ' ' || lastname as fullname
, row_number() over (order by empno) as r_num
from employee ) as t1
Where r_num >= 10 and r_num <20
Dummy Table
Sysibm.sysdummy1 (DB2)
select * from sysibm.sysdummy1
Truncate Table
DB2에서는 오라클 DB에서의 Truncate table은 존재하지 않는다. DB2에서 테이블의 데이터를 효율적으로 지우는 방법은 아래와 같다.
Import from /dev/null of del replace into 테이블이름
Alter table 테이블이름 activate not logged initially with empty table
ALTER TABLE EMPLOYEE ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE;
Decode문
Decode문은 지원하지 않는다. Case문으로 대체해야 한다.
UPDATE staff
SET comm = salary + DECODE(job,'Mgr',100,0)
UPDATE staff
SET comm = salary + CASE job
WHEN 'Mgr' THEN 100 ELSE 0 END
NULL 처리
Sequence
데이터베이스 전체에서 관리되는 Sequence와 별도로 테이블마다 제공되는 컬럼 sequence도 존재한다. 각 사용법은 아래와 같다
Procedure
1. 프로시저 생성시 CREATE OR REPLACE 옵션을 제공하지 않는다. 따라서 이미 존재하고 있는 프로시저일 경우 Drop 후 재생성 해야 한다. 이때 프로시저를 참조하는 Routine이 있으면 같이 Drop하고 생성해 주어야 한다.
2. 데이터 타입 정의시 반드시 길이를 정해 주어야 한다. 길이가 정해져 있지 않은 데이터 타입은 사용이 불가능 하다. 또한 참조되는 객체의 길이가 서로 다를 경우 생성되지 않으므로 참조되는 객체의 길이와 타입은 반드시 동일하게 생성해 주어야 한다.
3. 입/출력 값에 설정시 IN, OUT, INOUT을 변수 명 앞에 선언하고 변수와 변수 타입(크기가 명시된)을 선언한다.
4. LANGUAGE SQL 옵션은 ver7.x에서는 반드시 써야 하지만 ver8.x부터는 선택 사항이다.
5. Procedure 호출은 Call 명령어를 통해 호출한다.
Call stored_procedure_name (input1, input2….)
Temporary Table
Temporary table을 사용하기 위해서는 반드시 사용자 임시 테이블 스페이스 타입의 테이블 스페이스가 존재해야 하며, 세션에 독립적으로 생성되어 세션이 종료됨과 함께 자동으로 소멸된다.
-- User Temp 테이블 스페이스 작성
CREATE USER TEMPORARY TABLESPACE apptemps
MANAGED BY SYSTEM USING ('apptemps');
-- Temp Table 작성
DECLARE GLOBAL TEMPORARY TABLE t_employees LIKE employee NOT LOGGED;
Trigger
1. 트리거 생성시 CREATE OR REPLACE 옵션을 제공하지 않는다. 따라서 이미 존재하는 트리거일 경우 drop후 재 생성해야 한다.
2. Before 트리거에서 NO CASCADE 옵션은 필수 항목이다.
3. MODE DB2SQL 옵션은 필수 항목이다.
4. UPDATE & DELETE 구문은 Before&After를 사용해야 한다.
5. 오라클 DB의 INSERT OR UPDATE OR DELETE ON과 같은 다중 역할을 하는 트리거 생성이 불가능하다. 따라서 각 역할에 따라 트리거를 별도로 생성해 주어야 한다.
6. INNER SQL(Select .. INTO)을 통한 변수 설정이 불가능 하기 때문에 반드시 SET을 통해 SELECT 결과를 변수에 입력하여야 한다. 이때 SELECT 문장의 값은 반드시 단일 Row여야 한다.
변수 정의와 규칙
Oracle PL/SQL 같은 경우 아래의 4가지 위치에 변수 값 정의가 가능하다.
1. 스토어드 프로시저 또는 함수 파라미터 리스트 안
2. 스토어드 프로시저, 함수, 트리거의 내부
3. 패키지 정의
4. 패키지 body 정의
DB2에서는 오라클 DB에서와 같이 함수나 프로시저를 그룹화하는 패키지 개념이 없다. 따라서 변수 값 정의는 패키지를 제외한 위의 두 가지 경우만 허용된다.
DB2 SQL PL에서도 native data type과 user defined distinct type의 여러 형태 정의가 가능하다. 변수 정의시 반드시 DECLARE 구문을 써서 정의하여야 하며, 변수 값 정의를 위해서는 반드시 BEGIN … END 블록 안에서 정의되어야 한다. 초기값 설정 이후 변수에 값을 설정할 경우 DB2에서는 SET 문장을 써서 변수를 assign 한다.
예> 초기값 설정
Oracle PL/SQL: l_value NUMBER(10,2) :=0.0;
DB2 SQL PL: DECLARE l_value NUMERIC(10,2) DEFAULT 0.0;
예> 변수 값 할당
Oracle PL/SQL: l_value = 99.99;
DB2 SQL PL: SET l_value = 99.99;
Trigger의 경우 INNER SQL(Select .. INTO)을 통한 변수 설정이 불가능 하기 때문에 반드시 SET을 통해 SELECT 결과를 변수에 입력하여야 한다. 이때 SELECT 문장의 값은 반드시 단일 Row여야 한다.
SET l_value =(SELECT balance from account_info where account_no = actNo);
Cursor 처리
1. 응용프로그램에서 결과 집합을 검색하기 위해 사용하는 기법으로 Select 문에서 여러 건의 데이터를 반환하는 경우에 사용된다.
2. 커서는 declare / open / fetch / close의 단계로 사용된다.
3. Open된 커서는 UOW(unit of work) 종료시(commit / rollback) 소멸되지만 DB2에서는 With HOLD 옵션으로 커서의 위치를 유지할 수 있다.
4. DB2는 Memory level의 Lock을 사용하며 그에 따른 Cursor의 유형도 읽기 전용(READ ONLY)과 업데이트 가능한 UPDATEABLE 커서가 있다.
5. UPDATEABLE(FOR UPDATE OF)를 사용하면 데이터를 Fetch 하는 동안 S모드 대신 U모드 LOCK이 적용되어 Deadlock을 방지할 수 있다.
커서 예외 처리
Debugging
DB2에는 오라클 DB의 dbms.output.put_line과 같은 함수가 존재 하지 않는다. 따라서 dbms.output.put_line 함수와 같은 UDF Fuction을 만들거나, 디버깅 테이블을 만들어 디버깅 하고자 하는 값을 새로 만든 디버깅 테이블에 Insert 하는 방법이 있다.
아래의 방법은 put_line UDF를 생성하여 디버깅 하는 방법에 대한 설명이다. 해당 원문은 아래의 Site에서 확인 하기 바란다.
http://www.ibm.com/developerworks/db2/library/techarticle/0302izuha/0302izuha.html
put_line UDF생성 방법
CREATE PROCEDURE TESTCASE() RESULT SETS 0 LANGUAGE SQL
L_TESTCASE:
BEGIN NOT ATOMIC
DECLARE V_DEPTNO SMALLINT;
DECLARE V_DEPTNAME VARCHAR(20);
DECLARE V_DIVISION VARCHAR(20);
-- FOR DEBUG
DECLARE V_NUM SMALLINT DEFAULT 0;
DECLARE V_MSG1 VARCHAR(4000);
DECLARE V_MSG2 VARCHAR(1);
-- END
-- SAMPLE1
SET V_NUM=2000;
SET V_MSG1='debugging start';
VALUES(PUT_LINE(V_NUM,V_MSG1)) INTO V_MSG2;
-- SAMPLE2
VALUES(PUT_LINE(SMALLINT(2),'this is no2'))
INTO V_MSG2;
-- SAMPLE3
VALUES(PUT_LINE(3)) INTO V_MSG2;
-- SAMPLE4
VALUES(PUT_LINE('##number4##')) INTO V_MSG2;
-- SAMPLE5
SET V_NUM = 0;
FOR V_C1_REC AS C1 CURSOR FOR
SELECT DEPTNUMB, DEPTNAME, DIVISION
FROM ORG ORDER BY DEPTNUMB DESC
DO
SET V_DEPTNO = v_C1_REC.DEPTNUMB;
SET V_DEPTNAME = v_C1_REC.DEPTNAME;
SET V_DIVISION = v_C1_REC.DIVISION;
SET V_NUM = V_NUM + 1;
SET V_MSG1 ='DEPTNO=' || CHAR(V_DEPTNO)||',' ||'DEPTNAME='||V_DEPTNAME||','
||'DIVISION='||V_DIVISION;
VALUES(PUT_LINE(V_NUM,V_MSG1)) INTO V_MSG2;
END FOR;
VALUES(PUT_LINE(32000,'end of the program'))
INTO V_MSG2;
END L_TESTCASE
<참조>
Oracle to DB2 UDB Conversion Guide(IBM.com/redbooks)
DB2 사용자 가이드(IBM)