2016-08-09 2 views
0

に先行ゼロを追加します。 old_table - 月、日、世紀、年の4つのフィールドがあります(やはりchar)。これらの日付をnew_tableに1つのフィールドとして追加しています - invdat(char)。クライアントはの前に、の先頭にゼロを追加したいと考えています。現在はold_tableに保存されていません。ここでは、私はフィールドのセット(すべての文字)私は別のテーブル(<strong>OLD_TABLE</strong>)から表(<strong>NEW_TABLE</strong>)に書いていますがあり、SQL INSERT文

はサンプルです:

INSERT INTO new_table 
SELECT month || oedy01 || oecc01 || oeyr01 || as invdat 
FROM old_table 

だから、私はNEW_TABLEにinvdatフィールドにそれらを入れる前に、これらのフィールドに先行ゼロを追加する必要があります。

アドバイスありがとうございます。

+0

最初の質問は、日付部分が1つの日付ではなく別々の文字列として保存される理由です。 2番目の質問は、日付ではなく文字列を作成する理由です。もちろん、日付データ型を使用する場合は、日付を扱う方がはるかに簡単です。 –

+0

とにかく、左にゼロを文字列に埋め込む方法は次のとおりです。http://stackoverflow.com/questions/4964244/pad-varchar-numbers-with-0s-in-db2 –

+4

これです。日付は 'プレゼンテーションレイヤー'に表示されている間に 'データレイヤー'に保存されます。データレイヤーとそれらが保持しているフォーマットは、表示とパディングには関係ありません。 ThorstenのEcho、日付フィールドに切り替える...あなたは現在、クライアントが後で対処するための完全な混乱を設定しています。 – Twelfth

答えて

2

古いソフトウェアを使用するシステムでは、文字列として日付を格納する理由はたくさんあります。おそらく、ソフトウェアが日付データ型がRPGで簡単に利用可能になる前に書かれていたからです。上記のコメントは、20年間このように行われていると述べています。おそらく周囲にはたくさんのコードがあり、 "新しい"慣習を満たすためにそれを変更することは費用がかかりません。 DB2/400とRPG IVは今日の日付をうまく扱いますが、他の作業があるときに何十年もうまく動作している大きなシステムを再コーディングして再テストしたい人はいますか?それは、ここでは単一の日付フィールドにゼロパッドに、あなたのフィールドをAS/400-幸せDB2のSQLを使用して、簡単な方法で、言った:私はAS/400の開発者とその日付フォーマットを検証することをお勧め

INSERT INTO new_table 
SELECT Right('00'||month,2) || Right('00'||oedy01,2) || Right('00'||oecc01,2) || Right('00'||oeyr01,2) as invdat 
FROM old_table 

。通常、ccyymmdd形式で保存された日付が表示されますが、それについての厳しい規則はありません。

+0

それは、彼らが私に尋ねた日付について私に言ったことです。彼らは、彼らがまだRPGIIIでプログラミングしていたコードベースで(80年代前半)始めた時に戻ってきました。しかし、このソリューションは完全に機能します。ありがとうございました。 – Echoic

2

通常、OPはDDLを与えませんでした。 の場合、大部分のクエリアクティビティがこれらのコンポーネントに依存し、それらが索引付けされている場合、日付の別々のコンポーネントを格納することに大きな利点があります。派生したINDEXの追加機能では、YEAR(date_field)やSUBSTR(mmddyyyy_string_field、5,4)などの式をキーとして、これらの選択を実行する実行時の派生の問題を改善できます。指定された形式の記述されたINVDATへの変換は、ほとんどの選択項目が特定の日付 - 構成要素に対してではない場合でも、 goodの選択IMOのものではありません。私はそれについて後でコメントする。

一般的に正しい結果が得られるはずですが、データのドメインが見た目の日付 - 少なくとも1桁の数値[文字列または数字]の期待値のため、結果はデータタイピング;つまり、 "先行ゼロ...現在の値は古い値で保存されていません"というデータ型は、文字列と数値の区別があり、 "(やはりchar)"によると、CHARとVARCHARの両方が期待できます。また、文字列データとして、ゼロ以外の埋め込み値\ prependedの値が左に調整されているのか、右に調整されているのかについては言及されていません。暗黙 DDL \実際、未知のために適切ではないかもしれないので、それらの応答が「与えとしてこのDDLを」有効で前置きしなければならないと他の\未来の答えと解説

。 (

たとえば、コメントに既に言及されている左パッド(LPAD)スカラー[IBM DB2 for i 7.1以降で利用可能]。LPADはおそらく実際に残された実際のデータに必要とされるように、1つ以上のゼロの文字列の前に組み合わされたときに、より長く存在し、かなり能力の高いRIGHTスカラーの使用より意図された効果に対するより顕著に適切なスカラー要求。がOP内にありますが、の値を取り除いた場合にのみ有効ですが、LPADではVARCHARではなくCHAR [すなわち、LPADは常識を破る。テストでは、最も有望な\ rational intentionsを実装することができず、代わりにSUBSTR関数がすでにその効果のために存在していたにもかかわらず、固定長CHARデータに対する効果的な部分文字列として機能します。

もちろん、OPがDDLに対して持っていることについての同じ推論では、式RIGHT('00' CONCAT char_2_field, 2)でも望ましい結果が得られません。例えばフィールド内の左調整値'1 'を用いて、その式は、結果が'01'ではなく、'1 'ではなくRIGHT(CHAR('001 ', 4), 2)であり、フィールド内で右に調整された値' 1'が有効であることを効果的に求めているその結果が'01'ではなく' 1'であるRIGHT(CHAR('00 1', 4), 2)を求める。私は実際には少し驚いてその答えはが受け入れられました。つまり、元のDDLはVARCHARとして宣言されたフィールドを持っていて、格納されたり適切にキャストされたときにそれらの値が適切に削除されたように見えます。

これらのフィールドがVARCHARであった場合、またはSTRIP [またはLTRIMまたは同様のもの]がそのデータ型を変更するために使用された場合[一見任意に、左揃えの結果がドキュメントの影響に従って私の経験では、左のトリムまたは完全なストリッピングが推奨されると示唆している場合、の回答のコメントの両方で提供されている式の文字列を期待通りに生成できます。

コメントに記載されているDATEスカラーを省略して、date-componentsの順序を並べ替えることができました。しかし、DATEデータ型の結果ではなく文字列として、に表示されているMMDDYYYYの形式の文字列は、となります。 [lexicographical qualityがありません]ので、ソートや[ない]等しい述語; YYYYMMDDという形式の文字列[そのコメントが提供しようとしているものとほとんど同じ] です。したがって、並べ替えや相対的な一致には適しています。 DATE算術と検証のための固有のサポートを持たないことは、それほど負のものではありません。

注:DDLとデータの入力に関する次のスクリプトアクションでは、単純な世紀の数値の2桁の値を参照しています。すなわち、 "cc"は0世紀を無視するので、 '19'は1900年代から1800年代を意味し、 'cc'は '00' - > '19'、 '01' - > ' 20 '、等。

与えられ、別のクエリをテストできるようにするためのセットアップ:だから、与えられた設定で、上記のクエリはありません

SELECT Right('00'||month, 2) || Right('00'||oedy01, 2)   
    || Right('00'||oecc01, 2) || Right('00'||oeyr01, 2) as invdat 
from old_table 
where month not in (2, 4) 
; -- report of above query follows; no leading zeroes anywhere: 
    INVDAT 
    1 11940 
    3 3 1940 
    1 120 0 
    3 3 200 
    1 120 1 
    3 3 201 
    1 12039 
    3 3 2039 
    1 1 0 1 
    3 3 0 1 
-- end of data -- 
select               
    lpad(month , 2, '0') concat lpad(oedy01, 2, '0') concat 
    lpad(oecc01 , 2, '0') concat lpad(oeyr01, 2, '0') as invdat 
from old_table             
where month not in (2, 4) 
; -- report of above query follows; no leading zeroes anywhere: 
    INVDAT 
    1 11940 
    3 3 1940 
    1 120 0 
    3 3 200 
    1 120 1 
    3 3 201 
    1 12039 
    3 3 2039 
    1 1 0 1 
    3 3 0 1 
-- end of data; a duplicate of the prior query report -- 

:セットアップを超えていたものを照会するための今

create table old_table 
(month char(2) not null with default 
, oedy01 char(2) not null with default 
, oecc01 char(2) not null with default 
, oeyr01 char(2) not null with default 
) 
; 
create table new_table 
(invdat char(8) not null with default 
) 
; 
insert into old_table /* mm, dd, cc, yy */ values   
    (' 1', ' 1', '19', '40'), ('3 ', '3 ', '19', '40') 
, (' 1', ' 1', '20', ' 0'), ('3 ', '3 ', '20', '0 ') 
, (' 2', ' 2', '20', ' '), ('4 ', '4 ', '20', ' ') 
, (' 1', ' 1', '20', ' 1'), ('3 ', '3 ', '20', '1 ') 
, (' 1', ' 1', '20', '39'), ('3 ', '3 ', '20', '39') 
, (' 1', ' 1', ' 0', ' 1'), ('3 ', '3 ', '0 ', '1 ') 
, (' 2', ' 2', ' ', ' 1'), ('4 ', '4 ', ' ', '1 ') 
; -- mm(1,2):right-adj, mm(3,4):left-adj, mm(2,4):blank-elems 
    -- 14 rows inserted in OLD_TABLE 

を非常に役立ちます。 CHARデータは最初に余計な空白を剥奪されていることを確認するために、各クエリにマイナーリビジョンでは、結果が非​​常に優れている:

select      
    lpad(strip( month) , 2, '0') concat 
    lpad(strip( oedy01) , 2, '0') concat 
    lpad(strip( oecc01) , 2, '0') concat 
    lpad(strip( oeyr01) , 2, '0') as invdat 
from old_table        
/* where month not in (2, 4) -- this *fixes* blank values too */ 
; -- report of above query follows; expected leading zeroes appear: 
    INVDAT 
    01011940 
    03031940 
    01012000 
    03032000 
    02022000 
    04042000 
    01012001 
    03032001 
    01012039 
    03032039 
    01010001 
    03030001 
    02020001 
    04040001 
-- end of data -- 
SELECT            
    Right('00' concat strip(month) , 2) concat 
    Right('00' concat strip(oedy01) , 2) concat 
    Right('00' concat strip(oecc01) , 2) concat 
    Right('00' concat strip(oeyr01) , 2) as invdat 
from old_table          
/* where month not in (2, 4) -- this *fixes* blank values too */ 
; -- report of above query matches the prior; not repeated here 

DDLではなく、数値であり、値のために格納されている有効な小数点データを持つことが知られている場合は、

drop table old_table 
; 
create table old_table     
(month dec (2) not null with default 
, oedy01 dec (2) not null with default 
, oecc01 dec (2) not null with default 
, oeyr01 dec (2) not null with default 
)          
; 
insert into old_table /* mm, dd, cc, yy */ values   
    (' 1', ' 1', '19', '40'), ('3 ', '3 ', '19', '40') 
, (' 1', ' 1', '20', ' 0'), ('3 ', '3 ', '20', '0 ') 
, (' 1', ' 1', '20', ' 1'), ('3 ', '3 ', '20', '1 ') 
, (' 1', ' 1', '20', '39'), ('3 ', '3 ', '20', '39') 
, (' 1', ' 1', ' 0', ' 1'), ('3 ', '3 ', '0 ', '1 ') 
; -- notably, no blank values per inability to cast to decimal 
select 
    digits(month) concat digits(oedy01) concat 
    digits(oecc01) concat digits(oeyr01) as invdat 
from old_table          
; -- report from above query follows; DIGITS casting gives leading zeros: 
INVDAT 
01011940 
03031940 
01012000 
03032000 
01012001 
03032001 
01012039 
03032039 
01010001 
03030001 
-- end of data -- 

[上記の例に含まれていた変種。 の回答がで、のコメントのRIGHT()式とLPAD()のあるものは、上記と同じレポートを出力します。これは、CHARからDECIMALへの暗黙的キャストの結果が数値の左調整された可変文字ストリング表現であるため、暗黙的に左トリムおよび可変長であり、スカラー関数が望ましい出力を生成するためです。

[いいえ "すべてのchar"データ型の代わりに]数値データ型の使用のスクリプトがの回答が受け入れられるものとしてOPによって選択された理由である場合、 DDLを含めることによって、問題のシナリオが説明され、それがいかに簡単に防止されたかを示しています。サンプルデータを追加した方がよいでしょう。

関連する問題

 関連する問題