次のクエリを実行しています。しかし、ORA-12899を取得しています。挿入しようとしている文字列の長さは30ですが。
INSERT INTO TABLE1 SELECT * FROM temp_Table1 where LENGTH(column1)=30;
SQL Error: ORA-12899:value too large for column "TABLE1"."column1" (actual: 31, maximum: 30)
select column1 from temp_Table1 where LENGTH(column1)=30;
Testing - HLC/TC Design Corre
Desc temp_Table1
column1 VARCHAR2(30)
Desc Table1
column1 VARCHAR2(30)
文字とバイト長のセマンティクス の違いがわかります。
VARCHAR2列の最大長を指定する必要があります。格納される実際の文字列は長さゼロの文字列( '')でもかまいませんが、この最大値は少なくとも1バイトでなければなりません。 VARCHAR2(10 CHAR)などのCHAR修飾子を使用して、バイトの代わりに文字で最大長を指定できます。文字は、技術的にはデータベースの文字セットのコードポイントです。 VARCHAR2(10 BYTE)などのBYTE修飾子を使用して、最大長を明示的にバイト単位で指定できます。この列または属性を持つデータベースオブジェクトが作成されるときに、列または属性の定義に明示的な修飾子が含まれていない場合、長さのセマンティクスは、オブジェクトを作成するセッションのNLS_LENGTH_SEMANTICSパラメータの値によって決まります。
セッションがバイトセマンティクスを使用している場合、テーブルの列はデフォルトで次のようになります。
_select value from nls_session_parameters where parameter = 'NLS_LENGTH_SEMANTICS';
VALUE
----------------------------------------
BYTE
create table t42(text varchar2(5));
Table T42 created.
select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';
C
-
B
_
これは明示的に行うことと同じです。
_create table t42(text varchar2(5 byte));
_
ソースデータが5文字でマルチバイト文字が含まれている場合、bytesの数は5を超えます。
_insert into t42 (text) values ('Hello');
1 row inserted.
insert into t42 (text) values ('Señor');
SQL Error: ORA-12899: value too large for column "SCHEMA"."T42"."TEXT" (actual: 6, maximum: 5)
_
あなたが見ているのはそれです。他のテーブルから値を挿入すると、値の長さでフィルタリングされますが、length()
はバイトではなく文字をカウントします。バイトをカウントするlengthb()
関数があります。選択している30文字の値のバイト長を確認すると、実際には31バイトであるため、これらの文字の1つはマルチバイトです。
_with t42 (text) as (
select 'Hello' from dual
union all select 'Señor' from dual
union all select 'Testing - HLC/TC Design Corre' from dual
)
select text, length(text) as chars, lengthb(text) as bytes, dump(text, 16) as hex
from t42;
TEXT CHARS BYTES HEX
------------------------------- ----- ----- ----------------------------------------------------------------------------------------------------------
Hello 5 5 Typ=1 Len=5: 48,65,6c,6c,6f
Señor 5 6 Typ=1 Len=6: 53,65,c3,b1,6f,72
Testing - HLC/TC Design Corre 30 31 Typ=1 Len=31: 54,65,73,74,69,6e,67,c2,a0,20,2d,20,48,4c,43,2f,54,43,20,44,65,73,69,67,6e,20,43,6f,72,72,65
_
dump()
の値から、Testing
(_54,65,73,74,69,6e,67
_)の後、スペースとダッシュ(_20,2d
_)の前に_c2,a0
_があることがわかります。 is TF-8マルチバイトの非改行スペース文字 。 (Word文書などからコピーされたテキストに、中かっこやその他の非ASCII範囲の文字と共に表示されることがよくあります)。
挿入をLENGTHB(column1)=30
でフィルターするように変更するか(現在検出されている行を除外します)、または列定義を30バイトではなく30文字に変更します。
_drop table t42;
Table T42 dropped.
create table t42(text varchar2(5 char));
Table T42 created.
select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';
C
-
C
insert into t42 (text) values ('Hello');
1 row inserted.
insert into t42 (text) values ('Señor');
1 row inserted.
_
または、可能であり、データに意味がある場合は、予期しないマルチバイト文字を同等のシングルバイト文字に置き換えます。この場合、通常のスペースmightは機能しますが、置換を行うと、実際に重要な情報が破壊されます。
次のようにテーブルを変更してみてください
ALTER TABLE1 MODIFY column1 VARCHAR2(30 CHAR)
このエラーは、column1が最大30文字を格納できることを示しており、30文字を超えて渡すとエラーが発生します。
この記事を参照することもできます: Oracleデータベース-VARCHAR2とCHARのバイトまたは文字
ORA-12899
多くの場合、クライアントベース、スタッフ、利益、または市場の形での拡大に対応して当社が成長し、進化するにつれて、この成長に関連するデータも変化します。 Oracleのようなデータシステムには、このような情報の変化に対応するという点で、かなり柔軟であり続ける能力があります。それでも、最も用途の広いデータベースシステムでさえ、データトラフィックの増加に直面して、保守と調整が必要です。この作業は、メモリの制約や必要なパラメータの再定義に対応するために不可欠です。 ORA-12899エラーは、データの上昇またはユーザーエラーのいずれかにより、要求されたアクション中にOracleが停止するように強制されているインスタンスを表しています。
問題
ORA-12899は、列文字列に入力された値が大きすぎる場合に発生するOracleエラーです。これは、宛先列に対して幅が広すぎる値を持つ列をユーザーが更新または挿入しようとしたことを意味します。特定の列の名前が与えられ、値の実際の幅と、列に許可されている最大幅がそれに関連付けられます。前述のように、値は文字の形式で指定できます。幅が文字数で報告される場合、これは文字長セマンティクスが列に対して機能していることを意味します。それ以外の場合、幅はバイト単位で報告されます。基本的に、このエラーは、列の指定された最大幅を超える値または値のセットをプッシュしようとしたことが原因です。では、ユーザーはこのタイプのエラーをどのように修正するのでしょうか?
ソリューション
まず、OERRユーティリティを開きます。ユーザーは、エラーに関する適切なフィードバックを受け取るために、完全なORA-12899メッセージを必要とします。これにより、エラーに関する詳細情報が提供され、詳細な調査が可能になります。通常、エラーは3つの原因のいずれかから発生します。最初のソースは、生成されたSQLステートメントです。 2番目のソースは、ソース列と宛先列のデータ型をチェックして、現在の形式と互換性があるかどうかを確認することです。最後に、ユーザーは目的の列の幅(値が割り当てられている場所)を調べて、ユーザーが割り当てを予期している最大値に対応するのに十分な大きさであることを確認できます。次に、ORA-12899を修正する例を見てみましょう。ユーザーが次のテーブルを作成したとします。
CREATE TABLE Clients( ClientID varchar2(9) PRIMARY KEY, Client_Contact varchar2(40) NOT NULL, Address varchar(20) NOT NULL, Zip varchar2(5) NOT NULL, Client_Number varchar2(11) NOT NULL)
次に、ユーザーは次のようなINSERT VALUESステートメントを発行しようとします。
INSERT INTO Clients VALUES( 727546345, ‘Roger Holcomb’, ‘—Benjamin Road Syracuse’, ‘-----‘, 05307623754)
ユーザーがここからステートメントを実行しようとすると、次のエラーメッセージが表示されます。
コマンドの7行目から始まるエラー:INSERT INTO Clients VALUES(727546345、 'Ricky Galorey'、'18 Benjamin Road Syracuse '、' 13208 '、05307623754)エラー報告:SQLエラー:ORA-12899:列「ORGANIZATIONS」の値が大きすぎます」。 "市場"。 「ADDRESS」(実際:25、最大:20)12899. 00000 –「列%sには大きすぎる値(実際:%s、最大:%s)」
このエラーステートメントは、変数 ‘Address’が列パラメーターの幅を超えるため、20文字を超えることはできないことを示しています。住所の値(「18 Benjamin Road Syracuse」)を振り返ると、文字の総数(25)が列の幅に許可されている最大数を超えていることがわかります。これを修正するために、ユーザーは住所のVARCHAR2を、会社が入力する一般的な住所の長さに対応できる量に変更できます。
ターゲットテーブルデータベースのNLS設定が異なるため、ターゲットでより多くのバイトが必要になる場合があります。 alter Table1 modify column1 varchar2(30 char)としてテーブルを変更してみてください