如何用一条sql删除主明细记录?

发布于 2024-11-29 00:12:40 字数 406 浏览 0 评论 0原文

使用 Delphi 7 和 interbase 7

是否可以在一个 SQL 语句中删除主详细记录及其所有嵌套的详细记录?

示例:

表1
ID - 整数
标题 - Varchar(80)

表 2
ID - 整数
Table1_ID - 整数
标题 - Varchar(80)

表 3
ID - 整数
Table2_ID - 整数
TITLE - Varchar(80)

我想从 Table1 中删除 ID 10,以及表 2 中的所有匹配记录 (Table1_ID),以及表 3 中的所有匹配记录 (Table2_ID)

如果我无法在一个 sql 中执行此操作,我如何在多个sql中执行此操作(调用语句的正确顺序)?

Using Delphi 7 and interbase 7

Is it possible to delete a master detail record and all of its nested detail records in one SQL statement?

Example:

Table1
ID - Integer
TITLE - Varchar(80)

Table2
ID - Integer
Table1_ID - Integer
TITLE - Varchar(80)

Table3
ID - Integer
Table2_ID - Integer
TITLE - Varchar(80)

I would like to delete ID 10 from Table1, and all of its matching records (Table1_ID) in table 2, and all its matching records (Table2_ID) in table 3

If i can't do this in one sql, how do i do it in multiple sqls (correct sequence to call statements)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

因为看清所以看轻 2024-12-06 00:12:40

你可以通过一些SQL按顺序删除Table3、table2和table1上的记录来完成。一笔交易就像“独特的操作”一样。

一种替代方法是,当您删除表 1 上的一条记录时,使用触发器删除表 2 上的相关记录,并在表 2 中使用触发器来删除表 3 上的相关记录。

另一种(如果数据库允许)是在删除 table1 上的记录时使用 ON CASCADE DELETE (或类似的)删除 tabla2 和 table3 上的相关记录(请参阅有关 SGBD/数据库的帮助或文档)。

抱歉,英语有错误。这不是我的自然语言。

问候。

Yo can do it witn some SQL's deleteing in order, records on Table3, table2 and table1. All in one transaction to do it like "unique operation".

One alternative is use Triggers for delete record related on table2 when you delete one record on table1, and equivalent in table2 to delete related records on table3.

Another (if DB let you) is use ON CASCADE DELETE (or similar) to delete related records on a tabla2 and table3, when you delete a record un table1 (see help or documentation on your SGBD/Database).

Excuse-me for mistakes with English. It's not my natural language.

Regards.

长安忆 2024-12-06 00:12:40

当父记录被删除时,您可以使用外键将删除级联到子记录。

当删除 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

问候,

You can use foreign keys to cascade deletes to child records when the parent record is deleted.

The following command should create the foreign key to delete records in Table2 (Table1_ID) when the record in Table1 (ID) is deleted.

ALTER TABLE TABLE2 ADD CONSTRAINT FK_TABLE2_TABLE1 
FOREIGN KEY (Table1_ID) REFERENCES TABLE1 (ID) 
ON DELETE CASCADE;

This way the database engine takes care of deletes in child tables so all you need to do is

delete from TABLE1 where ID = :ID_VALUE

Regards,

岁月打碎记忆 2024-12-06 00:12:40

DELETE FROM Table3 WHERE Table2_ID IN (SELECT ID FROM Table_2 WHERE Table1_ID=xxxx)

DELETE FROM Table2 WHERE Table1_ID=xxxx

DELETE FROM Table1 WHERE ID=xxxx

DELETE FROM Table3 WHERE Table2_ID IN (SELECT ID FROM Table_2 WHERE Table1_ID=xxxx)

DELETE FROM Table2 WHERE Table1_ID=xxxx

DELETE FROM Table1 WHERE ID=xxxx

乙白 2024-12-06 00:12:40

您不能在单个语句中执行此操作,但您可以在 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; 语句

You cannot do that in a single statement but instead you can use transactions in Delphi make sure that either all or none of the statements are executed.

If you are using BDE, then drop TDatabase component and set the default properties and write the following code.

try
  Database1.StartTransaction;
  //Execute first query
  //Execute second query
  //Execute third query
  Database1.Commit;
except on E: Exception do
  Database1.Rollback;
end;

If you are using ADO then use ADOConnection1.BeginTrans; ADOConnection1.CommitTrans; ADOConnection1.RollbackTrans; statements

仙女 2024-12-06 00:12:40

如果您使用级联选项创建外键引用,则删除父记录也将删除所有详细信息(除非其他限制阻止这样做)。

SQL:

ALTER TABLE Table2 ADD CONSTRAINT Table2_Table1_ID 
  FOREIGN KEY(Table1_ID) REFERENCES Table1(ID) ON DELETE CASCADE

该解决方案不需要客户端应用程序的配合,服务器将保持数据模型的一致性。

If you create foreign key references with cascade option, deleting the parent record will also delete all details (unless other restrictions prevent this).

SQL:

ALTER TABLE Table2 ADD CONSTRAINT Table2_Table1_ID 
  FOREIGN KEY(Table1_ID) REFERENCES Table1(ID) ON DELETE CASCADE

This solution does not require the cooperation of the client applications, the server will keep the data model consistent.

ゞ花落谁相伴 2024-12-06 00:12:40

除了已经给出的答案之外,还有多个 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 字段是主键,那么第一个 for 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)

BTW。我几乎总是在 SP 中使用至少一个返回参数。这将允许使用查询组件来调用存储过程。
如果没有结果参数,则必须使用存储过程组件来执行 SP。

In addition to the answers already given with multiple SQL statements, foreign key relationships and triggers. In InterBase you can also write a stored procedure to delete the master and detail records. Then you will only need one SQL statement in your program.

Below two kind of stored procedures you could use in this situation.
The first one is almost the same as HeartWave answer, but then in a stored procedure.

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

The SQL statement to call this stored procedure is:

select rresult
from deletemasterdetail_withoutinfo(:pMasterID)

The second one will return information about the amount of deleted records per table. I don't know if you need it, but perhaps it is helpfull for someone else. If the ID field in Table1 is the primary key the first for select statement is a bit overkill.

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

The SQL statement to call this stored procedure is:

select rtable1deleted, rtable2deleted, rtable3deleted
from deletemasterdetail_withinfo(:pMasterID)

BTW. I almost always use at least one return parameter in SP's. This will allow to use a Query component to call the stored procedure.
If there are no result parameters a Stored Procedure component must be used to execute the SP.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文