Как удалить все данные из таблицы, содержащей внешний ключ с собственной ссылкой - PullRequest
8 голосов
/ 20 марта 2010

У меня есть таблица, в которой определены отношения между сотрудниками.т.е.

EmpID   Name  SeniorId
-----------------------
1         A      NULL
2         B       1
3         C       1
4         D       3

и так далее ...

Где старший идентификатор - это внешний ключ, таблица первичного ключа которого совпадает со столбцом ссылки EmpId. Я хочу удалить все строки из этой таблицы, не удаляялюбое ограничение.Как я могу это сделать?

Удаление необходимо выполнить следующим образом: 4, 3, 2, 1

Как я могу это сделать

РЕДАКТИРОВАТЬ:

Ответ Джонни работает на меня, но какой из ответов более эффективен.

Ответы [ 5 ]

17 голосов
/ 20 марта 2010

Я не знаю, что-то упустил, но, может быть, вы можете попробовать это.

UPDATE employee SET SeniorID = NULL
DELETE FROM employee
3 голосов
/ 21 марта 2010

Если таблица очень большая (количество элементов в миллионах), и нет необходимости регистрировать транзакции DELETE, удаление ограничений и TRUNCATEing и воссоздание ограничений, безусловно, является наиболее эффективным способом. Кроме того, если в других таблицах есть внешние ключи (и в этом конкретном дизайне таблицы это может показаться так), все эти строки также должны быть сначала удалены во всех случаях.

Нормализация ничего не говорит о рекурсивных / иерархических / древовидных отношениях, поэтому я считаю, что это красная селедка в вашем ответе на предложение DVK разбить это на свою собственную таблицу - безусловно, жизнеспособным будет сделать вертикальное разбиение этой таблицы и также подумайте, можете ли вы воспользоваться этим, чтобы получить другие преимущества, перечисленные ниже. Как намекает DVK, в этом конкретном проекте я часто видел отдельную таблицу ссылок для записи собственных и других видов отношений. Это имеет многочисленные преимущества:

  • есть много ко многим вверх и вниз вместо многих к одному (необычно, но потенциально полезно)
  • отслеживание различных типов прямых отношений - менеджер, наставник, помощник, утверждающий заработной платы, утверждающий расходы, технический отчет - со строками в таблицах отношений и типов отношений вместо новых столбцов в таблице сотрудников
  • отслеживание изменений иерархий согласованным во времени способом (включая прекращенную историю иерархии сотрудников) путем включения активных индикаторов и дат вступления в силу в строках отношений - это полностью возможно только при нормализации отношения в его собственной таблице
  • нет NULL в SeniorID (фактически для любого ID) - это явное преимущество во избежание плохой логики, но NULL обычно появляются в представлениях, когда вам все равно нужно оставить соединение с таблицей отношений
  • лучшая специализированная стратегия индексирования - в отличие от добавления SeniorID к выбранным индексам, которые у вас уже есть на Employee (особенно с ростом числа типов отношений)

И, конечно, чем больше информации вы относитесь к этим отношениям, тем сильнее указывается, что само отношение заслуживает таблицы (т. Е. Это «отношение» в истинном смысле этого слова, используемого в реляционных базах данных, связанных с данные хранятся в отношении или таблице (связанной с первичным ключом), и, таким образом, обычная форма отношений может строго указывать, что таблица отношений создается вместо простого отношения внешнего ключа в таблице сотрудника.

Преимущества также включают в себя простой сценарий удаления:

DELETE FROM EmployeeRelationships;
DELETE FROM Employee;

Вы заметите поразительную эквивалентность принятому ответу здесь на SO, так как в вашем случае сотрудники без старших отношений имеют NULL - поэтому в этом ответе плакат сначала устанавливает все в NULL, чтобы устранить отношения, а затем удалить сотрудники.

Возможно, есть подходящее использование TRUNCATE в зависимости от ограничений (EmpployeeRelationships обычно может быть TRUNCATEd, поскольку его первичный ключ обычно является составным, а не внешним ключом в любой другой таблице).

2 голосов
/ 20 марта 2010

Попробуйте это

DELETE FROM employee;
1 голос
/ 20 марта 2010

Одним из решений является нормализация этого путем разделения "старших" отношений в отдельную таблицу. Ради общности сделайте вторую таблицу «empID1 | empID2 | relations_type».

За исключением этого, вы должны сделать это в цикле. Один из способов сделать это:

declare @count int
select @count=count(1) from table
while (@count > 0)
BEGIN
    delete employee WHERE NOT EXISTS
       (select 1 from employee 'e_senior' 
        where employee.EmpID=e_senior.SeniorID)
    select @count=count(1) from table
END
1 голос
/ 20 марта 2010

Внутри цикла запустите команду, которая удаляет все строки с EmpID без ссылки, пока не останется нулевых строк. Эта внутренняя команда DELETE может быть написана разными способами:

 DELETE FROM employee WHERE EmpID NOT IN (SELECT SeniorID FROM employee)

 DELETE FROM employee e1 WHERE NOT EXISTS
    (SELECT * FROM employee e2 WHERE e2.SeniorID = e.EmpID

и, возможно, третий, использующий JOIN, но я не знаком с синтаксисом SQL Server для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...