在SQL Server 2012中执行的测试显示,如果删除表中的单个记录将导致外键违规,则命令DELETE FROM dbo.TableName
将停止并返回错误。没有记录被删除。
假设未使用的记录是可以在不违反外键关系的情况下删除的记录。
假设所有记录都可通过不可为空的整数ID列进行唯一标识。
假设忽略可能导致副作用的功能是安全的,例如触发器或级联删除。
关于表格的其他内容,应该假设其记录和关系。 (例如:解决方案在这些参数中应该是通用的。)
是否存在以下形式删除未使用的父记录的解决方案:
备注:
请说明您的解决方案适用的RDBMS并且已经过测试。
答案 0 :(得分:0)
在这种情况下我通常做的是禁用fk约束,如果这不起作用,我通常会删除约束,清理数据,然后重新创建fk。
以下是有关如何操作的快速链接 http://www.mssqltips.com/sqlservertip/1376/disable-enable-drop-and-recreate-sql-server-foreign-keys/
答案 1 :(得分: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
LOG ERRORS
选项的手册:http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_8005.htm#CEGCHDJF
答案 2 :(得分:0)
在所有平台上都没有让你想要的神奇药丸,但你可以编写一个可以适应任何DBMS的药丸。是的,我们在SQL服务器生产数据库上完成了这项工作。这不是一个单步过程,但您可以使用动态SQL或其他方式轻松实现第二步的自动化。
重新:
您必须知道当前记录的每个父表。
是的,但你可以编写代表该代码的代码。使用INFORMATION_SCHEMA视图(SQL Server,MySQL)或数据库等效视图为相关表生成删除语句。然后运行您生成的语句。
一个好的起点是INFORMATION_SCHEMA.TABLES,INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS和INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE。
答案 3 :(得分: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;
答案 4 :(得分:-1)
为T-SQL编写并在SQL Server 2012中测试。
此解决方案只获取表的最大ID,循环遍历每条记录并尝试删除它。它仅适用于正整数ID。如果使用否定ID,也应该运行反向循环(从0到MIN)。
DECLARE @recordID int;
DECLARE @maximumRecordID int;
SELECT @maximumRecordID = Max(recordID) from dbo.TableName;
SET @recordID = 0;
WHILE( @recordID < @maximumRecordID )
BEGIN;
DELETE FROM dbo.TableName
WHERE recordID = @recordID;
SET @recordID = @recordID + 1;
END;
GO
我不一定建议任何人这样做,因为它依赖于DBMS来捕捉错误和一般的懒惰。
目前的实际应用是在我们的测试数据库中,用于正在进行的应用程序。数据库架构可以是易失性的,并由第三方控制,有时(但不是通常)使得保存脚本以供将来使用不切实际。除此之外,我不经常保存SQL脚本,因为我的大多数工作都是在C#中完成的。