使用Delphi 7和interbase 7
是否可以在一个SQL语句中删除主详细记录及其所有嵌套详细记录?
示例:
表1
ID - 整数
标题 - Varchar(80)
表2
ID - 整数
Table1_ID - 整数
标题 - Varchar(80)
表3
ID - 整数
Table2_ID - 整数
标题 - Varchar(80)
我想删除Table1中的ID 10,以及表2中的所有匹配记录(Table1_ID)及其表3中的所有匹配记录(Table2_ID)
如果我不能在一个sql中执行此操作,我如何以多个sqls(正确的序列来调用语句)执行此操作?
答案 0 :(得分:10)
哟可以按顺序删除一些SQL,记录Table3,table2和table1。一次性交易就像“独特的操作”一样。
另一种方法是在table1上删除一条记录时使用触发器删除与table2相关的记录,在table2中删除相关记录以删除table3上的相关记录。
另一个(如果DB允许)使用ON CASCADE DELETE(或类似)删除tabla2和table3上的相关记录,当你删除记录un table1时(请参阅SGBD /数据库的帮助或文档)。
请原谅我的英语错误。这不是我的自然语言。
问候。
答案 1 :(得分:3)
删除父记录时,可以使用外键级联删除子记录。
当删除Table1(ID)中的记录时,以下命令应创建用于删除Table2(Table1_ID)中记录的外键。
ALTER TABLE TABLE2 ADD CONSTRAINT FK_TABLE2_TABLE1
FOREIGN KEY (Table1_ID) REFERENCES TABLE1 (ID)
ON DELETE CASCADE;
这样,数据库引擎会处理子表中的删除操作,因此您需要做的就是
delete from TABLE1 where ID = :ID_VALUE
此致
答案 2 :(得分:1)
您不能在单个语句中执行此操作,而是可以在Delphi中使用事务,确保执行所有语句或不执行任何语句。
如果您使用的是BDE,请删除TDatabase组件并设置默认属性并编写以下代码。
try
Database1.StartTransaction;
//Execute first query
//Execute second query
//Execute third query
Database1.Commit;
except on E: Exception do
Database1.Rollback;
end;
如果您使用的是ADO,请使用ADOConnection1.BeginTrans;
ADOConnection1.CommitTrans;
ADOConnection1.RollbackTrans;
条款
答案 3 :(得分:1)
如果使用cascade选项创建外键引用,删除父记录也将删除所有详细信息(除非其他限制阻止此操作)。
SQL:
ALTER TABLE Table2 ADD CONSTRAINT Table2_Table1_ID
FOREIGN KEY(Table1_ID) REFERENCES Table1(ID) ON DELETE CASCADE
此解决方案不需要客户端应用程序的配合,服务器将保持数据模型的一致性。
答案 4 :(得分:1)
从Table3删除WHERE Table2_ID IN(SELECT_2 FROM Table_2 WHERE Table1_ID = xxxx)
从Table2删除WHERE Table1_ID = xxxx
从Table1删除WHERE ID = xxxx
答案 5 :(得分:1)
除了已经给出的多个SQL语句,外键关系和触发器的答案。在InterBase中,您还可以编写存储过程来删除主记录和详细记录。然后,您的程序中只需要一个SQL语句。
在这种情况下,您可以使用以下两种存储过程 第一个与HeartWave答案几乎相同,但后来在存储过程中。
CREATE PROCEDURE DELETEMASTERDETAIL_WITHOUTINFO(
pMasterID INTEGER)
RETURNS (
rResult INTEGER)
AS
declare variable vTable2ID integer;
begin
/* don't return information about deleted records */
rResult = 0;
for select id
from table2
where table1_id = :pMasterID
into :vTable2ID do
begin
delete from table3
where table2_id = :vTable2ID;
end
delete from table2
where table1_id = :pMasterID;
delete from table1
where id = :pMasterID;
rResult = rResult + 1;
suspend;
end
调用此存储过程的SQL语句是:
select rresult
from deletemasterdetail_withoutinfo(:pMasterID)
第二个将返回有关每个表的已删除记录数量的信息。我不知道你是否需要它,但也许对其他人有帮助。如果Table1中的ID字段是主键,则select语句的第一个字段有点过分。
CREATE PROCEDURE DELETEMASTERDETAIL_WITHINFO(
pMasterID INTEGER)
RETURNS (
rTable1Deleted INTEGER,
rTable2Deleted INTEGER,
rTable3Deleted INTEGER)
AS
declare variable vTable1ID integer;
declare variable vTable2ID integer;
declare variable vTable3ID integer;
begin
/* return information about deleted records */
rTable1Deleted = 0;
rTable2Deleted = 0;
rTable3Deleted = 0;
for select id
from table1
where id = :pMasterID
into :vTable1ID do
begin
for select id
from table2
where table1_id = :vTable1ID
into :vTable2ID do
begin
for select id
from table3
where table2_id = :vTable2ID
into :vTable3ID do
begin
rTable3Deleted = rTable3Deleted + 1;
delete from table3
where id = :vTable3ID;
end
rTable2Deleted = rTable2Deleted + 1;
delete from table2
where id = :vTable2ID;
end
rTable1Deleted = rTable1Deleted + 1;
delete from table1
where id = :vTable1ID;
end
suspend;
end
调用此存储过程的SQL语句是:
select rtable1deleted, rtable2deleted, rtable3deleted
from deletemasterdetail_withinfo(:pMasterID)
顺便说一句。我几乎总是在SP中使用至少一个返回参数。这将允许使用Query组件来调用存储过程 如果没有结果参数,则必须使用存储过程组件来执行SP。