soothin
asked on
Violation on FOREIGN KEY constraint
I have almost reached the point of “Scream!” Running this code will return the error:
“Project Corp.exe raised exception class EIBInterbaseError with message ‘violation of FOREIGN KEY constraint “AVAIL_FUNDS”.
On the backend, EMPLOYEE Table is linked to ASSETS by employee id; cascade update and cascade delete.
All other tables -- including AVAIL_FUNDS -- where the employee ids are linked, are cascade update and set null on delete.
Calling “DELETE” only, on the employee table from either the backend or the front end operates properly. All linked records in ASSETS are deleted and the other tables set the associated records value to NULL.
Running the code will insert the values into the FUNDS and BUYO datasets, and will post/commit the values in the database, then return the error on DELETE of the employee.
One thing I’ve noticed, after commit the Employee dataset (EmpDS) is not closing as expected. For some reason it remain in the “Active” state.
Any assistance would be greatly appreciated.
Front end: C++ Builder 6 Pro (build 10.166)
Backend: Interbase 7.5 ; Dialect 3
Win XP ; Service Pack 2
void __fastcall TEmployeeFrm::btnBuyoutCli ck(TObject *Sender)
{
int shBuyOut = DataMod->EmpDS->FieldByNam e("EMPLOYE EID")->AsI nteger;
AnsiString currName = DataMod->EmpDS->FieldByNam e("FULL_NA ME")->AsSt ring;
Variant cpStanding = DataMod->StandDS->Lookup(" EMPLOYEE", shBuyOut," SUM_OF_ADD EDASSET1") ;
DataMod->FundsDS->Last();
double currAvail = DataMod->FundsDS->FieldByN ame("CURR_ FUNDS")->A sCurrency,
shStanding = cpStanding,
payAmount = 0,
curr_money_change = 0;
payAmount = shStanding * currAvail;
curr_money_change = currAvail - payAmount;
DataMod->FundsDS->Insert() ;
DataMod->FundsDS->FieldByN ame("CURR_ FUNDS")->A sCurrency = curr_money_change;
DataMod->FundsDS->FieldByN ame("EMP_I D")->AsInt eger = shBuyOut;
DataMod->FundsDS->FieldByN ame("CHANG E")->AsCur rency = payAmount;
DataMod->FundsDS->FieldByN ame("AVAIL _BY")->AsS tring = currName;
DataMod->FundsDS->Post();
if(DataMod->FundsTA->Activ e == false)
DataMod->FundsTA->StartTra nsaction() ;
Screen->Cursor = crSQLWait;
DataMod->EmpDS->DisableCon trols();
try
{
DataMod->FundsTA->Commit() ;
}
__finally
{
for(int z=0; z < DataMod->Corporate->DataSe tCount; z++)
DataMod->Corporate->DataSe ts[z]->Act ive = true;
}
DataMod->BuyODS->Insert();
DataMod->BuyODS->FieldByNa me("EMPLOY _ID")->AsI nteger = shBuyOut;
DataMod->BuyODS->FieldByNa me("BO_NAM E")->AsStr ing = currName;
DataMod->BuyODS->FieldByNa me("BO_STA NDING")->A sCurrency = shStanding;
DataMod->BuyODS->FieldByNa me("BO_CUR R_FUNDS")- >AsCurrenc y = currAvail;
DataMod->BuyODS->FieldByNa me("PAYOUT ")->AsCurr ency = payAmount;
DataMod->BuyODS->Post();
if(DataMod->BuyOTA->Active == false)
DataMod->BuyOTA->StartTran saction();
try
{
DataMod->BuyOTA->Commit();
}
__finally
{
for(int y=0; y < DataMod->Corporate->DataSe tCount; y++)
DataMod->Corporate->DataSe ts[y]->Act ive = true;
DataMod->EmpDS->EnableCont rols();
}
TLocateOptions SearchEmp;
SearchEmp.Clear();
bool FoundEmp = DataMod->EmpDS->Locate("EM PLOYEEID", shBuyOut, SearchEmp);
if(FoundEmp == true)
DataMod->EmpDS->Delete();
if(DataMod->EmpTA->Active == false)
DataMod->EmpTA->StartTrans action();
try
{
DataMod->EmpTA->Commit();
}
__finally
{
for(int x=0; x < DataMod->Corporate->DataSe tCount; x++)
DataMod->Corporate->DataSe ts[x]->Act ive = true;
DataMod->EmpDS->EnableCont rols();
}
Screen->Cursor = crDefault;
}
“Project Corp.exe raised exception class EIBInterbaseError with message ‘violation of FOREIGN KEY constraint “AVAIL_FUNDS”.
On the backend, EMPLOYEE Table is linked to ASSETS by employee id; cascade update and cascade delete.
All other tables -- including AVAIL_FUNDS -- where the employee ids are linked, are cascade update and set null on delete.
Calling “DELETE” only, on the employee table from either the backend or the front end operates properly. All linked records in ASSETS are deleted and the other tables set the associated records value to NULL.
Running the code will insert the values into the FUNDS and BUYO datasets, and will post/commit the values in the database, then return the error on DELETE of the employee.
One thing I’ve noticed, after commit the Employee dataset (EmpDS) is not closing as expected. For some reason it remain in the “Active” state.
Any assistance would be greatly appreciated.
Front end: C++ Builder 6 Pro (build 10.166)
Backend: Interbase 7.5 ; Dialect 3
Win XP ; Service Pack 2
void __fastcall TEmployeeFrm::btnBuyoutCli
{
int shBuyOut = DataMod->EmpDS->FieldByNam
AnsiString currName = DataMod->EmpDS->FieldByNam
Variant cpStanding = DataMod->StandDS->Lookup("
DataMod->FundsDS->Last();
double currAvail = DataMod->FundsDS->FieldByN
shStanding = cpStanding,
payAmount = 0,
curr_money_change = 0;
payAmount = shStanding * currAvail;
curr_money_change = currAvail - payAmount;
DataMod->FundsDS->Insert()
DataMod->FundsDS->FieldByN
DataMod->FundsDS->FieldByN
DataMod->FundsDS->FieldByN
DataMod->FundsDS->FieldByN
DataMod->FundsDS->Post();
if(DataMod->FundsTA->Activ
DataMod->FundsTA->StartTra
Screen->Cursor = crSQLWait;
DataMod->EmpDS->DisableCon
try
{
DataMod->FundsTA->Commit()
}
__finally
{
for(int z=0; z < DataMod->Corporate->DataSe
DataMod->Corporate->DataSe
}
DataMod->BuyODS->Insert();
DataMod->BuyODS->FieldByNa
DataMod->BuyODS->FieldByNa
DataMod->BuyODS->FieldByNa
DataMod->BuyODS->FieldByNa
DataMod->BuyODS->FieldByNa
DataMod->BuyODS->Post();
if(DataMod->BuyOTA->Active
DataMod->BuyOTA->StartTran
try
{
DataMod->BuyOTA->Commit();
}
__finally
{
for(int y=0; y < DataMod->Corporate->DataSe
DataMod->Corporate->DataSe
DataMod->EmpDS->EnableCont
}
TLocateOptions SearchEmp;
SearchEmp.Clear();
bool FoundEmp = DataMod->EmpDS->Locate("EM
if(FoundEmp == true)
DataMod->EmpDS->Delete();
if(DataMod->EmpTA->Active == false)
DataMod->EmpTA->StartTrans
try
{
DataMod->EmpTA->Commit();
}
__finally
{
for(int x=0; x < DataMod->Corporate->DataSe
DataMod->Corporate->DataSe
DataMod->EmpDS->EnableCont
}
Screen->Cursor = crDefault;
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Oh, also here are the indexes
Name Unique Table Foreign Key
-------------------------- ---------- ---------- ---------- ---------- --
RDB$FOREIGN37 No ASSETS RDB$PRIMARY1
RDB$PRIMARY3 Yes ASSETS
RDB$FOREIGN49 No ASSETS_SEC RDB$PRIMARY1
RDB$PRIMARY12 Yes ASSETS_SEC
RDB$FOREIGN48 No AVAIL_FUNDS RDB$PRIMARY1
RDB$PRIMARY52 Yes AVAIL_FUNDS
RDB$PRIMARY35 Yes BUYOUT
RDB$FOREIGN31 No DIST_WINS RDB$PRIMARY7
RDB$FOREIGN46 No DIST_WINS RDB$PRIMARY1
RDB$PRIMARY30 Yes DIST_WINS
RDB$10 Yes EMPLOYEES
RDB$PRIMARY1 Yes EMPLOYEES
Name Unique Table Foreign Key
--------------------------
RDB$FOREIGN37 No ASSETS RDB$PRIMARY1
RDB$PRIMARY3 Yes ASSETS
RDB$FOREIGN49 No ASSETS_SEC RDB$PRIMARY1
RDB$PRIMARY12 Yes ASSETS_SEC
RDB$FOREIGN48 No AVAIL_FUNDS RDB$PRIMARY1
RDB$PRIMARY52 Yes AVAIL_FUNDS
RDB$PRIMARY35 Yes BUYOUT
RDB$FOREIGN31 No DIST_WINS RDB$PRIMARY7
RDB$FOREIGN46 No DIST_WINS RDB$PRIMARY1
RDB$PRIMARY30 Yes DIST_WINS
RDB$10 Yes EMPLOYEES
RDB$PRIMARY1 Yes EMPLOYEES
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
After I post the metadata, I notice the same thing. Although the index was there, I made sure that the constraint appeared in the metadata, but still got the same error.
However, I’m hot on the track of getting this thing licked. Each dataset had its own transaction in the application. So I deleted all transactions with the exception of the default transaction, and the whole program works like a charm. I think this would be fine if only one person would be using the application, but this is not how we use our client / server applications.
Two bullets in the Developer’s Guide I’m currently looking at to resolve further.
- Concurrent transactions do not see each other’s partial or uncommitted results, which might create inconsistencies in the application’s state. This is referred to as “isolation”.
- Committed updates to records survive failures, including communication failures, process failures, and server system failure. This is referred to as durability.
The problem lies in the transactions, or how I'm using transactions.
However, I’m hot on the track of getting this thing licked. Each dataset had its own transaction in the application. So I deleted all transactions with the exception of the default transaction, and the whole program works like a charm. I think this would be fine if only one person would be using the application, but this is not how we use our client / server applications.
Two bullets in the Developer’s Guide I’m currently looking at to resolve further.
- Concurrent transactions do not see each other’s partial or uncommitted results, which might create inconsistencies in the application’s state. This is referred to as “isolation”.
- Committed updates to records survive failures, including communication failures, process failures, and server system failure. This is referred to as durability.
The problem lies in the transactions, or how I'm using transactions.
ASKER
/* Table: ASSETS, Owner: SYSDBA */
CREATE TABLE "ASSETS"
(
"ASSETID" INTEGER NOT NULL,
"EMPLOYEE" INTEGER,
"ADDEDASSET" "ASSETLINE",
"ASSETDATE" TIMESTAMP,
CONSTRAINT "PK_ASSETS" PRIMARY KEY ("ASSETID")
);
/* Table: ASSETS_SEC, Owner: SYSDBA */
CREATE TABLE "ASSETS_SEC"
(
"ASSET_SECID" INTEGER NOT NULL,
"ADDED_SEC" "ASSETLINE",
"ADD_SEC_DATE" TIMESTAMP,
"ADDED_SEC_SH" INTEGER,
"ADDED_BY" "FULLNAME_VALUE",
CONSTRAINT "PK_ASSETS_SEC" PRIMARY KEY ("ASSET_SECID")
);
/* Table: AVAIL_FUNDS, Owner: SYSDBA */
CREATE TABLE "AVAIL_FUNDS"
(
"AVAIL_ID" INTEGER NOT NULL,
"EMP_ID" INTEGER,
"CURR_FUNDS" "ASSETLINE",
"AVAIL_DATE" TIMESTAMP,
"CHANGE" "ASSETLINE",
"AVAIL_BY" "FULLNAME_VALUE",
PRIMARY KEY ("AVAIL_ID")
);
/* Table: BUYOUT, Owner: SYSDBA */
CREATE TABLE "BUYOUT"
(
"BUYOUT_ID" INTEGER NOT NULL,
"EMPLOY_ID" INTEGER,
"BO_NAME" "FULLNAME_VALUE",
"BO_STANDING" "ASSETLINE",
"BO_CURR_FUNDS" "ASSETLINE",
"PAYOUT" "ASSETLINE",
"BUYOUT_DATE" TIMESTAMP,
CONSTRAINT "PK_BUYOUT" PRIMARY KEY ("BUYOUT_ID")
);
/* Table: DIST_WINS, Owner: SYSDBA */
CREATE TABLE "DIST_WINS"
(
"WIN_KEY" INTEGER NOT NULL,
"WIN_ID" INTEGER,
"EMPNO" INTEGER,
"SH_STANDINGS" "ASSETLINE",
"DISTRIBUTED_SHARE" "ASSETLINE",
"DISTRIBUTED_DATE" TIMESTAMP,
"WIN_NAME" "FULLNAME_VALUE",
CONSTRAINT "PK_DIST_WINS" PRIMARY KEY ("WIN_KEY")
);
/* Table: EMPLOYEES, Owner: SYSDBA */
CREATE TABLE "EMPLOYEES"
(
"EMPLOYEEID" INTEGER NOT NULL,
"LASTNAME" VARCHAR(20) NOT NULL,
"FIRSTNAME" VARCHAR(15),
"USERID" "USERNAME" NOT NULL,
"DATEHIRE" DATE,
"ADDRESS1" "ADDRESSLINE",
"ADDRESS2" VARCHAR(10),
"CITY" VARCHAR(15),
"STATE" CHAR(2),
"ZIPCODE" VARCHAR(11),
"FULL_NAME" COMPUTED BY (LASTNAME||', '||FIRSTNAME),
"EMAIL" VARCHAR(20),
"PHONE" VARCHAR(13),
CONSTRAINT "PK_EMPLOYEES" PRIMARY KEY ("EMPLOYEEID"),
CONSTRAINT "UNQ1_EMPLOYEES" UNIQUE ("USERID")
);
ALTER TABLE "ASSETS" ADD FOREIGN KEY ("EMPLOYEE") REFERENCES "EMPLOYEES" ("EMPLOYEEID") ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE "ASSETS_SEC" ADD CONSTRAINT "FK_ASSETS_SEC_1" FOREIGN KEY ("ADDED_SEC_SH") REFERENCES "EMPLOYEES" ("EMPLOYEEID") ON UPDATE CASCADE ON DELETE SET NULL;
ALTER TABLE "AVAIL_FUNDS" ADD CONSTRAINT "FK_AVAIL_FUNDS_1" FOREIGN KEY ("EMP_ID") REFERENCES "EMPLOYEES" ("EMPLOYEEID") ON UPDATE CASCADE ON DELETE SET NULL;
ALTER TABLE "DIST_WINS" ADD CONSTRAINT "FK_DIST_WINS_2" FOREIGN KEY ("EMPNO") REFERENCES "EMPLOYEES" ("EMPLOYEEID") ON UPDATE CASCADE ON DELETE SET NULL;