sql >> データベース >  >> RDS >> Oracle

CHARセマンティクスとORA-01461

    VARCHAR2の代わりにCLOBを使用する場合を除いて、これはおそらく回避できるものではありません。

    Oracleでは、列を宣言すると、デフォルトでバイト長のセマンティクスが使用されます。したがって、たとえばVARCHAR2(100)は、100バイトのストレージを割り当てます。 ISO 8859-1のような1バイトの文字セットを使用している場合、すべての文字に1バイトのストレージが必要になるため、これによって100文字のスペースも割り当てられます。ただし、UFT-8のようなマルチバイト文字セットを使用している場合、各文字には1〜4バイトのストレージが必要になる可能性があります。したがって、データによっては、VARCHAR2(100)は25文字のデータしか格納できない場合があります(英語の文字は通常1バイト、ヨーロッパの文字は通常2バイト、アジアの文字は通常3バイトを必要とします)。

    Oracleに文字長セマンティクスを使用するように指示できます。これは通常、ISO-8859-1データベースからUTF-8データベースに移行するときに提案するものです。列VARCHAR2(100 CHAR)を宣言すると、最終的に100バイトか400バイトかに関係なく、Oracleは100文字にスペースを割り当てます。 NLS_LENGTH_SEMANTICSパラメータをCHARに設定して、デフォルト(新しいDDLの場合)を変更し、VARCHAR2(100)が100バイトではなく100文字のストレージを割り当てるようにすることもできます。

    ただし、残念ながら、Oracle VARCHAR2のサイズの制限(PL / SQLエンジンではなくSQLエンジンのコンテキストで)は4000バイトです。したがって、列VARCHAR2(4000 CHAR)を宣言した場合でも、実際には1000文字程度の4000バイトのデータを挿入するように制限されます。たとえば、AL32UTF8文字セットを使用するデータベースでは、列VARCHAR2(4000 CHAR)を宣言できますが、2バイトのストレージを必要とする文字を挿入すると、4000文字のデータを実際に挿入できないことがわかります

    SQL> create table foo (
      2    col1 varchar2(4000 char)
      3  );
    
    Table created.
    
    SQL> insert into foo values( rpad( 'abcde', 4000, unistr('\00f6') ) );
    
    1 row created.
    
    SQL> ed
    Wrote file afiedt.buf
    
      1* insert into foo values( rpad( 'abcde', 6000, unistr('\00f6') ) )
    SQL> /
    
    1 row created.
    
    SQL> select length(col1), lengthb(col1)
      2    from foo;
    
    LENGTH(COL1) LENGTHB(COL1)
    ------------ -------------
            2003          4000
            2003          4000
    

    4000文字のUTF-8データを格納する必要がある場合は、16000バイトを処理できるデータ型が必要であり、CLOBへの移動が必要になります。




    1. INSERT..RETURNINGがJOOQで機能していません

    2. 時間を考慮せずに日時列でグループ化するにはどうすればよいですか?

    3. MYSQL:別のテーブルの値に基づいてフィールド値を計算するトリガーを作成するにはどうすればよいですか?

    4. SQLサーバーでID列の値が突然1001にジャンプします