Конфликт инструкции delete с ограничением same table reference

I’m trying to run this sql server statement:

delete C from Company C, Company D where C.CompanyID > 1310 AND C.CompanyID != D.ParentID

I’m getting the following sql error:

The DELETE statement conflicted with the SAME TABLE REFERENCE constraint «FK_Company_Company». The conflict occurred in database «DevelopmentDB», table «dbo.Company», column ‘ParentID’.

I checked and there are no companies where ParentID = CompanyID. I’m curious why my delete statement isn’t filtering out the companies that would cause this constraint to be broken.

asked Oct 18, 2012 at 17:49

Have you verified the results of your attempt with something like this to ensure that what you are attempting to delete is what you actually intend to delete?

select C.<field list> from Company C, Company D 
where C.CompanyID > 1310 AND C.CompanyID != D.ParentID

You might also try the delete statement using a sub query approach. It might make it easier to logically identify that the query you are running is what you are actually intending.

However, I always recommend testing with a select first for verification.

So running (if this is your intended results — modify if not):

Select <field list> FROM Company WHERE CompanyID > 1310 
AND CompanyID NOT IN 
    (SELECT ParentID FROM Company)

Before running (again, this is just an example).:

DELETE Company WHERE CompanyID > 1310 
AND CompanyID NOT IN 
    (SELECT ParentID FROM Company)

answered Oct 18, 2012 at 18:11

RThomasRThomas

10.9k2 gold badges50 silver badges64 bronze badges

3

I ran into this error («The DELETE statement conflicted with the SAME TABLE REFERENCE constraint …») in a situation where I had a table with columns and data like:

| RecordID | ParentRecordID | (other fields...) |
|----------|----------------|-------------------|
|        1 |           null |               ... |   
|        2 |              1 |               ... |

The error hit when my DELETE command tried to delete record 1 before record 2. The same-table foreign key constraint that had been set up on column ParentRecordID pointing at column RecordID prevented the delete: It wouldn’t have been valid for record 2 to be pointing at record 1 when record 1 didn’t exist anymore.

I worked around the problem by deleting records with a non-null ParentRecordID value first:

DELETE FROM myTable
WHERE ParentRecordID IS NOT null
  AND (other criteria...)

Then I could proceed to delete the remaining records with an additional DELETE statement:

DELETE FROM myTable
WHERE (other criteria...)

answered Apr 12, 2017 at 20:17

Jon SchneiderJon Schneider

27.1k25 gold badges151 silver badges180 bronze badges

1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

I’m trying to delete all users but getting the error:

Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_M02ArticlePersons_M06Persons". The conflict occurred in database "workdemo.no", table "dbo.M02ArticlePersons", column 'M06PersonId'.
The statement has been terminated.

The query:

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
WHERE ID > '13'
GO

Seems I need to use on delete cascade; but I’m stuck.

asked Apr 4, 2013 at 11:50

You don’t need to use the on delete cascade. Somebody (the schema design author) had made sure you cannot delete a person that is still referenced by an article. It succeeded, you were just trying to do this and was blocked, kudos to the designer.

Now go and talk with that somebody that designed the schema and knows the constraints and ask him how to properly delete the records you’re trying to delete, in the correct order and taking the proper precautions to keep the database consistent.

answered Apr 4, 2013 at 12:02

Remus RusanuRemus Rusanu

52k4 gold badges96 silver badges172 bronze badges

You have two real choices here, you can disable constraints on the table. This usually not a great idea as you can end up with a bad data condition if you’re messing with data that relates to other tables, but not know the full extent of your schema and it may suit your purposes:

ALTER TABLE [workdemo.no].[dbo].[M06Persons] NOCHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

Remember to turn the constraint back on after the delete with

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH CHECK CHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

The second choice would be to drop and re-add the constraint with the ON DELETE CASCADE option using:

ALTER TABLE [workdemo.no].[dbo].[M06Persons] DROP CONSTRAINT [FK_M02ArticlePersons_M06Persons]

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH NOCHECK ADD CONSTRAINT [FK_M02ArticlePersons_M06Persons] FOREIGN KEY(M06PersonId)
REFERENCES <parent table here> (<parent column here>)
ON DELETE CASCADE

Based on your FK name it looks like your parent table is M02ArticlePersons and the parent column is M06Persons.

If you did not author this schema please try to consider why the constraints may be present, and understand that violating them in this manner may have unintended side effects.

answered Apr 4, 2013 at 12:10

0

dbo.M02ArticlePersons table of column M06PersonId is reffered in another table.
So before delete statement, disable this relationships and try again

below is for disbling the foreign key

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
  WHERE ID > '13'
GO

and this is to enable it

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Hope this will work

answered Apr 4, 2013 at 12:04

1

There is another manual option too:

You can go to the child table and delete the child rows referenced by the parent key. Then you can delete the parent row. This is essentially what the cascade delete does. This way, you do not have to drop/recreate/alter your constraints.

answered Apr 4, 2013 at 14:49

StanleyJohnsStanleyJohns

5,9822 gold badges25 silver badges44 bronze badges

This little code will help for any table that you want to delete records from. It takes care of referential integrity as well …

Below code will generate DELETE statements .. Just specify the schema.table_Name

Declare @sql1 varchar(max)
      , @ptn1 varchar(200)
      , @ctn1 varchar(200)
      , @ptn2 varchar(200)
      , @ctn2 varchar(200)
--
SET @ptn1 = ''
--
SET @ctn1 = ''
--
SET @ptn2 = ''
--
SET @ctn2 = ''
--
SELECT @sql1 = case when (@ptn1 <> OBJECT_NAME (f.referenced_object_id)) then
                         COALESCE( @sql1 + char(10), '') + 'DELETE' + char(10) + ' ' + OBJECT_NAME (f.referenced_object_id) + ' FROM ' + OBJECT_NAME(f.parent_object_id) + ', '+OBJECT_NAME (f.referenced_object_id) + char(10) +' WHERE ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    else
                         @sql1 + ' AND ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    end + char(10)
     , @ptn1 = OBJECT_NAME (f.referenced_object_id)
     , @ptn2  = object_name(f.parent_object_id)
FROM   sys.foreign_keys AS f
       INNER JOIN
       sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id
WHERE  f.parent_object_id = OBJECT_ID('dbo.M06Persons'); -- CHANGE here schema.table_name
--
print  '--Table Depended on ' + @ptn2 + char(10) + @sql1

answered Apr 4, 2013 at 19:56

Kin ShahKin Shah

62.4k6 gold badges122 silver badges242 bronze badges

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

01.11.2023

Думаю каждый, кто начинает работать с планами обслуживания в Microsoft SQL сервере, столкнётся с ошибкой при удалении ненужного вам плана.
И звучит она примерно так: 
Действие Удалить завершилось неудачно для объекта Задание

Конфликт инструкции DELETE с ограничением REFERENCE ... (ошибка: 547)

Эту проблему мы с вами и будем решать.

Итак, проблема неочевидна, на скриншоте страшноватые надписи с наименованием таблиц и каких-то параметров, ничего не понятно, а удалить план хочется.
Сама ошибка выглядит примерно так:

84651384313.JPG

Вкратце: Действие Удалить завершилось неудачно для объекта Задание

Конфликт инструкции DELETE с ограничением REFERENCE … (ошибка: 547)

Для удаления данного задания нам понадобится открыть шелл MS SQL сервера, где мы сможем выполнять команды. Для этого закрываем окна с ошибкой и кликаем на верхней панели «Создать запрос»:

2248646513.JPG

В правой части у нас появляется форма, где мы вводим следующую команду:
select * from msdb.dbo.sysmaintplan_plans

И нажимаем сверху на кнопку «Выполнить»:

84635418643.JPG

После нажатия на кнопку «Выполнить», снизу окна у нас появится информация о текущих планах обслуживания и будет столбец с указанием ID каждого плана, он нам и нужен:

1145465135.JPG

В списке мы находим название того, плана, что мы хотим удалить и видим его ID, в нашем случае это задание под номером 2 с ID: A3550947-8DDC-4D25-8E97-05DC17FB53DC. Копируем этот ID и формируем следующую команду в шелле SQL, предыдущую команду удаляем.
Получаем примерно следующее:

delete from msdb.dbo.sysmaintplan_subplans where plan_id = 'A3550947-8DDC-4D25-8E97-05DC17FB53DC'

Где в конце команды в кавычки мы вставляем скопированный ID. Нажимаем кнопку «Выполнить», снизу окна появится надпись «Запрос успешно выполнен». Отлично.
Ну и для положительного решения нашего вопроса выполняем второй и последний запрос в шелле (не забываем удалять предыдущую команду):

delete from msdb.dbo.sysmaintplan_plans where id = 'A3550947-8DDC-4D25-8E97-05DC17FB53DC'
Опять жмём «Выполнить» и опять должны увидеть надпись «Запрос успешно выполнен». 
Отлично. Теперь мы спокойно можем удалить наше задание без всяких ошибок!

Напоследок хочется отметить один момент

: если задание создано через «Мастер планов обслуживания», то задания нужно удалять именно через каталог объектов «Управление» — «Планы обслуживания», в этом случае ошибки изначально не будет. Если же задание создавалось вручную, то, скорее всего, получите ошибку и решить её можно вышеприведённым методом.

На этом всё, удачи в администрировании!


Re: Проблемы с триггером каскадного удаления

От: Аноним

 
Дата:  12.12.11 13:54
Оценка:

3 (1)

Здравствуйте, spy__, Вы писали:

_>Проблема в том, что если выполнить запрос

__>

__>delete from Table4 where id = 2;
__>

__>то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?

Тело триггера по идее должно быть таким:

begin
    delete from Table4 WHERE x in (select id from deleted)
    delete from Table4 WHERE id in (select id from deleted)
end;


Re[3]: Проблемы с триггером каскадного удаления

От:

Sshur

Россия

http://shurygin-sergey.livejournal.com
Дата:  12.12.11 13:55
Оценка:

3 (1)

Здравствуйте, spy__, Вы писали:

S>>Ну дык триггер то istead of. Данные, которые в deleted из таблицы не удаляются. Делайте триггер after или удаляйте руками.


__>1. for/after я уже пробовал. При выполнении запроса на удаление:

__>

Сообщение 547, уровень 16, состояние 0, строка 1
__>Конфликт инструкции DELETE с ограничением SAME TABLE REFERENCE «FK_TABLE4_2». Конфликт произошел в базе данных «TEST1», таблица «dbo.Table4», column ‘x’.
__>Выполнение данной инструкции было прервано.


__>Это подкидывает свинью наличие FK.

Ну да. Вообще имхо плохая идея делать такое каскадное удаление через триггер. Надо сначала удалить все записи, на которые есть FK, а потом PK

__>2. «Удаляйте руками». Можно конкретный пример? Т.к. у меня само создание триггера ругается на то, что не удается обновить deleted и inserted (это когда пробую выполнить больше одного запроса в триггере).

Как-то так


create trigger casc_table4_1 on Table4 instead of delete as
begin
delete from Table4 WHERE x in (select id from deleted)

delete from Table4 WHERE id in (select id from deleted)
end;

У меня пример прошел успешно

Шурыгин Сергей

«Не следует преумножать сущности сверх необходимости» (с) Оккам


Проблемы с триггером каскадного удаления

От:

spy__

 
Дата:  12.12.11 13:23
Оценка:

Добрый день.

У меня есть MS SQL 2008 и табличка такого плана:

create table Table4
(
id integer not null identity(1, 1) constraint PK_Table4_1 primary key,
x integer constraint FK_Table4_2 references Table4(id) on delete no action on update no action
);

Данные в ней, скажем, такие:

id | x
2 | null
3 | 2
4 | 2
5 | 2

Под все это дело я хочу организовать триггер для удаления записей. На данный момент родил такую штуку:

create trigger casc_table4_1 on Table4 instead of delete as
begin
delete from Table4 WHERE x in (select id from deleted)
end;

Проблема в том, что если выполнить запрос

delete from Table4 where id = 2;

то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?


Re: Проблемы с триггером каскадного удаления

От:

Sshur

Россия

http://shurygin-sergey.livejournal.com
Дата:  12.12.11 13:38
Оценка:

Здравствуйте, spy__, Вы писали:

__>Проблема в том, что если выполнить запрос

__>

__>delete from Table4 where id = 2;
__>

__>то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?

Ну дык триггер то istead of. Данные, которые в deleted из таблицы не удаляются. Делайте триггер after или удаляйте руками.

Шурыгин Сергей

«Не следует преумножать сущности сверх необходимости» (с) Оккам


Re[2]: Проблемы с триггером каскадного удаления

От:

spy__

 
Дата:  12.12.11 13:46
Оценка:

Здравствуйте, Sshur, Вы писали:

S>Здравствуйте, spy__, Вы писали:


__>>Проблема в том, что если выполнить запрос

__>>

__>>delete from Table4 where id = 2;
__>>

__>>то удалится все, кроме строки 2 | null. А ведь изначально цель удалить именно ее + всех, кто из этой таблицы на нее ссылается. В чем может быть косяк?

S>Ну дык триггер то istead of. Данные, которые в deleted из таблицы не удаляются. Делайте триггер after или удаляйте руками.

1. for/after я уже пробовал. При выполнении запроса на удаление:

Сообщение 547, уровень 16, состояние 0, строка 1
Конфликт инструкции DELETE с ограничением SAME TABLE REFERENCE «FK_TABLE4_2». Конфликт произошел в базе данных «TEST1», таблица «dbo.Table4», column ‘x’.
Выполнение данной инструкции было прервано.

Это подкидывает свинью наличие FK.

2. «Удаляйте руками». Можно конкретный пример? Т.к. у меня само создание триггера ругается на то, что не удается обновить deleted и inserted (это когда пробую выполнить больше одного запроса в триггере).


Re[4]: Проблемы с триггером каскадного удаления

От:

spy__

 
Дата:  12.12.11 14:11
Оценка:

Аноним, Sshur, благодарю, господа. Это рабочий вариант.

Вообще очень мутные вещи творятся с этими FK и триггерами. Т.е. таким же образом (instead of) нужно поступать и в ситуации, когда есть вторая таблица с not null FK на id первой таблицы: удалять сначала из второй, а потом и из первой.


Re[5]: Проблемы с триггером каскадного удаления

От:

Sshur

Россия

http://shurygin-sergey.livejournal.com
Дата:  12.12.11 14:33
Оценка:

Здравствуйте, spy__, Вы писали:

__>Аноним, Sshur, благодарю, господа. Это рабочий вариант.


__>Вообще очень мутные вещи творятся с этими FK и триггерами. Т.е. таким же образом (instead of) нужно поступать и в ситуации, когда есть вторая таблица с not null FK на id первой таблицы: удалять сначала из второй, а потом и из первой.

Для второй таблицы на FK можно поставить on cascade delete

Если вы все чистите, то можно временно «выключить» связь (alter table nocheck constaraint …)

Шурыгин Сергей

«Не следует преумножать сущности сверх необходимости» (с) Оккам


Re[6]: Проблемы с триггером каскадного удаления

От:

spy__

 
Дата:  12.12.11 14:37
Оценка:

S>Для второй таблицы на FK можно поставить on cascade delete

S>Если вы все чистите, то можно временно «выключить» связь (alter table nocheck constaraint …)

Можно, но, к сожалению, не везде. В некоторых случаях MS SQL ругается на появление множественных каскадных путей, а исправлять структуру БД нельзя.


Re[7]: Проблемы с триггером каскадного удаления

От:

Sshur

Россия

http://shurygin-sergey.livejournal.com
Дата:  12.12.11 14:51
Оценка:

Здравствуйте, spy__, Вы писали:

S>>Для второй таблицы на FK можно поставить on cascade delete


S>>Если вы все чистите, то можно временно «выключить» связь (alter table nocheck constaraint …)


__>Можно, но, к сожалению, не везде. В некоторых случаях MS SQL ругается на появление множественных каскадных путей, а исправлять структуру БД нельзя.

Ну да. Эта проверка на каскадное удаление в MS SQL меня тоже иногда раздражает

Шурыгин Сергей

«Не следует преумножать сущности сверх необходимости» (с) Оккам

  • Переместить
  • Удалить
  • Выделить ветку

Пока на собственное сообщение не было ответов, его можно удалить.

From Stack Overflow:

I have an SQL Server table defined as below:

TestComposite

id (PK) siteUrl (PK) name parentId
1 site1 Item1 NULL
2 site1 Item2 NULL
3 site1 Folder1 NULL
4 site1 Folder1.Item1 3
5 site1 Folder1.Item2 3
6 site1 Folder1.Folder1 3
7 site1 Folder1.Folder1.Item1 6

Items and folders are stored inside the same table

If an item is inside a folder, the parentID column is the id of the folder.

I would like to be able to DELETE CASCADE items/folders when I delete a folder.

I tried to define a constraint similar to:

ALTER TABLE [TestComposite]
ADD CONSTRAINT fk_parentid
FOREIGN KEY (ParentID, SiteUrl)
REFERENCES [TestComposite] (ID, SiteUrl) ON DELETE CASCADE

, but it gives me this error:

Introducing FOREIGN KEY constraint 'fk_parentid' on table 'TestComposite' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

SQL Server does support chained CASCADE updates, but does not allow one table to participate more that once in a chain (i. e. does not allow loops).

SQL Server, unlike most other engines, optimizes cascading DML operations to be set-based which requires building a cycle-free DML order (which you can observe in the execution plan). With the loops, that would not be possible.

However, it is possible to define such a constraint without cascading operations, and with a little effort it is possible to delete a whole tree branch at once.

Let’s create a sample table:

Table creation details

This table contains 50,000 records forming a hierarchy.

If we try to delete an entry that has some children, we’ll fail:

DELETE
FROM    [20100303_cascade].TestComposite
WHERE   id = 42
AND siteUrl = 'site1'
Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the SAME TABLE REFERENCE constraint "fk_TestComposite_self". The conflict occurred in database "test", table "20100303_cascade.TestComposite".
The statement has been terminated.

To delete an item and all of its children, we should build a hierarchical query to retrieve the whole branch, and delete the branch all at once.

To do it, we just semi-join the table to the results of the recursive CTE:

WITH    q AS
(
SELECT  id, siteUrl
FROM    [20100303_cascade].TestComposite
WHERE   id = 42
AND siteUrl = 'site1'
UNION ALL
SELECT  tc.id, tc.siteUrl
FROM    q
JOIN    [20100303_cascade].TestComposite tc
ON      tc.parentID = q.id
AND tc.siteUrl = q.siteUrl
)
DELETE
FROM    [20100303_cascade].TestComposite
OUTPUT  DELETED.*
WHERE   EXISTS
(
SELECT  id, siteUrl
INTERSECT
SELECT  id, siteUrl
FROM    q
)

View query results

We see that the whole branch of 31 records was deleted all at once, without violating the FOREIGN KEY.

Unlike some other systems, we don’t have to worry about the order the records are deleted, since all SQL Server referential constraints are deferred till the end of the query.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Ремонт кузова автомобиля стекловолокном своими руками пошаговая инструкция
  • Инструкция tarrington house микроволновая печь инструкция
  • Диклофенак гель 5 процентный инструкция по применению взрослым при боли в спине
  • Панцеф 400 мг инструкция по применению детям суспензия
  • Тромексин для кроликов инструкция по применению