Insert/update TBlobfield (aka image) using sql parameters - sql

I want to store images in a database using sql but cant seem to get it to work:
qry.SQL.Clear;
qry.Sql.Add('update tbl set pic = :blobVal where id = :idVal');
qry.Parameters.ParamByName('idVal')._?:=1;
.Parameters has no .asinteger like .Param has but .Param isn't compatible with a TADOquery - to workaround I tried:
a_TParameter:=qry.Parameters.CreateParameter('blobval',ftBlob,pdinput,SizeOf(TBlobField),Null);
a_TParam.Assign(a_TParameter);
a_TParam.asblob:=a_Tblob;
qry.ExecSql;
This also doesnt work:
qry.SQL.Clear;
qry.Sql.Add('update tbl set pic = :blobVal where id = 1')
qry.Parameters.ParamByName('blobVal').LoadFromStream(img as a_TFileStream,ftGraphic);//ftblob
//or
qry.Parameters.ParamByName('blobVal').LoadFromFile('c:\sample.jpg',ftgrafic);//ftblob
qry.ExecSql;

Should be something like:
qry.Parameters.Clear;
qry.Parameters.AddParameter.Name := 'blobVal';
qry.Parameters.ParamByName('blobVal').LoadFromFile('c:\sample.jpg', ftBlob);
// or load from stream:
// qry.Parameters.ParamByName('blobVal').LoadFromStream(MyStream, ftBlob);
qry.Parameters.AddParameter.Name := 'idVal';
qry.Parameters.ParamByName('idVal').Value := 1;
qry.SQL.Text := 'update tbl set pic = :blobVal where id = :idVal';
qry.ExecSQL;
To read the BLOB back from the DB:
qry.SQL.Text := 'select id, pic from tbl where id = 1';
qry.Open;
TBlobField(qry.FieldByName('pic')).SaveToFile('c:\sample_2.jpg');

I'm using Lazarus, not Delphi, but I guess its usually the same syntax. If so, here's a slight improvement on kobiks suggestion:
Parameters are added automatically if the SQL.Text is assigned before trying to assign values to the parameters. Like this:
qry.Parameters.Clear;
qry.SQL.Text := 'update tbl set pic = :blobVal where id = :idVal';
qry.Parameters.ParamByName('blobVal').LoadFromFile('c:\sample.jpg', ftBlob);
qry.Parameters.ParamByName('idVal').Value := 1;
qry.ExecSQL;

I wrote this as an answer to this q,
Delphi save packed record as blob in a sql database
which is currently flagged as a duplicate, possibly incorrectly because the technique
used by the OP as described in comments appears to be correct. So, the cause of the problem may lie elsewhere.
If the Duplicate flag gets removed, I'll re-post this answer there.
The following code works fine for me against a Sql Server table defined as shown below.
The data from Rec1 is saved into the table and correctly read back into Rec2.
(* MS Sql Server DDL
CREATE TABLE [blobs] (
[id] [int] NOT NULL ,
[blob] [image] NULL ,
CONSTRAINT [PK_blobs] PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
*)
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
qBlobInsert: TADOQuery;
qBlobRead: TADOQuery;
Button1: TButton;
procedure Button1Click(Sender: TObject);
[...]
type
TMyRecord = packed record
FontName: string[30];
FontSize: word;
FontColor: integer;
FontStyle: word;
Attachement: string[255];
URL: string[255];
end;
const
scInsert = 'insert into blobs(id, blob) values(:id, :blob)';
scSelect = 'select * from blobs where id = %d';
procedure TForm1.Button1Click(Sender: TObject);
begin
TestInsert;
end;
procedure TForm1.TestInsert;
var
Rec1,
Rec2 : TMyRecord;
MS : TMemoryStream;
begin
FillChar(Rec1, SizeOf(Rec1), #0);
FillChar(Rec2, SizeOf(Rec2), #0);
Rec1.FontName := 'AName';
Rec1.URL := 'AUrl';
MS := TMemoryStream.Create;
try
// Save Rec1 using an INSERT statement
MS.Write(Rec1, SizeOf(Rec1));
MS.Seek(0, soFromBeginning);
qBlobInsert.Parameters[0].Value := 1;
qBlobInsert.Parameters[1].LoadFromStream(MS, ftBlob);
qBlobInsert.SQL.Text := scInsert;
qBlobInsert.ExecSQL;
// Read saved data back into Rec2
qBlobRead.SQL.Text := Format(scSelect, [1]);
qBlobRead.Open;
MS.Clear;
TBlobField(qBlobRead.FieldByName('blob')).SaveToStream(MS);
MS.Seek(0, soFromBeginning);
MS.Read(Rec2, MS.Size - 1);
Caption := Rec2.FontName + ':' + Rec2.URL;
finally
MS.Free;
end;
end;
Extract from DFM
object qBlobInsert: TADOQuery
Connection = ADOConnection1
Parameters = <
item
Name = 'id'
DataType = ftInteger
Value = Null
end
item
Name = 'blob'
DataType = ftBlob
Value = Null
end>
Left = 56
Top = 32
end

Related

IsNull returns TRUE when inserting empty (NOT NULL) strings in a LONG VARCHAR field (SQL Anywhere)

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.

Delphi save packed record as blob in a sql database [duplicate]

I want to store images in a database using sql but cant seem to get it to work:
qry.SQL.Clear;
qry.Sql.Add('update tbl set pic = :blobVal where id = :idVal');
qry.Parameters.ParamByName('idVal')._?:=1;
.Parameters has no .asinteger like .Param has but .Param isn't compatible with a TADOquery - to workaround I tried:
a_TParameter:=qry.Parameters.CreateParameter('blobval',ftBlob,pdinput,SizeOf(TBlobField),Null);
a_TParam.Assign(a_TParameter);
a_TParam.asblob:=a_Tblob;
qry.ExecSql;
This also doesnt work:
qry.SQL.Clear;
qry.Sql.Add('update tbl set pic = :blobVal where id = 1')
qry.Parameters.ParamByName('blobVal').LoadFromStream(img as a_TFileStream,ftGraphic);//ftblob
//or
qry.Parameters.ParamByName('blobVal').LoadFromFile('c:\sample.jpg',ftgrafic);//ftblob
qry.ExecSql;
Should be something like:
qry.Parameters.Clear;
qry.Parameters.AddParameter.Name := 'blobVal';
qry.Parameters.ParamByName('blobVal').LoadFromFile('c:\sample.jpg', ftBlob);
// or load from stream:
// qry.Parameters.ParamByName('blobVal').LoadFromStream(MyStream, ftBlob);
qry.Parameters.AddParameter.Name := 'idVal';
qry.Parameters.ParamByName('idVal').Value := 1;
qry.SQL.Text := 'update tbl set pic = :blobVal where id = :idVal';
qry.ExecSQL;
To read the BLOB back from the DB:
qry.SQL.Text := 'select id, pic from tbl where id = 1';
qry.Open;
TBlobField(qry.FieldByName('pic')).SaveToFile('c:\sample_2.jpg');
I'm using Lazarus, not Delphi, but I guess its usually the same syntax. If so, here's a slight improvement on kobiks suggestion:
Parameters are added automatically if the SQL.Text is assigned before trying to assign values to the parameters. Like this:
qry.Parameters.Clear;
qry.SQL.Text := 'update tbl set pic = :blobVal where id = :idVal';
qry.Parameters.ParamByName('blobVal').LoadFromFile('c:\sample.jpg', ftBlob);
qry.Parameters.ParamByName('idVal').Value := 1;
qry.ExecSQL;
I wrote this as an answer to this q,
Delphi save packed record as blob in a sql database
which is currently flagged as a duplicate, possibly incorrectly because the technique
used by the OP as described in comments appears to be correct. So, the cause of the problem may lie elsewhere.
If the Duplicate flag gets removed, I'll re-post this answer there.
The following code works fine for me against a Sql Server table defined as shown below.
The data from Rec1 is saved into the table and correctly read back into Rec2.
(* MS Sql Server DDL
CREATE TABLE [blobs] (
[id] [int] NOT NULL ,
[blob] [image] NULL ,
CONSTRAINT [PK_blobs] PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
*)
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
qBlobInsert: TADOQuery;
qBlobRead: TADOQuery;
Button1: TButton;
procedure Button1Click(Sender: TObject);
[...]
type
TMyRecord = packed record
FontName: string[30];
FontSize: word;
FontColor: integer;
FontStyle: word;
Attachement: string[255];
URL: string[255];
end;
const
scInsert = 'insert into blobs(id, blob) values(:id, :blob)';
scSelect = 'select * from blobs where id = %d';
procedure TForm1.Button1Click(Sender: TObject);
begin
TestInsert;
end;
procedure TForm1.TestInsert;
var
Rec1,
Rec2 : TMyRecord;
MS : TMemoryStream;
begin
FillChar(Rec1, SizeOf(Rec1), #0);
FillChar(Rec2, SizeOf(Rec2), #0);
Rec1.FontName := 'AName';
Rec1.URL := 'AUrl';
MS := TMemoryStream.Create;
try
// Save Rec1 using an INSERT statement
MS.Write(Rec1, SizeOf(Rec1));
MS.Seek(0, soFromBeginning);
qBlobInsert.Parameters[0].Value := 1;
qBlobInsert.Parameters[1].LoadFromStream(MS, ftBlob);
qBlobInsert.SQL.Text := scInsert;
qBlobInsert.ExecSQL;
// Read saved data back into Rec2
qBlobRead.SQL.Text := Format(scSelect, [1]);
qBlobRead.Open;
MS.Clear;
TBlobField(qBlobRead.FieldByName('blob')).SaveToStream(MS);
MS.Seek(0, soFromBeginning);
MS.Read(Rec2, MS.Size - 1);
Caption := Rec2.FontName + ':' + Rec2.URL;
finally
MS.Free;
end;
end;
Extract from DFM
object qBlobInsert: TADOQuery
Connection = ADOConnection1
Parameters = <
item
Name = 'id'
DataType = ftInteger
Value = Null
end
item
Name = 'blob'
DataType = ftBlob
Value = Null
end>
Left = 56
Top = 32
end

Oracle 11g - Find Records in a CLOB with Carriage Return Line Feed

I am on Oracle 11g. I am trying to do a Find and Replace functionality on a CLOB field (using REPLACE).
Now the data in my CLOB has CRLFs in them, the replace works just fine until I want to find a string that contains CRLFs. Perhaps this would be best explained by example:
So say the text in my field is:
----------------------------------
Hi there this is some text
that has CRLFS in it.
Some other text that
is there also.
Have a nice day
Now what I want to do is replace all occurrences of this INCLUDING the CRLFs:
Search Text
--------------------------------------------------------------------------------
Some other text that
is there also.
With this text INCLUING the CRLFs:
Replace Text
------------------------------------
Some other text that
has some new text that is there also.
So That could come out to be:
----------------------------------
Hi there this is some text
that has CRLFS in it.
Some other text that
has some new text that is there also.
Have a nice day
Now I am doing this in a stored procedure and the Search Text and Replace Text come in as variables, but When I try and say where like % || ReplaceText || '%' it returns 0 rows.
Does anyone have an idea how to do this?
Here is my stored procedure (iOldResponsibilities is the Search Text, iNewResponsibilities is the replace text:
PROCEDURE FindReplaceResponsibilities (
iOldResponsibilities IN JP_JOB_FAMILIES.RESPONSIBILITIES%TYPE,
iNewResponsibilities IN JP_JOB_FAMILIES.RESPONSIBILITIES%TYPE,
oNumRowsUpdated OUT INTEGER
)
IS
BEGIN
oNumRowsUpdated := 0;
SAVEPOINT sp_jf_findrepresp;
-- If there is no old text to search for then,
-- append the new text to the end of every row.
-- Else replace all occurrences of the old text with the new text
IF iOldResponsibilities IS NULL THEN
UPDATE JP_JOB_FAMILIES
SET RESPONSIBILITIES = RESPONSIBILITIES || iNewResponsibilities;
oNumRowsUpdated := SQL%ROWCOUNT;
ELSE
UPDATE JP_JOB_FAMILIES
SET RESPONSIBILITIES = REPLACE(RESPONSIBILITIES, iOldResponsibilities, iNewResponsibilities)
WHERE RESPONSIBILITIES like '%' || iOldResponsibilities || '%';
-- I have also tried this:
--WHERE dbms_lob.instr(RESPONSIBILITIES, TO_CLOB(iOldResponsibilities)) > 0; -- This is a LIKE for CLOBS
oNumRowsUpdated := SQL%ROWCOUNT;
END IF;
RETURN;
EXCEPTION
WHEN OTHERS THEN
BEGIN
oNumRowsUpdated := -1;
ROLLBACK TO sp_jf_findrepresp;
dbms_output.put_line('error: ' || sqlerrm);
RETURN;
END;
END FindReplaceResponsibilities;
The Text is coming from an asp.net application (c#) as String values:
public int FindReplaceJobFamilyResponsibilities(String oldResponsibilities, String newResponsibilities, IDbTransaction transaction = null)
{
using (IDbCommand cmd = this._dataHelper.GetStoredProcedure(_connectionString,
"JP_JOBFAM_PKG.FindReplaceResponsibilities", true))
{
_dataHelper.SetParameterValue(cmd, "iOldResponsibilities", oldResponsibilities);
_dataHelper.SetParameterValue(cmd, "iNewResponsibilities", newResponsibilities);
DataHelperBase.VerifyParameters(cmd.Parameters, false);
base.SetExecuteConnection(cmd, transaction);
_dataHelper.ExecuteNonQuery(cmd);
return Convert.ToInt32(_dataHelper.GetParameterValue(cmd, "oNumRowsUpdated"));
}
}
Turns out to be a case of bad data. The data in my Test DB was corrupted and only had LFs instead of CRLFs.
GIGO :-)
Thanks for all your help
Oh and by the way In my code example I went with the INSTR function instead of the like function. If the user entered a % in the text to search through that might have messed up the like statement. (Can't filter those out because % might be a valid character in my data)
Here is the Final Code:
PROCEDURE FindReplaceResponsibilities (
iOldResponsibilities IN JP_JOB_FAMILIES.RESPONSIBILITIES%TYPE,
iNewResponsibilities IN JP_JOB_FAMILIES.RESPONSIBILITIES%TYPE,
oNumRowsUpdated OUT INTEGER
)
IS
BEGIN
oNumRowsUpdated := 0;
SAVEPOINT sp_jf_findrepresp;
-- If there is no old text to search for then,
-- append the new text to the end of every row.
-- Else replace all occurrences of the old text with the new text
IF iOldResponsibilities IS NULL THEN
UPDATE JP_JOB_FAMILIES
SET RESPONSIBILITIES = RESPONSIBILITIES || iNewResponsibilities;
oNumRowsUpdated := SQL%ROWCOUNT;
ELSE
UPDATE JP_JOB_FAMILIES
SET RESPONSIBILITIES = REPLACE(RESPONSIBILITIES, iOldResponsibilities, iNewResponsibilities)
WHERE dbms_lob.instr(RESPONSIBILITIES, iOldResponsibilities) > 0;
oNumRowsUpdated := SQL%ROWCOUNT;
END IF;
RETURN;
EXCEPTION
WHEN OTHERS THEN
BEGIN
oNumRowsUpdated := -1;
ROLLBACK TO sp_jf_findrepresp;
dbms_output.put_line('error: ' || sqlerrm);
RETURN;
END;
END FindReplaceResponsibilities;
The code from my application was fine:
public int FindReplaceJobFamilyResponsibilities(String oldResponsibilities, String newResponsibilities, IDbTransaction transaction = null)
{
using (IDbCommand cmd = this._dataHelper.GetStoredProcedure(_connectionString,
"JP_JOBFAM_PKG.FindReplaceResponsibilities", true))
{
_dataHelper.SetParameterValue(cmd, "iOldResponsibilities", oldResponsibilities);
_dataHelper.SetParameterValue(cmd, "iNewResponsibilities", newResponsibilities);
DataHelperBase.VerifyParameters(cmd.Parameters, false);
base.SetExecuteConnection(cmd, transaction);
_dataHelper.ExecuteNonQuery(cmd);
return Convert.ToInt32(_dataHelper.GetParameterValue(cmd, "oNumRowsUpdated"));
}
}

Updating a record in database

Using TADOCommand to update a record.
using TADOCommand to insert a new record.
Name of table is Board
Using MS Access database
I get an error
Syntax error in UPDATE/INSERT INTO statement
I can connect and retrieve data just fine. Just never added or updated data before.
My database columns looks like this
ID (auto number)
SN (text)
CardType (text)
Desc (memo)
dbDate (date)
Tech (text)
Code looks like this:
procedure TForm2.BSaveClick(Sender: TObject);
const
sqlStringNew = 'INSERT INTO Board (SN,CardType,Desc,dbDate,Tech) VALUES (:aSN,:aCardType,:aDesc,:aDate,:aTech);';
sqlStringUpdate = 'UPDATE Board SET SN=:aSN, CardType=:aCardType, Desc=:aDesc, dbDate=:aDate, Tech=:aTech WHERE ID = :aID;';
var
ADOCommand : TAdoCommand;
begin
ADOCommand := TADOCommand.Create(nil);
// updating a board
if NewBoard = false then
begin
try
ADOCommand.Connection := adoConnection1;
ADOCommand.Parameters.Clear;
ADOCommand.Commandtext := sqlStringUpdate;
ADOCommand.ParamCheck := false;
ADOCommand.Parameters.ParamByName('aSN').Value := ESerialNumber.Text;
ADOCommand.Parameters.ParamByName('aCardType').Value := ECardType.Text;
ADOCommand.Parameters.ParamByName('aDesc').Value := MDescription.Text;
ADOCommand.Parameters.ParamByName('aDate').Value := strtodate(EDate.Text);
ADOCommand.Parameters.ParamByName('aTech').Value := ETech.Text;
ADOCommand.Parameters.ParamByName('aID').Value := UpdateID;
ADOCommand.Execute;
finally
ADOCommand.Free;
end;
Showmessage('Update Complete');
end;
//if a new board
if NewBoard = True then
Begin
try
ADOCommand.Connection := adoConnection1;
ADOCommand.Parameters.Clear;
ADOCommand.Commandtext := sqlStringNew;
ADOCommand.ParamCheck := false;
ADOCommand.Parameters.ParamByName('aSN').Value := ESerialNumber.Text;
ADOCommand.Parameters.ParamByName('aCardType').Value := ECardType.Text;
ADOCommand.Parameters.ParamByName('aDesc').Value := MDescription.Text;
ADOCommand.Parameters.ParamByName('aDate').Value := strtodate(EDate.Text);
ADOCommand.Parameters.ParamByName('aTech').Value := ETech.Text;
ADOCommand.Execute;
finally
ADOCommand.Free;
end;
NewBoard := false;
BSave.Enabled := false;
NoEdit;
Showmessage('New Record Added');
End;
end;
It is advisable not to use SQL keywords for table and field names. DATE is a function in many SQL dialects. If you choose to use a reserved word/function name for a table/field name, you have to escape it in SQL statement: [Date] for SQL Server and MS Access, "Date" - for Oracle.

SQL query updates then revertes changes

I'm currently baffled by the one problem. I can insert and delete records from my table but I can't update certain fields. It does update it temporarily before reverting changes 0.5 seconds later, I physically see the change. Btw this is done in Delphi 7:
CloseDatabase; // Closes my database first to prevent an error from accessing one that is already open
OpenDatabase; // Dynamically opens the database
ActivateEdits;
if dbeEnglish.Enabled then
begin
qryDictionary.SQL.Text := 'Update [word list] set [english] = "'+dbeEnglish.Text+'" where ([afrikaans] = "'+dbeAfrikaans.Text+'") and ([english] = "'+sEnglishBefore+'")';
qryDictionary.ExecSQL;
end
else
begin
qryDictionary.SQL.Text := 'Update [word list] set [afrikaans] = "'+dbeAfrikaans.Text+'" where ([english] = "'+dbeEnglish.Text+'") and ([afrikaans] = "'+sAfrikaansBefore+'")';
qryDictionary.ExecSQL;
end;
SelectAll; // SQL to select * from [word list] as well as set the column widths
bEngOnce := False; // variable i used to prevent both dbe (data base edits) from being edited
bAfrOnce := False;
Am I updating wrong or missing something in OI? It does update just doesn't make it permanent.
Forgot to mention: The table word list has 3 fields: an auto number field called ID, english and afrikaans. Could the auto number be causing a problem to update?
I would try the following. I'm not sure if it helps but you can check the ExecSQL result. It seems as Bharat mentioned that you have uncommited transaction in your code.
...
if dbeEnglish.Enabled then
begin
qryDictionary.Connection.BeginTrans;
try
qryDictionary.SQL.Text := 'Update [word list] set [english] = "'+dbeEnglish.Text+'" where ([afrikaans] = "'+dbeAfrikaans.Text+'") and ([english] = "'+sEnglishBefore+'")';
qryDictionary.ExecSQL;
qryDictionary.Connection.CommitTrans;
except
qryDictionary.Connection.RollbackTrans;
end;
end
else
begin
qryDictionary.Connection.BeginTrans;
try
qryDictionary.SQL.Text := 'Update [word list] set [afrikaans] = "'+dbeAfrikaans.Text+'" where ([english] = "'+dbeEnglish.Text+'") and ([afrikaans] = "'+sAfrikaansBefore+'")';
qryDictionary.ExecSQL;
qryDictionary.Connection.CommitTrans;
except
qryDictionary.Connection.RollbackTrans;
end;
end;
...
You can also check if some of the rows will be affected by a commit. This is returned by TADOQuery.ExecSQL function result, so you can check it this way.
var
RowsAffected: Integer;
...
RowsAffected := qryDictionary.ExecSQL;
ShowMessage(IntToStr(RowsAffected) + ' row(s) will be affected by commiting this query ...');
...