如何删除可以删除的每一行?

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