Delphi 10.3.2 enterprise, database ASA (SQL Anywhere 17.0.9.4913).
I have this table
CREATE TABLE string_null(
lo_key integer NOT NULL DEFAULT AUTOINCREMENT PRIMARY KEY,
str_short char(100) NOT NULL DEFAULT '',
str_long long varchar NOT NULL DEFAULT '');
and I want to insert records using FireDAC TFDConnection
and TFDQuery
components.
qry.Insert;
If I assign non-empty strings, everything works properly.
qry.FindField('str_short').Asstring := 'ABC';
qry.FindField('str_long').Asstring := 'XYZ';
If I insert a record using empty strings (empty, not null!)
qry.FindField('str_short').Asstring := ''; // IsNull is FALSE, ok
qry.FindField('str_long').Asstring := ''; // IsNull becomes TRUE (wrong!)
the IsNull
property on the LONG VARCHAR field returns TRUE even if it has been assigned a NOT NULL value (the empty string), while the short field behavior is correct.
(The property FormatOptions.StrsEmpty2Null
for both the connection and the query is FALSE).
Furthermore, when I execute the Post()
method, Delphi raises the exception on the LONG VARCHAR
field:
Field 'str_long' must have a value
If I set
qry.FindField('str_long').Required := FALSE;
qry.Post;
the record is successful inserted in the database, with empty strings values.
To make short a long story: if I insert a record with empty string values in a LONG VARCHAR
field, the IsNull
property returns a wrong value and I have to assign Required := False
in order to get the INSERT
operation executed.
In this small demonstrative application I try to insert
a record with NOT EMPTY strings (and everything works properly)
a record with EMPTY strings.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.ASA, FireDAC.Phys.ASADef, FireDAC.VCLUI.Wait,
FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, Vcl.StdCtrls,
FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef, FireDAC.Stan.ExprFuncs, FireDAC.Phys.ODBCBase, FireDAC.Comp.UI;
type
TForm1 = class(TForm)
conn: TFDConnection;
qry: TFDQuery;
memo: TMemo;
procedure FormCreate(Sender: TObject);
private
procedure exec_insert(str_value : string);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
LONG_FIELD = 'str_long';
SHORT_FIELD = 'str_short';
procedure TForm1.exec_insert(str_value : string);
procedure msg(s : string);
begin
memo.Text := memo.Text + s + #13#10
end;
begin
msg('======================');
msg('INSERT VALUE = "' + str_value + '"');
try
qry.Insert;
if qry.FindField(SHORT_FIELD).IsNull then msg('BEFORE assign SHORT field is NULL')
else msg('BEFORE assign SHORT field is NOT NULL');
if qry.FindField(LONG_FIELD).IsNull then msg('BEFORE assign LONG field is NULL')
else msg('BEFORE assign LONG field is NOT NULL');
msg('');
qry.FindField(SHORT_FIELD).AsString := str_value;
qry.FindField(LONG_FIELD).Asstring := str_value;
if qry.FindField(SHORT_FIELD).IsNull then msg('AFTER assign SHORT field is NULL')
else msg('AFTER assign SHORT field is NOT NULL');
if qry.FindField(LONG_FIELD).IsNull then msg('AFTER assign LONG field is NULL')
else msg('AFTER assign LONG field is NOT NULL');
//qry.FindField(LONG_FIELD).Required := FALSE;
qry.Post
except
on e: Exception do msg('EXCEPTION: ' + e.message)
end;
msg('')
end;
procedure TForm1.FormCreate(Sender: TObject);
var
s : string;
begin
conn.params.Text := 'Database=jolly'#$D#$A'User_Name=jop'#$D#$A'Password=jpw'#$D#$A'Server=jolly'#$D#$A'DriverID=ASA'#$D#$A;
conn.FormatOptions.StrsEmpty2Null := FALSE;
conn.Connected := TRUE;
qry.FormatOptions.StrsEmpty2Null := FALSE;
qry.SQL.Text := 'select * from string_null';
qry.UpdateOptions.RequestLive := TRUE;
qry.Active := TRUE;
exec_insert('ABC');
exec_insert('')
end;
end.
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 299
ClientWidth = 635
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
DesignSize = (
635
299)
PixelsPerInch = 96
TextHeight = 13
object memo: TMemo
Left = 120
Top = 8
Width = 273
Height = 283
Anchors = [akLeft, akTop, akBottom]
TabOrder = 0
end
object conn: TFDConnection
Left = 28
Top = 12
end
object qry: TFDQuery
Connection = conn
Left = 28
Top = 64
end
end
program Project1;
uses
Vcl.Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
I have not tested the behavior with other databases.