0

在 SQL Server 2012 中执行的测试表明,DELETE FROM dbo.TableName如果即使删除表中的一条记录也会导致外键违规,该命令会暂停并返回错误。没有记录被删除。

  • 假设未使用的记录是可以在不违反外键关系的情况下删除的记录。

  • 假设所有记录都可以通过不可为空的整数 ID 列唯一标识。

  • 假设忽略可能导致副作用的功能是安全的,例如触发器或级联删除。

  • 应该假设关于表、它的记录和关系的其他内容。(例如:解决方案在这些参数中应该是通用的。)

是否存在以以下形式删除未使用的父记录的解决方案:

  1. SQL 将忽略导致它的记录的错误,并成功执行没有的记录?
  2. 仅对一组以某种方式检测到的未使用的父记录执行删除的 SQL?(对于已知 FK 关系的特定表很容易完成。一般来说不太容易完成
  3. 服务器端代码将执行与上述解决方案等效的操作?

笔记:

  • SQL 解决方案优于需要 C#、Python、Java、Ruby 等的解决方案。
  • 跨 RDBMS 解决方案优于特定于 RDBMS 的解决方案。

请说明您的解决方案适用于并已经过测试的 RDBMS 。

4

4 回答 4

0

如果该行引用了 PK,则删除将失败,但会继续。

SET NOCOUNT ON;

DECLARE @PK varchar(10);

PRINT '-------- Delete PK --------';

DECLARE delete_cursor CURSOR FOR 
SELECT PK 
FROM PKstring
ORDER BY PK;

OPEN delete_cursor

FETCH NEXT FROM delete_cursor 
INTO @PK

WHILE @@FETCH_STATUS = 0
BEGIN
    DELETE PKstring where PK = @PK 

    FETCH NEXT FROM delete_cursor 
    INTO @PK
END 
CLOSE delete_cursor;
DEALLOCATE delete_cursor;
于 2013-05-07T14:58:28.287 回答
0

在 Oracle 中,您可以使用以下LOG ERRORS INTO选项:

样本数据设置:

create table parent (pid integer not null primary key);
create table child 
(
  cid integer not null primary key,
  pid integer not null references parent(pid)
);

insert into parent values (1);
insert into parent values (2);
insert into parent values (3);

insert into child values (1,1);
insert into child values (2,1);
insert into child values (3,2);

创建将记录所有不可删除行的表:

begin
  DBMS_ERRLOG.CREATE_ERROR_LOG('PARENT', 'ERR_LOG_PARENT');
end;
/

现在运行删除:

delete from parent
log errors into err_log_parent ('delete test')
reject limit unlimited;

SQLFiddle 示例:http ://sqlfiddle.com/#!4/d379c/1

DBMS_ERRLOG 手册:http ://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_errlog.htm选项
手册: http ://docs.oracle.com/cd/B28359_01/server.111/ b28286/statements_8005.htm#CEGCHDJFLOG ERRORS

于 2013-05-06T19:58:32.337 回答
0

在这种情况下,我通常会禁用 fk 约束,如果这不起作用,我通常会删除约束,清理数据,然后重新创建 fk。

这是有关如何操作的快速链接 http://www.mssqltips.com/sqlservertip/1376/disable-enable-drop-and-recreate-sql-server-foreign-keys/

于 2013-05-06T19:43:51.187 回答
0

没有什么灵丹妙药可以在所有平台上满足您的需求,但您可以编写一种适用于几乎任何 DBMS 的灵丹妙药。是的,我们是在 SQL Server 生产数据库上完成的。这不是一个单步过程,但您可以使用动态 SQL 或类似的方式轻松地自动化第二步。

回复:

您必须知道当前记录的每个父表。

是的,但是您可以编写代码来解决这个问题。使用 INFORMATION_SCHEMA 视图(SQL Server、MySQL)或数据库的等效视图为相关表生成删除语句。然后运行您生成的语句。

一个好的起点是 INFORMATION_SCHEMA.TABLES、INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS 和 INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE。

于 2013-05-07T04:29:31.830 回答