Ошибка Sql при обновлении: инструкция UPDATE противоречила ограничениям FOREIGN KEY

У меня есть таблица под названием patient_address, которая ссылается на ключ PK в таблице patient. Но если я попытаюсь выполнить одно из следующих утверждений:

update patient set id_no='7008255601088' where id_no='8008255601088'
update patient_address set id_no='7008255601088' where id_no='8008255601088'

Я получаю это сообщение об ошибке:

"Операция UPDATE противоречила ограничению REFERENCE" FK__patient_a__id_no__27C3E46E ". Конфликт произошел в базе данных" PMS ", таблица" dbo.patient_address ", столбец" id_no "." Или "Операция UPDATE противоречит ограничению FOREIGN KEY" FK__patient_a__id_no__27C3E46E ". Конфликт произошел в базе данных" PMS ", таблица" dbo.patient ", столбец" id_no ".".

Знает ли кто-нибудь о возможной причине? Спасибо.

Ответ 1

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

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

Щелкните правой кнопкой мыши свой внешний ключ и выберите Изменить. В диалоговом окне "Отношение внешних ключей" в настройках INSERT и UPDATE установите правило UPDATE на Cascade:

enter image description here

Вы также можете установить правило с помощью T-SQL:

ALTER TABLE YourTable
DROP Constraint Your_FK
GO

ALTER TABLE YourTable
ADD CONSTRAINT [New_FK_Constraint]
FOREIGN KEY (YourColumn) REFERENCES ReferencedTable(YourColumn)
ON DELETE CASCADE ON UPDATE CASCADE
GO 

Надеюсь, что это поможет

Ответ 2

В MySQL

set foreign_key_checks=0;

UPDATE patient INNER JOIN patient_address 
ON patient.id_no=patient_address.id_no 
SET patient.id_no='8008255601088', 
patient_address.id_no=patient.id_no 
WHERE patient.id_no='7008255601088';

Обратите внимание, что foreign_key_checks только временно устанавливает внешний ключ, проверяющий false. Поэтому он должен выполняться каждый раз перед операцией обновления. Мы устанавливаем его 0, как если бы мы сначала обновляли родительский элемент, тогда это не будет разрешено, поскольку у ребенка может быть уже это значение. И если мы сначала обновим пароль, это также будет запрещено, поскольку родитель может не иметь того значения, из которого мы обновляем. Поэтому нам нужно установить проверку внешнего ключа. Другое дело, что если вы используете инструмент командной строки для использования этого запроса, тогда позаботьтесь о том, чтобы указать пробелы, где я помещаю новую строку или ENTER в код. Поскольку командная строка берет его в одной строке, может случиться так, что два слова будут вставляться как patient_addressON, которые создают синтаксическую ошибку.

Ответ 3

Я думаю, если вы измените id_no, некоторые внешние ключи ничего не будут ссылаться, что приведет к нарушению ограничения. Вы можете добавить initialy deffered к внешним ключам, поэтому ограничения проверяются при совершении изменений

Ответ 4

Если столбец dbo.patient_address.id_no позволяет NULL, вы можете использовать это решение:

SET XACT_ABORT ON;
BEGIN TRANSACTION;

-- I assmume that [id] is the primary key of patient_address table (single column key)
-- replace the name of [id] column with the name of PK column from patient_address table
-- replace INT data type with the proper type
DECLARE @RowsForUpdate TABLE([id] INT PRIMARY KEY); 
UPDATE patient_address 
SET id_no = NULL
OUTPUT deleted.[id] INTO @RowsForUpdate ([id])
WHERE id_no='8008255601088'

UPDATE patient 
SET id_no='7008255601088' 
WHERE id_no='8008255601088'

UPDATE patient_address 
SET id_no='7008255601088' 
WHERE [id] IN (SELECT u.[id] FROM @RowsForUpdate u)

COMMIT;

Ответ 5

Я не изменил бы ограничения, вместо этого вы можете вставить новую запись в таблицу_1 с помощью первичного ключа (id_no = 7008255601088). Это не что иное, как повторяющаяся строка id_no = 8008255601088. так что теперь patient_address с ограничением внешнего ключа (id_no = 8008255601088) можно обновить, чтобы указать на запись с новым ID (ID, который необходимо обновить), который обновляется id_no - id_no = 7008255601088.

Затем вы можете удалить начальную строку первичного ключа с id_no = 7008255601088.

Три шага включают:

  • Вставить повторяющуюся строку для нового id_no
  • Обновить Patient_address, чтобы указать на новую повторяющуюся строку
  • Удалите строку со старым id_no

Ответ 6

Это было решение для меня:

-- Check how it is now
select * from patient
select * from patient_address

-- Alter your DB
alter table patient_address nocheck constraint FK__patient_a__id_no__27C3E46E
update patient 
set id_no='7008255601088'
where id_no='8008255601088'

alter table patient_address nocheck constraint FK__patient_a__id_no__27C3E46E
update patient_address 
set id_no='7008255601088'
where id_no='8008255601088'

-- Check how it is now
select * from patient
select * from patient_address

Ответ 7

Иногда это происходит, когда вы пытаетесь Insert/Update объект, в то время как foreign key который вы пытаетесь Insert/Update самом деле не существует. Поэтому убедитесь, что foreign key существует, и повторите попытку.

Ответ 8

Причина, как говорит @MilicaMedic. Альтернативное решение - отключить все ограничения, выполнить обновление, а затем снова включить ограничения, как показано ниже. Очень полезно при обновлении тестовых данных в тестовых средах.

exec sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

update patient set id_no='7008255601088' where id_no='8008255601088'
update patient_address set id_no='7008255601088' where id_no='8008255601088'

exec sp_MSforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

Источник:

fooobar.com/questions/12205/...

Ответ 9

ALTER TABLE [UserStore] 
NOCHECK CONSTRAINT FK_UserStore_User_UserId

ALTER TABLE [UserIdentity]
NOCHECK CONSTRAINT  FK_UserIdentity_User_UserId

BEGIN TRAN

UPDATE  [user] 
SET Id = 10
WHERE Id = 9

UPDATE  [dbo].[UserStore]
SET UserId = 10
WHERE UserId = 9

UPDATE  [dbo].UserIdentity
SET UserId = 10
WHERE UserId = 9

COMMIT TRAN

ALTER TABLE [UserStore] 
CHECK CONSTRAINT FK_UserStore_User_UserId

ALTER TABLE UserIdentity 
CHECK CONSTRAINT FK_UserIdentity_User_UserId