Oracleでの文字列連結サイズの上限

このQ&Aのポイント
  • Oracle9iでテーブル内容をスプール出力していますが、カラム単位で余白を削除したい(トリムをかけたい)ので以下のようにカラムを連結させてスプールしています。
  • 実際の項目数は100以上あり、レコードの最大長も数千バイトになりますが、各項目にMAXの値を入力して上記スプールを実行したところ、以下のエラーメッセージが出力されました。「ORA-01489: 文字列を連結した結果、長さが最大長を超えました」
  • データを連結した結果の長さが上限を超えたということなのでしょうが、この最大長はどこで設定されているものなのでしょうか?また、そもそもスプール出力でトリムが効かないためにこのようなやり方で出力していますが、他によい方法をご存知の方いましたら教えて下さい。
回答を見る
  • ベストアンサー

Oracleでの文字列連結サイズの上限

Oracle9iでテーブル内容をスプール出力していますが、カラム単位で余白を削除したい (トリムをかけたい)ので以下のようにカラムを連結させてスプールしています。 set colsep ',' spool test.csv select a ||','|| b ||','|| c from test_table spool off 実際の項目数は100以上あり、レコードの最大長も数千バイトになりますが、 各項目にMAXの値を入力して上記スプールを実行したところ、以下のエラーメッセージが 出力されました。 「ORA-01489: 文字列を連結した結果、長さが最大長を超えました」 データを連結した結果の長さが上限を超えたということなのでしょうが、 この最大長はどこで設定されているものなのでしょうか? また、そもそもスプール出力でトリムが効かないためにこのようなやり方で 出力していますが、他によい方法をご存知の方いましたら教えて下さい。 よろしくお願いします。

  • Oracle
  • 回答数4
  • ありがとう数6

質問者が選んだベストアンサー

  • ベストアンサー
  • GoF
  • ベストアンサー率37% (34/91)
回答No.4

>>Code Tipsの内容も実際に試してみたのですが、結局のところ項目を連結させる >>やり方では4000バイトまでが限度ということだと判断したのですが 4000バイトまでが限度 とは、どのような理由からでしょうか? 以下のSQLで4000バイトオーバーは可能です。(32KBの壁はあります) 既に完成度の高いスクリプトがデバッグ済みで存在するのに 同じものを 1からコーディングするのは、(自分の勉強にはなるとは思いますが) 意味のない行為だと思いますので、 Code Tipsをお勧めしました。 SPOOL HOGE.TXT SET PAGESIZE 0 SET LINESIZE 32767 SET LONG 40000 SET LONGC 40000 SET TRIMSPOOL ON SET FEEDBACK OFF SET VERIFY OFF SELECT TO_CLOB('') || LPAD('1', 4000,'1') || LPAD('2', 4000,'2') || LPAD('3', 4000,'3') || LPAD('4', 4000,'4') || LPAD('5', 4000,'5') || LPAD('6', 4000,'6') || LPAD('7', 4000,'7') || LPAD('8', 4000,'8') || LPAD('9', 4000,'9') || LPAD('0', 4000,'0') FROM DUAL / SPOOL OFF

kirayama
質問者

お礼

回答ありがとうございます。やはり認識間違っていたようですね。 OcacleのSQLリファレンスで連結演算子の説明に「どちらかの文字列がVARCHAR2型の場合、 連結結果はVARCHAR2型となり、最大文字数は4000」とあります。 また、「どちらかがCLOB型の場合、結果は一時CLOB型になります」とも書いています。 GoFさんの例示されているSQLを見ると、CLOB型のデータと連結してやれば、4000バイト以上の 連結も可能ということなのでしょうか。 (最大長はCLOB型の4GBなのかと思いましたが32KBなのですね) 確かに文字列連結は4000バイト以上可能なのですが、実際にエラーの出ていたスプール処理を 以下のように変更して試してみたのですが、実行結果が何分待っても帰ってこない状態になって しまいました。(4GBを項目数分連結するので処理に時間がかるのでしょうか?) spool test.csv select to_clob('') || a ||','|| b ||','|| c ||','|| //以下100項目以上連結 from test_table Code Tipsの#764は実際に試したのですが、単純に文字列連結を行っているようで、 質問と同様のエラーが出てしまいます。 #675は内容がやや複雑で実行内容がよく理解できなかったのと、TO_CLOB等も使用していないよう なので#764と変わらないのかと思い実行は控えていました。 暗黙的な変換等、基本的な部分を理解できていないこともあり、せっかくの回答も生かせていないようです。 もう少し勉強して試してみたいと思います。いろいろとありがとうございました。

その他の回答 (3)

  • GoF
  • ベストアンサー率37% (34/91)
回答No.3

SELECT TO_CLOB('') || LPAD('A', 4001, 'C') FROM DUAL ; 通常 暗黙変換 により VARCHAR2に変換されます。 VARCHAR2の最大長は 4000バイト すぐ下に同じような質問内容があるので、そちらのスクリプトを使用した方がよいと思います。

参考URL:
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1460873
kirayama
質問者

お礼

回答ありがとうございます。返事が遅れてしまいもうし訳ありません。 連結する文字列のどちらかがVARCHAR2の場合、連結した結果はVARCHAR2の文字列となり、 最大4000バイトとなるということですね。 SQL文の内容はCLOB型のデータと連結すれば連結結果はCLOB型となり、 最大長は4GBとなるのでエラーとはならないことを言われているのでしょうか。 Code Tipsの内容も実際に試してみたのですが、結局のところ項目を連結させる やり方では4000バイトまでが限度ということだと判断したのですが、上のCLOB型の 組み合わせ次第では4000バイト超のデータも出力可能なのでしょうか? 質問ばかりで申し訳ないのですが、認識間違ってましたら、 反応して頂けないでしょうか。 よろしくお願いします。

  • entree
  • ベストアンサー率55% (405/735)
回答No.2

簡単なテストケースを使って自力で確認できませんか? 質問を見ていてもいかなる努力をしても解決できない様子が全く見て取れません。

kirayama
質問者

補足

単にスプール出力の方法を質問している訳ではありません。レコード長が短いデータであれば問題はなかったのですが、今回文字列連結云々のエラーが出てしまい、マニュアルを調べても「最大長」が何を意味しているかが分からず質問しています。

  • ppg-2
  • ベストアンサー率39% (77/193)
回答No.1

以下の環境変数で、直接csvに出力できます。 set heading off set feedback off set trimspool on set termout off set pages 0 set line 9999

kirayama
質問者

補足

回答ありがとうございます。 すみません、ご指摘のシステム変数は全て設定しており、その上で文字列連結のエラーが出るということなのですが。 情報開示が不十分であったことをお詫びします。

関連するQ&A

  • SQLPLUSにて演算子を使う方法と条件文を使いたい・・

    以下のようにspoolコマンドにてselectの結果をCSVに出力したいのですが、カンマ区切りしたいため連結していますがエラーが発生します。 spool aaa.csv select AAA || ',' || BBB || ',' ||   CCC - DDD || ',' || EEE from table_A ・・・ そうすると、引き算が引っかかっているらしく、 「ORA-01722:数値が無効です」エラーが発生します。 連結をやめて、「|| ',' ||」→「,」にすれば正常に終了します。 連結の場合に演算子を使うにはどのようにすればよいのでしょうか? また、例えば「AAA<0」の場合には、BBBに100を掛けるとかのような 他カラムでの条件により、別カラムの計算結果を変えるといったことは 可能なのでしょうか? よろしくお願い致します。

  • OracleでCLOB型をファイル出力したい

    Oracle10gで、CLOB型を含むテーブルを全件ファイル出力しているのですが、CLOB型の項目は正常に出力されず、項目の内容が80byte位で切れてしまいます。 項目の内容が切れずにファイルに出力できる方法が知りたいです。 宜しくお願い致します。 ファイル出力の内容は以下の通りです。 ########################################################## set pages 0 set heading off set colsep '<ec>' set lines 3000 set feed off set trimspool on set define off set num 20 spool テーブル名.dat select /* FULL(テーブル名) */ 項目A,項目B,・・・・ from テーブル名; spool off ########################################################## ※項目は、全部で15項目あり、レコード長は135です。

  • SQL 同テーブル、同フィールドの文字列連結

    以下の様にSQLで実現したいと思っております。 なお、DBはOracle10Gを利用しております。 親と子テーブルがあり以下の構成となっております。 ■親テーブル  ID,カラムA  1 ,AA  2 ,BB  3 ,CC ■子テーブル  ID,枝番,カラムB  1 ,1 ,あああ  1 ,2 ,いいい  2 ,1 ,ううう  2 ,2 ,えええ  2 ,3 ,おおお  3 ,2 ,かかか ※IDカラムは親テーブルと子テーブルは1:1です  子テーブルの枝番カラムはIDに対してN件です。 やりたい事としては、上記の2テーブルより、以下の結果を出力したいです。  ID,カラムA,カラムB  1 ,AA ,あああ いいい  2 ,BB ,ううう えええ おおお  3 ,CC ,かかか 親テーブルを元にして、 親テーブルに紐づく子テーブルのカラムBを連結して出力 するSQLをご教授いただけますでしょうか

  • テーブルレイアウトの差異

    SQL*Plusでテーブルの構造を表示するDESCを使って、結果をSPOOLする際に csvファイルにしたいと思い SET HEADING OFF SET COLSEP "," SPOOL C:\WINDOWS\デスクトップ\スプール結果.txt DESC テーブル名 SPOOL OFF と実行してもカンマ区切りにならないのですが、DESCのときは出来ないのですか? Oracle for Windows 95のSQL*Plus Ver3.3.3.0.0を使用しています。 また、テーブルの構造の差異を見つける作業を行ないたいのですが、 効率の良い方法もしくはフリーソフトをご存知の方情報お願いします。 この質問がメインかな?

  • 文字列連結を行いたい

    以下のようなテーブル「TABLE_A」があります。 何とかSQLで抽出結果のようにしたいのですが、 方法が思いつきません。 【TABLE_A】  CODE | HIDUKE  -----|------------  1 | 2005/06/01  1 | 2005/06/02  1 | 2005/06/03  2 | 2005/06/01  2 | 2005/06/03 【抽出結果】  CODE | rst  ---------------------------------------------  1  | 2005/06/01 2005/06/02 2005/06/03  2 | 2005/06/01 2005/06/03  (列「CODE」単位に列「HIDUKE」を文字列連結を行う) どなたかご教授ください。 よろしくお願いいたします。

  • オラクルでいうところのdescとspoolのサイベース版。

    サイベース初心者です(オラクルも初級者ですが・・・)。 オラクルではdescで表の情報をみたり、処理結果をspool~spool off で出力したりしますが、これと同じ機能をサイベースでやりたいのですが、どうなりますか? また、オラクルでテーブル全てを表示したいとき、 select table_name from user_tables (だったかな?(--;)) というのがあるとおもいますが、これをサイベースでやるときは どう記述したらよいでしょうか。 以上、ひとつでもご存知の方、ご回答よろしくお願いします。

  • Oracleのupdate文について

    OracleでテーブルB、Cを結合し取得できた項目で、テーブルAを更新したいのですがSQLがわかりません。結合結果とテーブルAは1:1にはなりません。 件数が結合結果>テーブルAの時もあれば、その逆の場合もあります。また、複数項目を更新したいです。実行して考えてみたいのですが、明朝客先ですぐに実行しなければならず(テスト環境はあるので明日そこで一旦確認後、すぐに本番環境で実行)、現在移動中→ホテル泊のため余裕がありません。 ネットで下記を見つけたのですが、更新する項目に更新日時を追加したいのと、テーブルAとの紐付けやEXISTSのWHEREはテーブルBとC両方の項目に紐づけたいです。 また、テーブルAの更新条件に、テーブルB、Cにはないcolumn③に対する条件も追加したいです。 UPDATE [TABLE①] A SET (COLUMN①, COLUMN②) = ( SELECT B.COLUMN, C.COLUMN FROM [TABLE②] B, [TABLE③] C WHERE B.COLUMN = C.COLUMN AND B.COLUMN = A.COLUMN ) WHERE EXISTS ( SELECT 1 FROM [TABLE②] B2 WHERE B2.COLUMN = A.COLUMN) もろもろとわかりづらい説明&他力本願で心苦しいのですが、どなたか教えていただけないでしょうか?

  • 項目内の改行がレコードの終わりと判定されてしまう

    SQL*PLUSでORACLEデータを単純にテキストファイルに書き出したいのですが、項目内に「改行」があるとレコードが複数行に分かれていまい、上手くいきません。 項目内の「改行」のみ(レコード終端の本来の「改行」は残す)を削除して前詰めする(または空白に置き換える)方法をご存じの方ご教示いただけないでしょうか。 例) SET COLSEP ',' SPOOL D:\出力ファイル.txt SELECT      項目1 || 項目2 || 項目3 FROM テストテーブル ; SPOOL OFF;

  • 項目以外の文字列は連結できますか?

    やりたいことは、日付と時間の項目から 現在時刻を過ぎているかのフラグを返す事ですが、 MySQLで普通の文字列を連結する方法がわかりません。 どのようにすれば実現できるでしょうか? SELECT IF(CONCAT(end_day,end_time) < NOW(), 1,0) end, from test testテーブル |end_day |end_time |2006-03-15 | 10:00 |2006-03-20 | 10:00

    • ベストアンサー
    • MySQL
  • oracle 複数列を1列にまとめる

    oracle 複数列のデータ中身を別のテーブルの1列にインサートしたい ご存知の方、オラクルプロの方、 若輩者の私にアドバイス等ご指導受けたまりたく存じます。 以下のようなテーブルがあったとします。 テーブルA MID | K1 | K2 |K3 ------------------------- 011 |ああ |いい |うう  012 |ええ |おお |かか 特定の列を選択しての、Updateには成功しました。 update テーブルA set K1 = (select K1|| ' ' ||K2|| ' '||K3 from テーブルA where MID = '011') where MID = '011'; これを別のテーブルに全行Insertしたいのです。約5千行はあり、環境の制限によりSQL文のみしか使えません。 テーブルB MID |K1 ----------------------- 011 |ああ いい うう 012 |ええ おお かか 以下のようなSQLで正しいでしょうか? insert into テーブルA (K1) select K1|| ' ' ||K2|| ' '||K3 from テーブルB; 上記の方法で実施しましたが、下記のようなエラーメッセージが表示されます。MID項目が主キーのため、NULL不可なことはわかりますが、指定していないMIDが何故でてくるのでしょう? SQL Error: ORA-01400: テーブルA (MID) にはNULLは挿入できません。 環境情報: Oracle 10g  検証環境:Oracle SQL Developerあり 本番環境:Oracle SQL Developerなし、SQLのみ使用可