如何删除可以删除的每一行?
How to delete every row that can be deleted?
在 SQL 服务器中是否有一种方法可以删除每一行可删除的行(没有外键阻止删除)而不必知道每个外键引用?
我知道我可以用 WHERE ID NOT IN (..)
或 LEFT OUTER JOIN
检查每个约束,但是是否有类似
的东西
DELETE * FROM MyTable WITH CONTINUE_ON_ERROR
那会简单地尝试删除每条记录,如果发生错误则忽略它并继续处理下一条记录而不回滚事务?
如果您确实需要这样做,请检查每个约束。
您可以使用游标遍历每个条目并将其包装在 try catch 中但是这太可怕了,会给您和任何必须支持您的人带来痛苦和痛苦应用程序/数据库。
您可以通过 cursor
使用 try catch
块来做到这一点:
DECLARE @id int
DECLARE curs CURSOR FAST_FORWARD
FOR
SELECT ID
FROM MyTable
OPEN curs
FETCH NEXT FROM curs INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
DELETE FROM MyTable
WHERE id = @id
END TRY
BEGIN CATCH
END CATCH
FETCH NEXT FROM curs INTO @id
END
CLOSE curs
DEALLOCATE curs
我写了一些 SQL 可以为您编写所有连接,然后 return 没有匹配的连接。只需将它指向您的 table。然后,如果您想删除,请从 table 中删除 pk_col IN(我动态创建的查询)
DECLARE @TableName VARCHAR(100) = 'yourTable',
@LeftJoins VARCHAR(MAX),
@WherePredicates VARCHAR(MAX);
WITH CTE_FK_PK
AS
(
SELECT
FK_Table = FK.TABLE_NAME,
FK_Column = CU.COLUMN_NAME,
PK_Table = PK.TABLE_NAME,
PK_Column = PT.COLUMN_NAME
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN (
SELECT
i1.TABLE_NAME,
i2.COLUMN_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
WHERE
i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
) PT
ON PT.TABLE_NAME = PK.TABLE_NAME
WHERE PK.TABLE_NAME = @TableName
)
SELECT @LeftJoins = COALESCE(@LeftJoins + CHAR(10),'') + 'LEFT JOIN ' + FK_Table + ' ON ' + FK_Table + '.' + FK_Column + ' = ' + PK_Table + '.' + PK_Column,
@WherePredicates = COALESCE(@WherePredicates + CHAR(10) + 'AND ','') + FK_Table + '.' + FK_Column + ' IS NULL '
FROM CTE_FK_PK
SELECT
'SELECT pk_col
FROM ' + @TableName + '
' + @LeftJoins + '
WHERE ' + @WherePredicates
在 SQL 服务器中是否有一种方法可以删除每一行可删除的行(没有外键阻止删除)而不必知道每个外键引用?
我知道我可以用 WHERE ID NOT IN (..)
或 LEFT OUTER JOIN
检查每个约束,但是是否有类似
DELETE * FROM MyTable WITH CONTINUE_ON_ERROR
那会简单地尝试删除每条记录,如果发生错误则忽略它并继续处理下一条记录而不回滚事务?
如果您确实需要这样做,请检查每个约束。
您可以使用游标遍历每个条目并将其包装在 try catch 中但是这太可怕了,会给您和任何必须支持您的人带来痛苦和痛苦应用程序/数据库。
您可以通过 cursor
使用 try catch
块来做到这一点:
DECLARE @id int
DECLARE curs CURSOR FAST_FORWARD
FOR
SELECT ID
FROM MyTable
OPEN curs
FETCH NEXT FROM curs INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
DELETE FROM MyTable
WHERE id = @id
END TRY
BEGIN CATCH
END CATCH
FETCH NEXT FROM curs INTO @id
END
CLOSE curs
DEALLOCATE curs
我写了一些 SQL 可以为您编写所有连接,然后 return 没有匹配的连接。只需将它指向您的 table。然后,如果您想删除,请从 table 中删除 pk_col IN(我动态创建的查询)
DECLARE @TableName VARCHAR(100) = 'yourTable',
@LeftJoins VARCHAR(MAX),
@WherePredicates VARCHAR(MAX);
WITH CTE_FK_PK
AS
(
SELECT
FK_Table = FK.TABLE_NAME,
FK_Column = CU.COLUMN_NAME,
PK_Table = PK.TABLE_NAME,
PK_Column = PT.COLUMN_NAME
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK
ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK
ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN (
SELECT
i1.TABLE_NAME,
i2.COLUMN_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2
ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
WHERE
i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
) PT
ON PT.TABLE_NAME = PK.TABLE_NAME
WHERE PK.TABLE_NAME = @TableName
)
SELECT @LeftJoins = COALESCE(@LeftJoins + CHAR(10),'') + 'LEFT JOIN ' + FK_Table + ' ON ' + FK_Table + '.' + FK_Column + ' = ' + PK_Table + '.' + PK_Column,
@WherePredicates = COALESCE(@WherePredicates + CHAR(10) + 'AND ','') + FK_Table + '.' + FK_Column + ' IS NULL '
FROM CTE_FK_PK
SELECT
'SELECT pk_col
FROM ' + @TableName + '
' + @LeftJoins + '
WHERE ' + @WherePredicates