처음 작업시 발생된 에러
SELECT DATA, DUMP(DATA) DUMP
FROM T;
SQL> SELECT DATA, DUMP(DATA) DUMP
2 FROM T;
SP2-0784: 0xE0(으)로 시작하는 부적합하거나 불완전한 문자가 반환됨
SP2-0784: 0xE1(으)로 시작하는 부적합하거나 불완전한 문자가 반환됨
SP2-0784: 0xE2(으)로 시작하는 부적합하거나 불완전한 문자가 반환됨
KO16MSWIN949작업시 생김
<에러 해결>
(캐릭터 셋 SERVER AL32UTF8, Client : AL32UTF8
해도 에러는 일어나지않지만 한글이 깨지는 현상 발생 조회시...
터미널 에서 set nls_lang=.AL32UTF8 으로 해결)
SQL> set linesize 50
SQL> SELECT *
2 FROM NLS_DATABASE_PARAMETERS
3 WHERE PARAMETER ='NLS_CHARACTERSET';
PARAMETER VALUE
------------ --------
NLS_CHARACTERSET AL32UTF8
host echo $NLS_LANG
$NLS_LANG
windown 환경에서는 레지스터리환경으로 변경가능
SQL> CREATE TABLE T ( DATA VARCHAR2(1));
Table created.
SQL> INSERT INTO T VALUES(CHR(224));
1 row created.
SQL> INSERT INTO T VALUES(CHR(225));
1 row created.
SQL> INSERT INTO T VALUES(CHR(226));
1 row created.
D DUMP
- ------------------
Typ=1 Len=1: 224
Typ=1 Len=1: 225
Typ=1 Len=1: 226
SQL> commit;
Commit complete.
export NLS_LANG=AMERICAN_AMERICA.US7ASCII
SQL> variable d varchar2(1)
SQL> variable r varchar2(20)
SQL>
SQL> begin
2 select data, rowid into :d, :r
3 from t
4 where rownum =1;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL> update t
2 set data = :d
3 where rowid = chartorowid(:r);
1 row updated.
SQL>
SQL> commit;
Commit complete.
SQL>
SQL> select data,dump(data) dump
2 from t;
D DUMP
- ------
Typ=1 Len=1: 224
Typ=1 Len=1: 225
Typ=1 Len=1: 226
캐릭터셋 변경관련 정리사이트
http://blog.naver.com/966138/60019247059
<VARCHAR2(80)에 저장된 hello World> |
<CHAR(80)에 저장된 Hello Wolrd> |
SQL> drop table t;
Table dropped.
SQL>
SQL> create table t
2 (
3 char_column char(20),
4 varchar2_column varchar2(20)
5 );
Table created.
SQL>
SQL> insert into t values('Hello World','Hello World');
1 row created.
SQL> select *
2 from t;
CHAR_COLUMN VARCHAR2_COLUMN
-------------------- --------------------
Hello World Hello World
SQL> select *
2 from t
3 where char_column ='Hello World';
CHAR_COLUMN VARCHAR2_COLUMN
-------------------- --------------------
Hello World Hello World
SQL>
SQL> select *
2 from t
3 where varchar2_column ='Hello World';
CHAR_COLUMN VARCHAR2_COLUMN
-------------------- --------------------
Hello World Hello World
SQL> select *
2 from t
3 where char_column = varchar2_column;
no rows selected
-- 같은 데이터지만 조회되지않는다.
-- CHAR는 빈공간 으로 채우기 때문에 다르다고 판단한다.
SQL> select *
2 from t
3 where trim(char_column) = varchar2_column;
CHAR_COLUMN VARCHAR2_COLUMN
-------------------- --------------------
Hello World Hello World
SQL> select *
2 from t
3 where char_column = rpad(varchar2_column,20);
CHAR_COLUMN VARCHAR2_COLUMN
-------------------- --------------------
Hello World Hello World
-- 바인드변수사용시
SQL> variable varchar2_bv varchar2(20)
SQL> exec :varchar2_bv := 'Hello World';
PL/SQL procedure successfully completed.
SQL>
SQL> select *
2 from t
3 where char_column = :varchar2_bv;
no rows selected
SQL> select *
2 from t
3 where varchar2_column = :varchar2_bv;
CHAR_COLUMN VARCHAR2_COLUMN
-------------------- --------------------
Hello World Hello World
-- varchar2 바인드 변수는 char로 확장되지 않음으로 나오지 않는다.
-- 정상적인 사용을 하기 위해서는 char 타입 바인드 변수를 사용한다.
SQL> variable char_bv char(20)
SQL> exec :char_bv := 'Hello World';
PL/SQL procedure successfully completed.
SQL>
SQL> select *
2 from t
3 where char_column = :char_bv;
CHAR_COLUMN VARCHAR2_COLUMN
-------------------- --------------------
Hello World Hello World
SQL>
SQL> select *
2 from t
3 where varchar2_column = :char_bv;
no rows selected
결론은 char는 쓰지말자!!(불필요한 함수를 사용하여 혼란을 야기 및 속도적인문제)
varchar2를 사용하자!!
문자열타입 | 연산 |
---|---|
VARCHAR (<SIZE> <BYTElCHAR>) | 최대 4000바이트 저장. 1에서 4000까지 숫자로 지정 |
CHAR (<SIZE> <BYTElCHAR>) | 최대 2000바이트 저장. 1에서 2000까지 숫자로 지정 |
NVARCHAR (<SIZE>) | 내셔널 캐릭터 셋이 지원하는 0보다 큰 최대 범위의 숫자를 지정 가능 |
NCHAR (<SIZE>) | 내셔널 캐릭터 셋이 지원하는 0보다 큰 최대 범위의 숫자를 지정 가능 |
-- 바이트 또는 문자 테스트
SQL> SELECT *
2 FROM NLS_DATABASE_PARAMETERS
3 WHERE PARAMETER ='NLS_CHARACTERSET';
PARAMETER VALUE
------------ --------
NLS_CHARACTERSET AL32UTF8
SQL> drop table t;
Table dropped.
SQL>
SQL> create table t
2 (
3 a varchar2(1),
4 b varchar2(1 char),
5 c varchar2(4000 char)
6 );
Table created.
SQL> desc t;
Name Null? Type
----------------------------------------- -------- ----------------------------
A VARCHAR2(1)
B VARCHAR2(1 CHAR)
C VARCHAR2(4000 CHAR)
SQL> insert into t(a) values(unistr('\00d6'));
insert into t(a) values(unistr('\00d6'))
*
ERROR at line 1:
ORA-12899: value too large for column "BSHMAN"."T"."A" (actual: 2, maximum: 1)
-- vharchar2(1)은 한 문자를 의미하는게 아니라 1바이트를 의미한다.
-- 유니코드 한 문자는 1바이트로 지정된 컬럼에 입력X
-- 싱글바이트 캐릭터 셋에서 문자 20자는 20바이트를 차지 = varchar2(20)이면 가능
-- 멀티바이트 캐릭터 셋에서는 20문자 필드는 80바이트를 사용(문자당 4바이트 일 경우)
-- 이런경우 alter table t modify (a char(1 char)) 의 DLL이나
-- 테이블 생성전 NLS_LENGTH_SEMANTICS (DEFAULT : BYTE) -> CHAR로 변경
-- alter session set NLS_LENGTH_SEMANTICS ='CHAR';
SQL> insert into t(b) values(unistr('\00d6'));
1 row created.
SQL> select length(b), lengthb(b), dump(b) dump
2 from t;
LENGTH(B) LENGTHB(B) DUMP
---------- ---------- -----------------
1 2 Typ=1 Len=2: 195,150
-- 영문,한글 입력 테스트
SQL> insert into t(a) values('a');
1 row created.
SQL> insert into t(a) values('가');
insert into t(a) values('가')
*
ERROR at line 1:
ORA-12899: value too large for column "BSHMAN"."T"."A" (actual: 2, maximum: 1)
SQL>
SQL> insert into t(b) values('a');
1 row created.
SQL> insert into t(b) values('가');
insert into t(b) values('가')
*
ERROR at line 1:
ORA-12899: value too large for column "BSHMAN"."T"."B" (actual: 2, maximum: 1)
SQL> declare
2 l_data varchar2(4000 char);
3 l_ch varchar2(1 char) := unistr('\00d6');
4 begin
5 l_data := rpad(l_ch,4000,l_ch);
6 insert into t (c) values(l_data);
7 end;
8 /
declare
*
ERROR at line 1:
ORA-01461: can bind a LONG value only for insert into a LONG column
ORA-06512: at line 6
-- 4000문자 -> 실제 8000바이트 입력으로 에러
SQL> declare
2 l_data varchar2(4000 char);
3 l_ch varchar2(1 char) := unistr('\00d6');
4 begin
5 l_data := rpad(l_ch,2000,l_ch);
6 insert into t (c) values(l_data);
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> select length(c), lengthb(c)
2 from t
3 where c is not null;
LENGTH(C) LENGTHB(C)
---------- ----------
2000 4000
-- 2000문자 -> 실제 4000바이트 입력으로 성공
- 강좌 URL : http://www.gurubee.net/lecture/4050
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.