Delphi 10.3.2 предприятие, база данных ASA (SQL Anywhere 17.0.9.4913).
У меня есть эта таблица
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 '');
, и я хочу вставить записи, используя FireDAC TFDConnection
иTFDQuery
компоненты.
qry.Insert;
Если я назначаю непустые строки, все работает правильно.
qry.FindField('str_short').Asstring := 'ABC';
qry.FindField('str_long').Asstring := 'XYZ';
Если я вставляю запись, используя пустые строки (пусто, не ноль!)
qry.FindField('str_short').Asstring := ''; // IsNull is FALSE, ok
qry.FindField('str_long').Asstring := ''; // IsNull becomes TRUE (wrong!)
свойство IsNull
в поле LONG VARCHAR возвращает TRUE, даже если ему было присвоено значение NOT NULL (пустая строка), а короткое поле поведение правильное.
( Свойство FormatOptions.StrsEmpty2Null
как для соединения, так и для запроса равно FALSE ).
Кроме того, когда я выполняю Post()
метод, Delphi вызывает исключение для поля LONG VARCHAR
:
Поле 'str_long' должно иметь значение
Если я установил
qry.FindField('str_long').Required := FALSE;
qry.Post;
запись успешно вставлена в базу данных со значениями пустых строк.
Короче говоря, длинная история: если я вставлюТ.е. запись с пустыми строковыми значениями в поле LONG VARCHAR
, свойство IsNull
возвращает неправильное значение, и мне нужно присвоить Required := False
, чтобы выполнить операцию INSERT
.
В этом небольшом демонстрационном приложении я пытаюсь вставить
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.
Я не тестировал поведение с другими базами данных.