TParametersにNULL値でエラー @Delphi XE2

3421 adErrDataConversion
アプリケーションが、現在の操作に対して間違った型の値を使用しています。たとえば、ストリームを使用する操作に文字列を指定した可能性があります。

という、エラーが発生。

今回、備考で使用していたftMemoFieldも同様のエラーが発生し、
ftWideMemoに変更してみたり、
SQLServerの型も、text >> nvarchar(MAX)に置き換えたりしたが、
だめだった・・・

ひとまずコメントアウトしてみたが、別の項目でもエラーが発生する。

大昔に悪銭苦闘し、

   Param.Size := Field.Size;
        if (Field is TBlobField) then begin
          with Field do
DebugPrint(FieldName + ': ' + Value + '/' + NewValue + '/' + OldValue);
          // blob #274 
          Param.Size := (Field as TBlobField).BlobSize;
        end;
        if Param.Size <= 0 then
          Param.Size := 1;
        if VarIsNull(Value) then
          if not (Param.DataType in [ftCurrency]) then
            Param.DataType := ftString;

こんなコードを記述して、TParameterを使用して、NULL値を、
Insert/Update文で、SQLServerに値を挿入していたが、
時が経過し、このコードが通用しなくなったようだ。

***

ParamByName('ID_TEST_2').DataType := ftInteger;
ParamByName('ID_TEST_2').Clear;
ParamByName('ID_TEST_2').Bound := True;

※https://stackoverflow.com/questions/23269537/delphi-xe2-how-to-pass-a-field-with-null-value

というコードで、NULLが代入できるようだが、
Clearも、Boundも定義されていない。。。@Delphi XE2


今回発生したのは、Int型。
上記、コードを見直してみると、文字列に対しての処理は問題ないが、
Int型、text型に対しては、処理出来ていない・・・

 

ということで、

 if VarIsNull(Value) then
  Param.DataType := Field.DataType;

と、NULLのときは、元の型を渡してやるだけでよかった。

if Param.Size <= 0 then 
  Param.Size := 1;

は、意味のある1つの解決方法だったと思われるが、
今は通用しないようだ。

-

Firebirdのテーブル・カラムに日本語が使えない難と、SQLSERVER LocalDBの発見!

インストール不要のDBサーバーを試してみました。

SQLite

DLLを置けば、使えますね。

新しいDelphiだとFireDACで、SQLiteに接続ができるようですが、
手持ちの最新は、XE5。

オープンソースのコンポーネントを使って、
試してみましたが、inner join 程度のレベルなんですが、
いいコンポーネントがなかったというのが、

MS ACCESS

ADOで接続できるので、期待したのですが、
テーブル同士の結合がとても面倒だったので、断念。

 

で、今回の本命

Firebird

Delphiの初期の頃に付属していたInterbaseから派生した
オープンソースのRDBS「Firebird」ですが、

もともとDelphiと親和性が高いため、コンポーネントも標準でついており、
期待感はとても高かったのですが、

Firebird 日本語 カラム名

日本語カラム(テーブル名も)が指定できません・・・

そういえば、昔Interbaseを使っていたときは、
アルファベットでテーブルを作っていました。

当時は、マルチバイトの対応がまだまだだったので、
そんなもんだと、諦めていましたが、
今では、ほとんどのRDBSで、日本語テーブル・カラムが使えるのに・・・

まさか、新しいFirebirdで日本語が使えないとは、とても思いませんでした!

でも、多くのDBエンジニアは、英語名でカラムを作ってるんですね。

https://thinkit.co.jp/free/tech/31/3

その比率も、

オラクル関連とマイクロソフト関連の両方のカンファレンスで講演する機会があったのですが、Oracle技術者主体だと9対1で日本語を利用しない方が圧倒的に多かったのですが、SQL Server技術者主体だと5対5といった結果でした。

私は、英語だと、列名が長くなりすぎるので、絶対に日本語派!

 

最後に、Firebird Embedded Serverを使うため調査履歴


ということで、
たかだかこの程度のことに、使いたくはなかったのですが、
親に使っていたSQLSERVER Expressを各クライアントにインストール・・・

と思ったところ、

SQLSERVER エディション

サービスとしてではなくアプリケーションのプロセス内で実行される SQL Server Express の軽量展開オプションである SQL Server Express LocalDB を使って、小規模なデータベースを基本的なデスクトップ アプリケーションやデスクトップ ツールに構築することができます。

https://www.microsoft.com/ja-jp/sql-server/sql-server-editions-express

 

ということで、

SQL SERVER EXPRESS Local DB!!!

https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-2016-express-localdb?view=sql-server-2017

※英語のみ

Install LocalDB through the installation wizard or by using the SqlLocalDB.msi program. LocalDB is an option when installing SQL Server 2016 Express.

最新のSQLSERVER Expressは、2017ですが、リンク先は、2016。
オプションとしてLocalDBがあるようですが、
たどっていくと、2017をインストールするしかないようです。

まあ、とりあえず、SQLSERVER Express 2017をダウンロードして、実行。

「メディアのダウンロード」を押すと、「LocalDB」がありました!

参考 >> https://www.ipentec.com/document/sql-server-2017-express-local-db-install

※このLocalDBの機能は、もっと古いエディション2012から、既にあったんですね!知りませんでした!

インスタンスの作成と起動

sqllocaldb.exeを使って、インスタンスを作り、
インスタンスを指定して、起動するわけですね。

sqlserver express localdb インスタンス作成

※黒塗りのところが、「データベース名」となります。

SQLServer Expressとの違いは、サービスとしてではなく、
アプリケーションとして、起動させること。

スタートアップから、起動させる感じで。

 

SQLSERVER Manage Studioに接続

参考 > https://blog.engineer-memo.com/2012/12/16/sql-server-localdb-にデータベースを接続/

SQLSERVER Management Studio に接続

上記で、作成したインスタンスを指定で、Windows認証で接続します。

(localdb)¥インスタンス名

で、SQLSERVER Expressでバックアップしたものを、
localDBに復元させたのですが、いとも簡単に・・・

 

Delphiからの接続

FireDACなど最新品を持ち合わせていないので、TADOConecctionで接続します。

Delphi TAdoConecttion SQLServer LocalDB

いつもは、「Microsoft OLE DB Provider for SQL Server」でつないでいましたが、
今回は、「SQL Server Native Client 11.0」を指定します。

理由は、ここにそう書いてあったのでw

http://linyi-zatta.blogspot.com/2013/02/localdb.html

はい、続いて、SSMSと同様に。

Delphi TAdoConecttion SQLServer LocalDB

以上です。

コンパイルして、実行してみると、変更するコード・SQLは一切なく、
スタンドアローンで、動いてくれるように!

 

あとは、集計時に、AWS RDSに吸い上げるロジックを作れば、完成ですが、
SQLをまったく変更する必要がなかったことで、
ずいぶん時間を節約することが出来ました!

 

ほんと、ExpressやSSMS、無料で商用に使わせてもらえる
SQLSERVER様 素晴らしい限りですね!

経緯

SQLServerを入れた親にも、忙しいときには、
作業が出来るように、アプリを入れているんですが、
不具合が起きると、他の正常なPCで作業ができなくなるため、
再起動出来ないという、罠にハマってしまい、

この対策のために、対策することになりました。

AWS RDSにSQLSERVER Expressがあり、
これを親として使おうと思ったわけですが、

インターネットに接続必須というが出来てしまい、

接続時にちょっと時間がかかる程度で、
データの読み込みは、クラウドであるとはわからないほどの、
使用感なのですが、インターネットが切れると動かないという状況を
考慮すると、やっぱり各クライアントにDBシステムが必要だなと、
ということで、軽いDBを探しました。

 

-