Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 启用约束_Sql_Sql Server_Tsql_Sql Server 2000 - Fatal编程技术网

Sql 启用约束

Sql 启用约束,sql,sql-server,tsql,sql-server-2000,Sql,Sql Server,Tsql,Sql Server 2000,我有一个有很多约束的大型数据库,我更新了一些数据禁用约束,我只想重新启用它们 我使用了下面的查询 EXEC sp_msforeachtable 'ALTER TABLE MyTable NOCHECK CONSTRAINT all' exec sp_msforeachtable @command1='print ''MyTable''', @command2='ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT all' 但是,当我运行enable

我有一个有很多约束的大型数据库,我更新了一些数据禁用约束,我只想重新启用它们

我使用了下面的查询

EXEC sp_msforeachtable 'ALTER TABLE MyTable NOCHECK CONSTRAINT all' 
exec sp_msforeachtable @command1='print ''MyTable''', @command2='ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT all'
但是,当我运行enable查询时,由于数据量巨大,需要很长时间。花了一个多小时

我只想以正确的方式快速启用它,而不会出现任何问题


请指导我如何克服这个问题。

以“正确的方式而不出现任何问题”来解决这个问题需要时间。您可以通过省略
WITH CHECK
选项来提高速度,但最终会在数据库中出现,因此我不建议使用该选项。

需要检查的一件事是,约束两侧是否都有索引(顺便说一句,在正常操作中这是个好主意)。为了明确这一点,假设您有两个表(tbl_a和tbl_b),它们之间有FK约束(假设它是col_c)。您需要一个索引,其中前导列在tbl_a和tbl_b上都是col_c,这样它就不必对没有这样一个索引的表进行表扫描


此外,单独检查每个约束(而不是做一个“检查约束全部”)将为您提供更好的粒度,如果您需要在中间停止。

< P>使用SPMsMealCabSt表顺序运行语句。最有可能的是,将事情分散在几个线程上会大大加快进程。使用ServiceBroker,这可以在SQL代码中完成

(下面是从内存中编写的代码,我没有可用的SQL Server来测试它。因此,其中可能有一些错误。只要有可用的服务器,我就会更新。)

首先创建一个激活过程

  CREATE PROC p_enable_constraints
  AS
     DECLARE @handle UNIQUEIDENTIFIER
           , @message sysname
           , @sql nvarchar(max)

     WHILE 1=1
       BEGIN
         BEGIN TRAN
         WAITFOR ( RECEIVE TOP(1) @handle = conversation_handle,
                              @message = message_body
                   FROM ConstraintQueueReceive), TIMEOUT 1000;
        IF @@rowcount = 0
          begin
            rollback
            break;
          end

        set @sql = N'ALTER TABLE ' + quotename(@message) + N' WITH CHECK CONSTRAINT ALL'
        exec (@sql)
        if @@error <> 0
          begin
            rollback tran
            break
          end 
        COMMIT TRANSACTION
      END
    RETURN(0)
   GO
现在创建一个过程,为每个表提交一条消息

  CREATE PROC p_submit_enable_constraints_message @object sysname
  AS
    DECLARE @handle UNIQUEIDENTIFIER;
    DECLARE @message sysname;

    BEGIN TRANSACTION;
    BEGIN DIALOG @handle FROM SERVICE [ConstraintServiceSend] 
                           TO SERVICE [ConstraintServiceReceive]
    WITH ENCRYPTION = OFF;
    SEND ON CONVERSATION @handle (@object);

    COMMIT TRANSACTION;

    END CONVERSATION @handle
    GO
最后,我们可以调用该过程将其提交到队列

   EXEC sp_msforeachtable 'EXEC p_submit_enable_constraints_message N''?'''

理想情况下,alter table的结果会被捕获并发送回。

感谢您的快速回复。我需要让它回到正常的阶段。我不想把任何事情弄糟。我认为启用需要时间,因为启用时会检查现有数据。我们可以选择禁用数据验证并立即启用吗?@user459295:正如我所说的,更快的选择是用CHECK忽略
,这将产生后果。我不想知道不可信约束的影响。我能够快速运行与检查选项删除。它忽略了数据验证。@user459295:请阅读我在回答中包含的链接中的文章,以了解不受信任的约束的影响。但是,您能告诉我跟踪与表相关的每个约束的方法吗。然后我知道要单独禁用或启用什么。@user459295:约束在sys.foreign\u键中。注意,“名称”列是约束的名称,父对象id是FK所属表的对象id。从那里,您应该能够生成必要的DDL语句。另一种选择是powershell或您最喜欢的SMO工作方式。但那是一匹不同颜色的马。
   EXEC sp_msforeachtable 'EXEC p_submit_enable_constraints_message N''?'''