Отключить и включить ограничения внешнего ключа, поддерживаемые в SQL Server? Или мой единственный вариант: drop
, а затем create
Ограничения?Как можно ограничить внешние ключи с помощью T-SQL?
ответ
Если вы хотите, чтобы отключить все ограничения в базе данных просто запустите этот код:
-- disable all constraints
EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
Чтобы включить их обратно, выполните: (печать не является обязательным, конечно, и это просто перечисление таблиц)
-- enable all constraints
exec sp_MSforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
Я считаю это полезным при заселении данные из одной базы данных в другую. Это гораздо лучший подход, чем снижение ограничений. Как вы уже упоминали, это пригодится при удалении всех данных в базе данных и их повторной загрузке (скажем, в тестовой среде).
Если вы удаляете все данные, вы можете найти this solution, чтобы быть полезным.
Также иногда удобно отключать все триггеры, вы можете увидеть полное решение here.
http://www.sqljunkies.com/WebLog/roman/archive/2005/01/30/7037.aspx
-- Disable all table constraints
ALTER TABLE MyTable NOCHECK CONSTRAINT ALL
-- Enable all table constraints
ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT ALL
-- Disable single constraint
ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint
-- Enable single constraint
ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint
хорошая находка, но обратите внимание, что вы по-прежнему не можете обрезать таблицу без удаления ограничений внешнего ключа – 2008-10-01 18:41:25
, и вам также нужно будет знать, что когда вы снова включаете ограничения и выполняете проверку целостности данных, ваши данные могут терпеть неудачу и исправить подобная проблема может быть кошмаром, если неудачные данные находятся в конце длинной строки связанных ограничений. – Jimoc 2008-10-01 18:44:13
my sql server 2008 просит проверить чек, а не проверять и проверять nocheck – Omu 2011-03-10 13:48:00
В стандарте SQL-92 допускается, чтобы константа была объявлена как DEFERRABLE, чтобы ее можно было отложить (неявно или явно) в рамках транзакции. К сожалению, SQL Server по-прежнему не хватает этой функциональности SQL-92.
Для меня изменение ограничения на NOCHECK сродни изменению структуры базы данных на лету - исключение ограничений - и что-то, чего следует избегать (например, пользователям требуются повышенные привилегии).
--Drop and Recreate Foreign Key Constraints
SET NOCOUNT ON
DECLARE @table TABLE(
RowId INT PRIMARY KEY IDENTITY(1, 1),
ForeignKeyConstraintName NVARCHAR(200),
ForeignKeyConstraintTableSchema NVARCHAR(200),
ForeignKeyConstraintTableName NVARCHAR(200),
ForeignKeyConstraintColumnName NVARCHAR(200),
PrimaryKeyConstraintName NVARCHAR(200),
PrimaryKeyConstraintTableSchema NVARCHAR(200),
PrimaryKeyConstraintTableName NVARCHAR(200),
PrimaryKeyConstraintColumnName NVARCHAR(200)
)
INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName)
SELECT
U.CONSTRAINT_NAME,
U.TABLE_SCHEMA,
U.TABLE_NAME,
U.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE = 'FOREIGN KEY'
UPDATE @table SET
PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME
FROM
@table T
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintTableSchema = TABLE_SCHEMA,
PrimaryKeyConstraintTableName = TABLE_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintColumnName = COLUMN_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME
--SELECT * FROM @table
--DROP CONSTRAINT:
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
DROP CONSTRAINT ' + ForeignKeyConstraintName + '
GO'
FROM
@table
--ADD CONSTRAINT:
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ')
GO'
FROM
@table
GO
Я согласен с вами, Хэмлин. Когда вы передаете данные с помощью SSIS или когда хотите реплицировать данные, представляется необходимым временно отключить или отключить ограничения внешнего ключа, а затем снова включить или воссоздать их. В этих случаях ссылочная целостность не является проблемой, поскольку она уже поддерживается в исходной базе данных. Поэтому вы можете быть уверены в этом.
SET NOCOUNT ON
DECLARE @table TABLE(
RowId INT PRIMARY KEY IDENTITY(1, 1),
ForeignKeyConstraintName NVARCHAR(200),
ForeignKeyConstraintTableSchema NVARCHAR(200),
ForeignKeyConstraintTableName NVARCHAR(200),
ForeignKeyConstraintColumnName NVARCHAR(200),
PrimaryKeyConstraintName NVARCHAR(200),
PrimaryKeyConstraintTableSchema NVARCHAR(200),
PrimaryKeyConstraintTableName NVARCHAR(200),
PrimaryKeyConstraintColumnName NVARCHAR(200),
UpdateRule NVARCHAR(100),
DeleteRule NVARCHAR(100)
)
INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName)
SELECT
U.CONSTRAINT_NAME,
U.TABLE_SCHEMA,
U.TABLE_NAME,
U.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE = 'FOREIGN KEY'
UPDATE @table SET
T.PrimaryKeyConstraintName = R.UNIQUE_CONSTRAINT_NAME,
T.UpdateRule = R.UPDATE_RULE,
T.DeleteRule = R.DELETE_RULE
FROM
@table T
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintTableSchema = TABLE_SCHEMA,
PrimaryKeyConstraintTableName = TABLE_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintColumnName = COLUMN_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME
--SELECT * FROM @table
SELECT '
BEGIN TRANSACTION
BEGIN TRY'
--DROP CONSTRAINT:
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
DROP CONSTRAINT ' + ForeignKeyConstraintName + '
'
FROM
@table
SELECT '
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RAISERROR(''Operation failed.'', 16, 1)
END CATCH
IF(@@TRANCOUNT != 0)
BEGIN
COMMIT TRANSACTION
RAISERROR(''Operation completed successfully.'', 10, 1)
END
'
--ADD CONSTRAINT:
SELECT '
BEGIN TRANSACTION
BEGIN TRY'
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ') ON UPDATE ' + UpdateRule + ' ON DELETE ' + DeleteRule + '
'
FROM
@table
SELECT '
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RAISERROR(''Operation failed.'', 16, 1)
END CATCH
IF(@@TRANCOUNT != 0)
BEGIN
COMMIT TRANSACTION
RAISERROR(''Operation completed successfully.'', 10, 1)
END'
GO
Чтобы отключить ограничение, вы должны изменить таблицу с помощью NOCHECK
ALTER TABLE [TABLE_NAME] NOCHECK CONSTRAINT [ALL|CONSTRAINT_NAME]
Для включения необходимо использовать двойной CHECK
ALTER TABLE [TABLE_NAME] WITH CHECK CHECK CONSTRAINT [ALL|CONSTRAINT_NAME]
- Обратите внимание на двойной ПРОВЕРКА ПРОВЕРКА при включении.
- ВСЕ средства для всех ограничений в таблице.
После завершения, если вам нужно проверить статус, используйте этот скрипт, чтобы указать статус ограничения.Будет очень полезна:
Ваш лучший вариант - DROP и CREATE ограничения внешнего ключа.
Я не нашел примеров в этом сообщении, которые бы работали для меня как «как есть», никто бы не работал, если внешние ключи ссылаются на разные схемы, а другая не работает, если внешний ключ ссылается на несколько столбцов. Этот сценарий рассматривает как множественные схемы, так и несколько столбцов для каждого внешнего ключа.
Вот скрипт, который генерирует «ADD Constraint» заявления, для нескольких столбцов будет разделять их запятой (не забудьте сохранить этот вывод перед выполнением операторы DROP):
PRINT N'-- CREATE FOREIGN KEY CONSTRAINTS --';
SET NOCOUNT ON;
SELECT '
PRINT N''Creating '+ const.const_name +'...''
GO
ALTER TABLE ' + const.parent_obj + '
ADD CONSTRAINT ' + const.const_name + ' FOREIGN KEY (
' + const.parent_col_csv + '
) REFERENCES ' + const.ref_obj + '(' + const.ref_col_csv + ')
GO'
FROM (
SELECT QUOTENAME(fk.NAME) AS [const_name]
,QUOTENAME(schParent.NAME) + '.' + QUOTENAME(OBJECT_name(fkc.parent_object_id)) AS [parent_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcP.parent_object_id, fcp.parent_column_id))
FROM sys.foreign_key_columns AS fcP
WHERE fcp.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [parent_col_csv]
,QUOTENAME(schRef.NAME) + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)) AS [ref_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcR.referenced_object_id, fcR.referenced_column_id))
FROM sys.foreign_key_columns AS fcR
WHERE fcR.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [ref_col_csv]
FROM sys.foreign_key_columns AS fkc
INNER JOIN sys.foreign_keys AS fk ON fk.object_id = fkc.constraint_object_id
INNER JOIN sys.objects AS oParent ON oParent.object_id = fkc.parent_object_id
INNER JOIN sys.schemas AS schParent ON schParent.schema_id = oParent.schema_id
INNER JOIN sys.objects AS oRef ON oRef.object_id = fkc.referenced_object_id
INNER JOIN sys.schemas AS schRef ON schRef.schema_id = oRef.schema_id
GROUP BY fkc.parent_object_id
,fkc.referenced_object_id
,fk.NAME
,fk.object_id
,schParent.NAME
,schRef.NAME
) AS const
ORDER BY const.const_name
Вот скрипт, который генерирует "DROP Constraint" заявления:
PRINT N'-- DROP FOREIGN KEY CONSTRAINTS --';
SET NOCOUNT ON;
SELECT '
PRINT N''Dropping ' + fk.NAME + '...''
GO
ALTER TABLE [' + sch.NAME + '].[' + OBJECT_NAME(fk.parent_object_id) + ']' + ' DROP CONSTRAINT ' + '[' + fk.NAME + ']
GO'
FROM sys.foreign_keys AS fk
INNER JOIN sys.schemas AS sch ON sch.schema_id = fk.schema_id
ORDER BY fk.NAME
Найти ограничение
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('TABLE_NAME')
Выполнить SQL, генерируемый этим SQL
SELECT
'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) +
'.[' + OBJECT_NAME(parent_object_id) +
'] DROP CONSTRAINT ' + name
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('TABLE_NAME')
Safeway.
Примечание: добавлено решение для устранения ограничения, чтобы можно было отбросить или изменить таблицу без какой-либо ошибки ограничения.
Первый пост :)
Для ОП, решения Krištof будет работать, если нет проблем с массивными данными и вопросами журнала транзакций на воздушном шаре на больших удалениях. Кроме того, даже с сохранением хранилища tlog, так как удаляет запись в tlog, операция может занять очень много времени для таблиц с сотнями миллионов строк.
Я использую серию курсоров для усечения и перезагрузки больших копий одной из наших огромных баз данных производства. Решение, разработанное для нескольких схем, нескольких столбцов внешнего ключа и, самое главное, может быть использовано для использования в SSIS.
Он включает в себя создание трех промежуточных таблиц (реальных таблиц) для размещения сценариев DROP, CREATE и CHECK FK, создания и вставки этих скриптов в таблицы, а затем циклического перемещения по ним и их выполнения. Приложенный сценарий состоит из четырех частей: 1.) создание и хранение сценариев в трех промежуточных (реальных) таблицах, 2.) выполнение сценариев FK сбрасывания с помощью курсора один за другим, 3.) использование sp_MSforeachtable для усечения всех таблицы в базе данных, отличные от наших трех промежуточных таблиц, и 4.) выполнение создания FK и проверка скриптов FK в конце вашего пакета SSIS ETL.
Запустить часть создания скрипта в выполнении задачи SQL в SSIS. Запустите «execute Drop FK Scripts» во второй задаче Execute SQL. Поместите скрипт усечения в третью задачу SQL Execute, затем выполните все другие процессы ETL, которые необходимо выполнить, перед тем, как присоединить сценарии CREATE и CHECK в конечной задаче Execute SQL (или два, если требуется) в конце вашего потока управления.
Хранение скриптов в реальных таблицах оказалось неоценимым, если повторное применение внешних ключей не удалось, поскольку вы можете выбрать * из sync_CreateFK, скопировать/вставить в окно запроса, запустить их по одному и исправить когда вы найдете те, которые не удались/все еще не могут повторно применяться.
Не перезапускайте сценарий еще раз, если он не работает, не убедившись, что вы повторно примените все внешние ключи/проверки до этого, или вы скорее всего потеряете некоторое создание и проверите скрипты fk как наш этап таблицы отбрасываются и воссоздаются до создания сценариев для выполнения.
----------------------------------------------------------------------------
1)
/*
Author: Denmach
DateCreated: 2014-04-23
Purpose: Generates SQL statements to DROP, ADD, and CHECK existing constraints for a
database. Stores scripts in tables on target database for execution. Executes
those stored scripts via independent cursors.
DateModified:
ModifiedBy
Comments: This will eliminate deletes and the T-log ballooning associated with it.
*/
DECLARE @schema_name SYSNAME;
DECLARE @table_name SYSNAME;
DECLARE @constraint_name SYSNAME;
DECLARE @constraint_object_id INT;
DECLARE @referenced_object_name SYSNAME;
DECLARE @is_disabled BIT;
DECLARE @is_not_for_replication BIT;
DECLARE @is_not_trusted BIT;
DECLARE @delete_referential_action TINYINT;
DECLARE @update_referential_action TINYINT;
DECLARE @tsql NVARCHAR(4000);
DECLARE @tsql2 NVARCHAR(4000);
DECLARE @fkCol SYSNAME;
DECLARE @pkCol SYSNAME;
DECLARE @col1 BIT;
DECLARE @action CHAR(6);
DECLARE @referenced_schema_name SYSNAME;
--------------------------------Generate scripts to drop all foreign keys in a database --------------------------------
IF OBJECT_ID('dbo.sync_dropFK') IS NOT NULL
DROP TABLE sync_dropFK
CREATE TABLE sync_dropFK
(
ID INT IDENTITY (1,1) NOT NULL
, Script NVARCHAR(4000)
)
DECLARE FKcursor CURSOR FOR
SELECT
OBJECT_SCHEMA_NAME(parent_object_id)
, OBJECT_NAME(parent_object_id)
, name
FROM
sys.foreign_keys WITH (NOLOCK)
ORDER BY
1,2;
OPEN FKcursor;
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name)
+ '.'
+ QUOTENAME(@table_name)
+ ' DROP CONSTRAINT '
+ QUOTENAME(@constraint_name)
+ ';';
--PRINT @tsql;
INSERT sync_dropFK (
Script
)
VALUES (
@tsql
)
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
;
END;
CLOSE FKcursor;
DEALLOCATE FKcursor;
---------------Generate scripts to create all existing foreign keys in a database --------------------------------
----------------------------------------------------------------------------------------------------------
IF OBJECT_ID('dbo.sync_createFK') IS NOT NULL
DROP TABLE sync_createFK
CREATE TABLE sync_createFK
(
ID INT IDENTITY (1,1) NOT NULL
, Script NVARCHAR(4000)
)
IF OBJECT_ID('dbo.sync_createCHECK') IS NOT NULL
DROP TABLE sync_createCHECK
CREATE TABLE sync_createCHECK
(
ID INT IDENTITY (1,1) NOT NULL
, Script NVARCHAR(4000)
)
DECLARE FKcursor CURSOR FOR
SELECT
OBJECT_SCHEMA_NAME(parent_object_id)
, OBJECT_NAME(parent_object_id)
, name
, OBJECT_NAME(referenced_object_id)
, OBJECT_ID
, is_disabled
, is_not_for_replication
, is_not_trusted
, delete_referential_action
, update_referential_action
, OBJECT_SCHEMA_NAME(referenced_object_id)
FROM
sys.foreign_keys WITH (NOLOCK)
ORDER BY
1,2;
OPEN FKcursor;
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
, @referenced_object_name
, @constraint_object_id
, @is_disabled
, @is_not_for_replication
, @is_not_trusted
, @delete_referential_action
, @update_referential_action
, @referenced_schema_name;
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name)
+ '.'
+ QUOTENAME(@table_name)
+ CASE
@is_not_trusted
WHEN 0 THEN ' WITH CHECK '
ELSE ' WITH NOCHECK '
END
+ ' ADD CONSTRAINT '
+ QUOTENAME(@constraint_name)
+ ' FOREIGN KEY (';
SET @tsql2 = '';
DECLARE ColumnCursor CURSOR FOR
SELECT
COL_NAME(fk.parent_object_id
, fkc.parent_column_id)
, COL_NAME(fk.referenced_object_id
, fkc.referenced_column_id)
FROM
sys.foreign_keys fk WITH (NOLOCK)
INNER JOIN sys.foreign_key_columns fkc WITH (NOLOCK) ON fk.[object_id] = fkc.constraint_object_id
WHERE
fkc.constraint_object_id = @constraint_object_id
ORDER BY
fkc.constraint_column_id;
OPEN ColumnCursor;
SET @col1 = 1;
FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@col1 = 1)
SET @col1 = 0;
ELSE
BEGIN
SET @tsql = @tsql + ',';
SET @tsql2 = @tsql2 + ',';
END;
SET @tsql = @tsql + QUOTENAME(@fkCol);
SET @tsql2 = @tsql2 + QUOTENAME(@pkCol);
--PRINT '@tsql = ' + @tsql
--PRINT '@tsql2 = ' + @tsql2
FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
--PRINT 'FK Column ' + @fkCol
--PRINT 'PK Column ' + @pkCol
END;
CLOSE ColumnCursor;
DEALLOCATE ColumnCursor;
SET @tsql = @tsql + ') REFERENCES '
+ QUOTENAME(@referenced_schema_name)
+ '.'
+ QUOTENAME(@referenced_object_name)
+ ' ('
+ @tsql2 + ')';
SET @tsql = @tsql
+ ' ON UPDATE '
+
CASE @update_referential_action
WHEN 0 THEN 'NO ACTION '
WHEN 1 THEN 'CASCADE '
WHEN 2 THEN 'SET NULL '
ELSE 'SET DEFAULT '
END
+ ' ON DELETE '
+
CASE @delete_referential_action
WHEN 0 THEN 'NO ACTION '
WHEN 1 THEN 'CASCADE '
WHEN 2 THEN 'SET NULL '
ELSE 'SET DEFAULT '
END
+
CASE @is_not_for_replication
WHEN 1 THEN ' NOT FOR REPLICATION '
ELSE ''
END
+ ';';
END;
-- PRINT @tsql
INSERT sync_createFK
(
Script
)
VALUES (
@tsql
)
-------------------Generate CHECK CONSTRAINT scripts for a database ------------------------------
----------------------------------------------------------------------------------------------------------
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name)
+ '.'
+ QUOTENAME(@table_name)
+
CASE @is_disabled
WHEN 0 THEN ' CHECK '
ELSE ' NOCHECK '
END
+ 'CONSTRAINT '
+ QUOTENAME(@constraint_name)
+ ';';
--PRINT @tsql;
INSERT sync_createCHECK
(
Script
)
VALUES (
@tsql
)
END;
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
, @referenced_object_name
, @constraint_object_id
, @is_disabled
, @is_not_for_replication
, @is_not_trusted
, @delete_referential_action
, @update_referential_action
, @referenced_schema_name;
END;
CLOSE FKcursor;
DEALLOCATE FKcursor;
--SELECT * FROM sync_DropFK
--SELECT * FROM sync_CreateFK
--SELECT * FROM sync_CreateCHECK
---------------------------------------------------------------------------
2.)
-----------------------------------------------------------------------------------------------------------------
----------------------------execute Drop FK Scripts --------------------------------------------------
DECLARE @scriptD NVARCHAR(4000)
DECLARE DropFKCursor CURSOR FOR
SELECT Script
FROM sync_dropFK WITH (NOLOCK)
OPEN DropFKCursor
FETCH NEXT FROM DropFKCursor
INTO @scriptD
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @scriptD
EXEC (@scriptD)
FETCH NEXT FROM DropFKCursor
INTO @scriptD
END
CLOSE DropFKCursor
DEALLOCATE DropFKCursor
--------------------------------------------------------------------------------
3.)
------------------------------------------------------------------------------------------------------------------
----------------------------Truncate all tables in the database other than our staging tables --------------------
------------------------------------------------------------------------------------------------------------------
EXEC sp_MSforeachtable 'IF OBJECT_ID(''?'') NOT IN
(
ISNULL(OBJECT_ID(''dbo.sync_createCHECK''),0),
ISNULL(OBJECT_ID(''dbo.sync_createFK''),0),
ISNULL(OBJECT_ID(''dbo.sync_dropFK''),0)
)
BEGIN TRY
TRUNCATE TABLE ?
END TRY
BEGIN CATCH
PRINT ''Truncation failed on''+ ? +''
END CATCH;'
GO
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
----------------------------execute Create FK Scripts and CHECK CONSTRAINT Scripts---------------
----------------------------tack me at the end of the ETL in a SQL task-------------------------
-------------------------------------------------------------------------------------------------
DECLARE @scriptC NVARCHAR(4000)
DECLARE CreateFKCursor CURSOR FOR
SELECT Script
FROM sync_createFK WITH (NOLOCK)
OPEN CreateFKCursor
FETCH NEXT FROM CreateFKCursor
INTO @scriptC
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @scriptC
EXEC (@scriptC)
FETCH NEXT FROM CreateFKCursor
INTO @scriptC
END
CLOSE CreateFKCursor
DEALLOCATE CreateFKCursor
-------------------------------------------------------------------------------------------------
DECLARE @scriptCh NVARCHAR(4000)
DECLARE CreateCHECKCursor CURSOR FOR
SELECT Script
FROM sync_createCHECK WITH (NOLOCK)
OPEN CreateCHECKCursor
FETCH NEXT FROM CreateCHECKCursor
INTO @scriptCh
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @scriptCh
EXEC (@scriptCh)
FETCH NEXT FROM CreateCHECKCursor
INTO @scriptCh
END
CLOSE CreateCHECKCursor
DEALLOCATE CreateCHECKCursor
WITH CHECK CHECK
почти наверняка требуется!
Этот вопрос был поднят в некоторых ответах и комментариях, но я чувствую, что это достаточно важно, чтобы снова вызвать его.
Повторное включение ограничения с использованием следующей команды (нет WITH CHECK
) будет содержать serious drawbacks.
ALTER TABLE MyTable CHECK CONSTRAINT MyConstraint;
обратными | С NOCHECK
Указывает, являются ли данные в таблице или не подтверждены с помощью недавно добавленного или повторно включенного ограничения FOREIGN KEY или CHECK. Если не указано , для новых ограничений предполагается WITH CHECK, а для возобновляемых ограничений используется NOKECK .
Если вы не хотите проверять новые ограничения CHECK или FOREIGN KEY против существующих данных, используйте WITH NOCHECK. Мы не рекомендуем делать , за исключением редких случаев. Новое ограничение будет оцениваться в все последующие обновления данных. Любые нарушения ограничений, которые подавляются с помощью NOCHECK при добавлении ограничения, могут привести к сбою будущих обновлений , если они обновляют строки данными, которые не соответствуют ограничению .
Оптимизатор запросов не учитывает ограничения, которые определены С NOCHECK. Такие ограничения игнорируются до тех пор, пока они не будут повторно активированы , используя таблицу ALTER TABLE WITH CHECK CHECK CONSTRAINT ALL.
Примечание: С NOCHECK по умолчанию для повторного включения ограничений. Я должен задаться вопросом, почему ...
- В ходе выполнения этой команды не будут оцениваться существующие данные в таблице - успешное завершение не гарантирует, что данные в таблице действительны в соответствии с ограничением.
- Во время следующего обновления недопустимых записей ограничение будет оцениваться и не будет выполнено, что приведет к ошибкам, которые могут быть не связаны с фактическим обновлением.
- Логика приложения, которая полагается на ограничение, чтобы гарантировать достоверность данных, может завершиться неудачей.
- Оптимизатор запросов не будет использовать какое-либо ограничение, которое будет включено таким образом.
Системный вид sys.foreign_keys обеспечивает определенную видимость проблемы. Обратите внимание, что он имеет как is_disabled
, так и столбец is_not_trusted
. is_disabled
указывает, будут ли проверены будущие операции манипуляции данными с ограничением.is_not_trusted
указывает, были ли все данные, находящиеся в настоящее время в таблице, проверены на ограничение.
ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint;
Есть ли у вас препятствия, которым нужно доверять? Узнать ...
SELECT * FROM sys.foreign_keys WHERE is_not_trusted = 1;
У меня есть более полезная версия, если вы заинтересованы. Я снял здесь немного кода http://www.dbaservices.com.au/news/drop-recreate-foreign-key-constraints/, изменяя его, чтобы разрешить массив таблиц в хранимой процедуре, и он заполняет команды drop, truncate, add, перед выполнением всех из них. Это дает вам возможность решить, какие таблицы нужно усекать.
/****** Object: UserDefinedTableType [util].[typ_objects_for_managing] Script Date: 03/04/2016 16:42:55 ******/
CREATE TYPE [util].[typ_objects_for_managing] AS TABLE(
[schema] [sysname] NOT NULL,
[object] [sysname] NOT NULL
)
GO
create procedure [util].[truncate_table_with_constraints]
@objects_for_managing util.typ_objects_for_managing readonly
[email protected] sysname
--,@table sysname
as
--select
-- @table = 'TABLE',
-- @schema = 'SCHEMA'
declare @exec_table as table (ordinal int identity (1,1), statement nvarchar(4000), primary key (ordinal));
--print '/*Drop Foreign Key Statements for ['[email protected]+'].['[email protected]+']*/'
insert into @exec_table (statement)
select
'ALTER TABLE ['+SCHEMA_NAME(o.schema_id)+'].['+ o.name+'] DROP CONSTRAINT ['+fk.name+']'
from sys.foreign_keys fk
inner join sys.objects o
on fk.parent_object_id = o.object_id
where
exists (
select * from @objects_for_managing chk
where
chk.[schema] = SCHEMA_NAME(o.schema_id)
and
chk.[object] = o.name
)
;
--o.name = @table and
--SCHEMA_NAME(o.schema_id) = @schema
insert into @exec_table (statement)
select
'TRUNCATE TABLE ' + src.[schema] + '.' + src.[object]
from @objects_for_managing src
;
--print '/*Create Foreign Key Statements for ['[email protected]+'].['[email protected]+']*/'
insert into @exec_table (statement)
select 'ALTER TABLE ['+SCHEMA_NAME(o.schema_id)+'].['+o.name+'] ADD CONSTRAINT ['+fk.name+'] FOREIGN KEY (['+c.name+'])
REFERENCES ['+SCHEMA_NAME(refob.schema_id)+'].['+refob.name+'](['+refcol.name+'])'
from sys.foreign_key_columns fkc
inner join sys.foreign_keys fk
on fkc.constraint_object_id = fk.object_id
inner join sys.objects o
on fk.parent_object_id = o.object_id
inner join sys.columns c
on fkc.parent_column_id = c.column_id and
o.object_id = c.object_id
inner join sys.objects refob
on fkc.referenced_object_id = refob.object_id
inner join sys.columns refcol
on fkc.referenced_column_id = refcol.column_id and
fkc.referenced_object_id = refcol.object_id
where
exists (
select * from @objects_for_managing chk
where
chk.[schema] = SCHEMA_NAME(o.schema_id)
and
chk.[object] = o.name
)
;
--o.name = @table and
--SCHEMA_NAME(o.schema_id) = @schema
declare @looper int , @total_records int, @sql_exec nvarchar(4000)
select @looper = 1, @total_records = count(*) from @exec_table;
while @looper <= @total_records
begin
select @sql_exec = (select statement from @exec_table where ordinal [email protected])
exec sp_executesql @sql_exec
print @sql_exec
set @looper = @looper + 1
end
Один сценария, чтобы управлять ими все: это сочетает в себе укоротить и удалять команды с sp_MSforeachtable, так что вы можете избежать падений и воссоздавать ограничения - просто указать таблицы, которые должны быть удалены, а не усеченной и для моих целей я включившие дополнительный фильтр схемы для хорошей меры (проверен в 2008R2)
declare @schema nvarchar(max) = 'and Schema_Id=Schema_id(''Value'')'
declare @deletiontables nvarchar(max) = '(''TableA'',''TableB'')'
declare @truncateclause nvarchar(max) = @schema + ' and o.Name not in ' + + @deletiontables;
declare @deleteclause nvarchar(max) = @schema + ' and o.Name in ' + @deletiontables;
exec sp_MSforeachtable 'alter table ? nocheck constraint all', @[email protected]
exec sp_MSforeachtable 'truncate table ?', @[email protected]
exec sp_MSforeachtable 'delete from ?', @[email protected]
exec sp_MSforeachtable 'alter table ? with check check constraint all', @[email protected]
Ответ пометка «905» выглядит хорошо, но не работает.
Следующие работали для меня. Любой основной ключ, уникальный ключ или ограничения по умолчанию CAN NOT отключить. Фактически, если «sp_helpconstraint» показывает «n/a» в status_enabled - означает, что он может быть включен/отключен NOT.
- Чтобы создать сценарий для DISABLE
select 'ALTER TABLE ' + object_name(id) + ' NOCHECK CONSTRAINT [' + object_name(constid) + ']'
from sys.sysconstraints
where status & 0x4813 = 0x813 order by object_name(id)
- Для создания сценария ВКЛЮЧИТЬ
select 'ALTER TABLE ' + object_name(id) + ' CHECK CONSTRAINT [' + object_name(constid) + ']'
from sys.sysconstraints
where status & 0x4813 = 0x813 order by object_name(id)
Вы на самом деле должны быть в состоянии отключить ограничения внешнего ключа так же, как временно отключить другие ограничения :
Alter table MyTable nocheck constraint FK_ForeignKeyConstraintName
Просто убедитесь, что вы отключили ограничение на th e первая таблица, указанная в имени ограничения. Например, если мое ограничение внешнего ключа было FK_LocationsEmployeesLocationIdEmployeeId, я хотел бы использовать следующее:
Alter table Locations nocheck constraint FK_LocationsEmployeesLocationIdEmployeeId
даже если нарушение этого ограничения будет выдавать ошибку, что не обязательно заявить, что в таблицу в качестве источника конфликта.
- 1. Внешние ключи TSQL по просмотрам?
- 2. Как ограничить внешние ключи в Rails-ассоциации?
- 3. Получить внешние ключи с помощью PHP
- 4. Как ограничить внешние ключи в действии контроллера обновлений Rails?
- 5. Получить все внешние ключи с помощью JDBC
- 6. Как добавить внешние ключи?
- 7. Внешние ключи и вторичные ключи
- 8. Как заменить все внешние ключи?
- 9. Внешние ключи против присоединения
- 10. SQL множественные внешние ключи как первичные ключи
- 11. Первичные ключи и внешние ключи?
- 12. Внешние ключи SQLite
- 13. Внешние ключи не распознаются
- 14. Можно ли отображать внешние ключи с аннотациями спящего режима?
- 15. Пользовательские внешние ключи с Rails
- 16. Как смоделировать несоответствующие внешние ключи
- 17. Как создать пользовательские внешние ключи?
- 18. Внешние ключи с MySQL.Cluster (NDB)
- 19. Динамические внешние ключи - как реализовать?
- 20. Как читать и писать внешние ключи с помощью ActiveAndroid?
- 21. Как заполнить объект mongo с помощью массива «внешние ключи»?
- 22. Doctrine внешние ключи
- 23. Настольные агностические внешние ключи?
- 24. Композитные внешние ключи
- 25. Как найти все внешние ключи?
- 26. SQL Как установить внешние ключи
- 27. Как добавить внешние ключи MySQL
- 28. MySQL: Как делать внешние ключи?
- 29. Внешние ключи Oracle Varrays
- 30. SQL: Дополнительно внешние ключи
Для людей, спрашивающих «почему», я хотел бы сделать это: это для тестовой среды, где я хочу иметь возможность удалять и загружать тестовые данные из нескольких таблиц без необходимости поддерживать и указывать порядок использования данных загружен. Целостность данных не так важна для этого сценария. – 2008-10-01 18:48:36
Примечание. Если вы хотите ПРОВЕРИТЬ таблицу, вам действительно нужно отказаться от ограничений. – OutstandingBill 2016-07-02 01:11:17