2015-05-01 1 views
1

Есть ли способ в SQL Server удалять каждую удаляемую строку (не имеет внешних ключей, предотвращающих удаление), не имея необходимости знать каждую ссылку на внешний ключ?Как удалить каждую строку, которую можно удалить?

Я знаю, что я могу проверить с WHERE ID NOT IN (..) или LEFT OUTER JOIN для каждого ограничения, но есть что-то вроде

DELETE * FROM MyTable WITH CONTINUE_ON_ERROR 

что бы просто попытаться удалить каждую запись, и если происходит ошибка игнорировать его и продолжить со следующей запись без возврата транзакции?

+5

Нет, такой функции нет. Если вы хотите удалить, это * ваша работа *, чтобы убедиться, что эти строки не указаны где-то –

+0

Похоже на странный запрос. Откуда вы знаете, что вы не удаляете FK, который не используется сегодня, но вам может понадобиться это в будущем? – Paparazzi

+0

Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

ответ

1

Если вам действительно нужно это сделать, проверьте каждое ограничение.

Вы можете использовать курсор для прокрутки каждой записи и обернуть его в try catch , но это ужасно и причинит вам боль и несчастье, и кто бы ни поддерживал ваше приложение/базу данных.

3

Вы можете сделать это с помощью cursortry 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 
+0

Это то, что пришло мне в голову, но знайте, что он будет медленным для любой таблицы размера. –

2

Я написал несколько SQL, который будет записывать все стыки для вас, то вернуться, где нет матча для объединения. Просто укажите на свой стол. Затем, если вы хотите удалить, то удалите из своей таблицы, где 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