質問
· 2024年11月22日

SQLのInsertにおける、JDBCとIRIS直の挙動差異について。

こんにちは、皆さま。
業務でIRISを用いて開発を行っている者です。

IRISに直接Insert文を発行する時と、JDBCを経由してInsert文を発行する時とで、
挙動差異があるように見受けれれまいたので、何かご存知な方がいらっしゃれば教えてください。

次の様なテーブルがあります。

それに対してDBeaverとIRIS管理ポータルからInsertを実行します。

★DBeaver

 

★IRIS管理ポータル

 

この後実際に作成されたグローバルの情報を確認すると、
『VARCHAR型』で作成したカラムに数値をInsertした際に、
実データの型が異なっていることがわかります。

DBeaver(JDBC) ➡ 文字列で登録
IRIS直     ➡ 数値で登録

個人的には『VARCHAR型』に数値が入ること自体がおかしいので、
DBeaverの方がまし(ホントは型違反とかになってほしい)と思うのですが、
この差異が何で発生するのか、また回避する方法をご存じな方がいらっしゃれば情報共有頂きたいです。

 

また、そもそもIRISはRDBを使っても型チェックが曖昧になるものなのかも気になっています。
さすがに数値のカラムに文字列を入れようとすると怒られるのですが、
上記の様な場合にチェックの仕組みが働かないのには違和感がありました。

ディスカッション (3)1
続けるにはログインするか新規登録を行ってください

@Yuji Ohata さん、面白い話題をありがとうございます!

ご質問への直接な回答としては
「DBeaver が文字列、ObjectScript経由が数値として入る差異は製品仕様で、回避する方法がない」
になります。。

背景やその他おもしろ情報を以下お伝えしますね。

ObjectScriptも、実は内部では、データを「文字列」か「数値型」かを明確に区別しています。たとえば、以下の2つはデータとしては厳密には異なります。

    set a="12345"  ;; a: STRING
    set x=12345    ;; x: INTEGER

if a=x write "OK" とすると、ちゃんと "OK" と表示しますが、内部的には異なるデータです。

ただ、ObjectScript では型を厳密に定義しなくてもデータを扱える、という「メリット」があります。たとえば a は上記のように内部的には文字列扱いですが、aをキャストしなくても、数値を加えることができます。 

    set a="12345"    ;; a: String
    set b=a+1        ;; b: INTEGER!

つまり、上記の a と x はデータとしては厳密には異なりますが、ObjectScriptで取り扱うときは、多言語と違って、文字でもあり数値でもある曖昧さを許容してプログラミングできる、ということです。プログラマーにはラクチンです😄


ここで、Yuji さんがご質問されているテーブル定義の VARCHAR ですが、これは内部データ格納時に、ObjectScript 経由で登録すると 「%Stringだが、もし数値として登録されるなら、数値として登録される仕様」となっています。

Property a1 As %String;

ClassMethod init()
{
    &sql(insert into test (a1) values ('123'))
    &sql(insert into test (a1) values ('12345678901234567890'))
}

1件目のデータは、数値 123
2件目のデータは、(数値範囲を超える桁数なので) 文字列 12345678901234567890

ただ、ODBC / JDBC 経由でデータ挿入をする場合は、ODBC / JDBC の世界では厳密にデータ型を定義しているため、IRIS登録時に「VARCHAR の 123456789012345678 ね」 と情報が届きます。そのため、同じINSERTでも

INSERT INTO test (a1) values (123)

は、文字列 123 として登録されます。

ちなみに、「ObjectScriptでそのデータは文字列か数値か」は、$List のデータに格納することで区別がつきます。

    set a=123    ;; INTEGER
    set x="123"  ;; STRING
    
    set a1=$LB(a)    ;; INTEGER in $LIST 
    zzdump a1        ;; a1: 03 04 7B 

    set x1=$LB(x)    ;; STRING in $LIST
    zzdump x1        ;; x1: 05 01 31 32 33
    

$LIST は第2バイトに型をもっています。上の例ですと

a1 :  型 04 = INTEGER
x1 :  型 01 = STRING

という感じです。

あまりご質問の回答としてふさわしくない話題かもしれませんが、、、 
「なるほど、その分野はユルめの言語なのね」と思っていただけると嬉しいです。

@Seisuke Nakahashi さん

ご回答ありがとうございます!
仕様かな、とは思っていましたが、よりDEEPな内容がお伺いできてよかったです。

上記を踏まえてうえでシステムとしてどう設計するべきかを検討するようにします。