web-dev-qa-db-ja.com

SQL Server 2005では、テーブルにプロパティを設定せずにカスケード削除を実行できますか?

顧客データでいっぱいのデータベースがあります。それは非常に大きいので、操作するのは本当に面倒です、そして私はむしろそれを顧客の10%にスリム化したいのですが、それは開発に十分です。非常に多くのテーブルがあり、 "ON DELETE CASCADE"ですべてを変更したくありません。これは1回限りの取引だからです。

最初に設定せずにすべてのテーブルをカスケードする削除操作を実行できますか?そうでない場合、私の最良の選択肢は何ですか?

36
Kevin Conner

オンラインで見つけたアドバイスとスクリプトを組み合わせて、ON DELETE CASCADEに関係なく、カスケード削除を実行するために実行できるSQLを生成する手順を作成しました。時間の無駄だったと思いますが、書いて楽しかったです。このようにすることの利点は、各行の間にGOステートメントを置くことができ、1つの大きなトランザクションである必要がないことです。オリジナルは再帰的な手順でした。これは、再帰をスタックテーブルに展開します。

create procedure usp_delete_cascade (
    @base_table_name varchar(200), @base_criteria nvarchar(1000)
)
as begin
    -- Adapted from http://www.sqlteam.com/article/performing-a-cascade-delete-in-sql-server-7
    -- Expects the name of a table, and a conditional for selecting rows
    -- within that table that you want deleted.
    -- Produces SQL that, when run, deletes all table rows referencing the ones
    -- you initially selected, cascading into any number of tables,
    -- without the need for "ON DELETE CASCADE".
    -- Does not appear to work with self-referencing tables, but it will
    -- delete everything beneath them.
    -- To make it easy on the server, put a "GO" statement between each line.

    declare @to_delete table (
        id int identity(1, 1) primary key not null,
        criteria nvarchar(1000) not null,
        table_name varchar(200) not null,
        processed bit not null,
        delete_sql varchar(1000)
    )

    insert into @to_delete (criteria, table_name, processed) values (@base_criteria, @base_table_name, 0)

    declare @id int, @criteria nvarchar(1000), @table_name varchar(200)
    while exists(select 1 from @to_delete where processed = 0) begin
        select top 1 @id = id, @criteria = criteria, @table_name = table_name from @to_delete where processed = 0 order by id desc

        insert into @to_delete (criteria, table_name, processed)
            select referencing_column.name + ' in (select [' + referenced_column.name + '] from [' + @table_name +'] where ' + @criteria + ')',
                referencing_table.name,
                0
            from  sys.foreign_key_columns fk
                inner join sys.columns referencing_column on fk.parent_object_id = referencing_column.object_id 
                    and fk.parent_column_id = referencing_column.column_id 
                inner join  sys.columns referenced_column on fk.referenced_object_id = referenced_column.object_id 
                    and fk.referenced_column_id = referenced_column.column_id 
                inner join  sys.objects referencing_table on fk.parent_object_id = referencing_table.object_id 
                inner join  sys.objects referenced_table on fk.referenced_object_id = referenced_table.object_id 
                inner join  sys.objects constraint_object on fk.constraint_object_id = constraint_object.object_id
            where referenced_table.name = @table_name
                and referencing_table.name != referenced_table.name

        update @to_delete set
            processed = 1
        where id = @id
    end

    select 'print ''deleting from ' + table_name + '...''; delete from [' + table_name + '] where ' + criteria from @to_delete order by id desc
end

exec usp_delete_cascade 'root_table_name', 'id = 123'
55
Kevin Conner

これは、データがまばらにデータモデル用に最適化された、承認済みの回答のバージョンです。削除リストに追加する前に、FKチェーン内のデータの存在を確認します。テストデータのクリーンアップに使用します。

アクティブなトランザクションデータベースでは使用しないでください。ロックを長時間保持します。

/*
-- ============================================================================
-- Purpose: Performs a cascading hard-delete.
--          Not for use on an active transactional database- it holds locks for too long.
--          (http://stackoverflow.com/questions/116968/in-sql-server-2005-can-i-do-a-cascade-delete-without-setting-the-property-on-my)
-- eg:
exec dbo.hp_Common_Delete 'tblConsumer', 'Surname = ''TestDxOverdueOneReviewWm''', 1
-- ============================================================================
*/
create proc [dbo].[hp_Common_Delete]
(
    @TableName sysname, 
    @Where nvarchar(4000),  -- Shouldn't include 'where' keyword, e.g. Surname = 'smith', NOT where Surname = 'smith'
    @IsDebug bit = 0
)
as
set nocount on

begin try
    -- Prepare tables to store deletion criteria.  
    -- #tmp_to_delete stores criteria that is tested for results before being added to #to_delete
    create table #to_delete
    (
        id int identity(1, 1) primary key not null,
        criteria nvarchar(4000) not null,
        table_name sysname not null,
        processed bit not null default(0)
    )
    create table #tmp_to_delete 
    (
        id int primary key identity(1,1), 
        criteria nvarchar(4000) not null, 
        table_name sysname not null
    )

    -- Open a transaction (it'll be a long one- don't use this on production!)
    -- We need a transaction around criteria generation because we only 
    -- retain criteria that has rows in the db, and we don't want that to change under us.
    begin tran
        -- If the top-level table meets the deletion criteria, add it
        declare @Sql nvarchar(4000)
        set @Sql = 'if exists(select top(1) * from ' + @TableName + ' where ' + @Where + ') 
            insert #to_delete (criteria, table_name) values (''' + replace(@Where, '''', '''''') + ''', ''' + @TableName + ''')'
        exec (@Sql)

        -- Loop over deletion table, walking foreign keys to generate delete targets
        declare @id int, @tmp_id int, @criteria nvarchar(4000), @new_criteria nvarchar(4000), @table_name sysname, @new_table_name sysname
        while exists(select 1 from #to_delete where processed = 0) 
        begin
            -- Grab table/criteria to work on
            select  top(1) @id = id, 
                    @criteria = criteria, 
                    @table_name = table_name 
            from    #to_delete 
            where   processed = 0 
            order by id desc

            -- Insert all immediate child tables into a temp table for processing
            insert  #tmp_to_delete
            select  referencing_column.name + ' in (select [' + referenced_column.name + '] from [' + @table_name +'] where ' + @criteria + ')',
                    referencing_table.name
            from  sys.foreign_key_columns fk
                    inner join sys.columns referencing_column on fk.parent_object_id = referencing_column.object_id 
                            and fk.parent_column_id = referencing_column.column_id 
                    inner join  sys.columns referenced_column on fk.referenced_object_id = referenced_column.object_id 
                            and fk.referenced_column_id = referenced_column.column_id 
                    inner join  sys.objects referencing_table on fk.parent_object_id = referencing_table.object_id 
                    inner join  sys.objects referenced_table on fk.referenced_object_id = referenced_table.object_id 
                    inner join  sys.objects constraint_object on fk.constraint_object_id = constraint_object.object_id
            where referenced_table.name = @table_name
                    and referencing_table.name != referenced_table.name

            -- Loop on child table criteria, and insert them into delete table if they have records in the db
            select @tmp_id = max(id) from #tmp_to_delete
            while (@tmp_id >= 1)
            begin
                select @new_criteria = criteria, @new_table_name = table_name from #tmp_to_delete where id = @tmp_id
                set @Sql = 'if exists(select top(1) * from ' + @new_table_name + ' where ' + @new_criteria + ') 
                    insert #to_delete (criteria, table_name) values (''' + replace(@new_criteria, '''', '''''') + ''', ''' + @new_table_name + ''')'
                exec (@Sql)

                set @tmp_id = @tmp_id - 1
            end
            truncate table #tmp_to_delete

            -- Move to next record
            update  #to_delete 
            set     processed = 1
            where   id = @id
        end

        -- We have a list of all tables requiring deletion.  Actually delete now.
        select @id = max(id) from #to_delete 
        while (@id >= 1)
        begin
            select @criteria = criteria, @table_name = table_name from #to_delete where id = @id
            set @Sql = 'delete from [' + @table_name + '] where ' + @criteria
            if (@IsDebug = 1) print @Sql
            exec (@Sql)

            -- Next record
            set @id = @id - 1
        end
    commit
end try

begin catch
    -- Any error results in a rollback of the entire job
    if (@@trancount > 0) rollback

    declare @message nvarchar(2047), @errorProcedure nvarchar(126), @errorMessage nvarchar(2048), @errorNumber int, @errorSeverity int, @errorState int, @errorLine int
    select  @errorProcedure = isnull(error_procedure(), N'hp_Common_Delete'), 
            @errorMessage = isnull(error_message(), N'hp_Common_Delete unable to determine error message'), 
            @errorNumber = error_number(), @errorSeverity = error_severity(), @errorState = error_state(), @errorLine = error_line()

    -- Prepare error information as it would be output in SQL Mgt Studio
    declare @event nvarchar(2047)
    select  @event =    'Msg ' + isnull(cast(@errorNumber as varchar), 'null') + 
                        ', Level ' + isnull(cast(@errorSeverity as varchar), 'null') + 
                        ', State ' + isnull(cast(@errorState as varchar), 'null') + 
                        ', Procedure ' + isnull(@errorProcedure, 'null') + 
                        ', Line ' + isnull(cast(@errorLine as varchar), 'null') + 
                        ': ' + isnull(@errorMessage, '@ErrorMessage null')
    print   @event

    -- Re-raise error to ensure admin/job runners understand there was a failure
    raiserror(@errorMessage, @errorSeverity, @errorState)
end catch
7
Neil

Chrisによって提案されたすべての関連クエリを維持する必要がない限り、ON DELETE CASCADEは、断然最速かつ最も直接的なソリューションです。そして、それを永続的にしたくない場合は、このオプションをここでオンとオフに切り替えるT-SQLコードを用意してください。

  1. 元の_Tbl_A_MyFK_制約を削除します(ON DELETE CASCADEなし)。

    _ALTER TABLE Tbl_A DROP CONSTRAINT Tbl_A_MyFK_

  2. oN DELETE CASCADEを使用して、制約_Tbl_A_MyFK_を設定します

    ALTER TABLE Tbl_A ADD CONSTRAINT Tbl_A_MyFK FOREIGN KEY (MyFK) REFERENCES Tbl_B(Column) ON DELETE CASCADE

  3. ここで削除を行うことができます

    _DELETE FROM Tbl_A WHERE ..._

  4. 制約を削除する_Tbl_A_MyFK_

    _ALTER TABLE Tbl_A DROP CONSTRAINT Tbl_A_MyFK_

  5. oN DELETE CASCADEを使用せずに制約_Tbl_A_MyFK_を設定する

    ALTER TABLE Tbl_A ADD CONSTRAINT Tbl_A_MyFK FOREIGN KEY (MyFK) REFERENCES (Tbl_B)

7

SQL Server Management Studioに移動し、データベースを右クリックします。 「タスク」->「スクリプトの生成」を選択します。 [次へ]を2回クリックします。 [オプション]ウィンドウで、CREATEステートメントのみを生成するように設定することを選択し、外部キーを除くすべてをFalseに設定します。 Nextをクリックします。 [テーブル]を選択して、もう一度[次へ]をクリックします。 [すべて選択]ボタンをクリックし、[次へ]、[完了]の順にクリックして、選択したクエリウィンドウまたはファイルにスクリプトを送信します(大きなスクリプトになる可能性があるため、クリップボードは使用しないでください)。 ここで、テーブルを追加するスクリプトをすべて削除しますとすると、外部キーを作成するためのスクリプトが残ります。

データベースを現在の状態に復元する方法なので、そのスクリプトのコピーを作成します。検索と置換を使用して、各制約の最後にON DELETE CASCADEを追加します。これは、FKが現在どのように設定されているかによって異なり、手動で編集する必要がある場合があります。

スクリプトの生成を繰り返しますが、今回はDROPステートメントのみを生成するように設定します。 生成されたテーブルドロップを手動で削除してください。ドロップを実行してから、編集したcreateを実行して、削除時にそれらをすべてカスケードします。削除を行い、ドロップスクリプトを再度実行してから、最初に保存したスクリプトを実行します。

また、-最初にDBのバックアップを作成してください!単なるdevデータベースであっても、スクリプトの一部が正しくない場合は、頭痛の種を減らすことができます。

お役に立てれば!

ところで、別のポスターが示唆しているように、完全なテストデータを使用していくつかのテストを確実に行う必要がありますが、最初の開発にそれが必要でない理由がわかります。ある時点でそれをQAの一部として含めることを忘れないでください。

5
Tom H

私は通常、不要なレコードを削除するクエリを手書きして、後で参照できるように.sqlファイルとして保存します。擬似コードは次のとおりです。

  1. 一時テーブルに削除するメインテーブルからレコードのIDを選択します
  2. 一時テーブルに結合する各関連テーブルの削除クエリを記述します。
  3. 一時テーブルに結合するメインテーブルの削除クエリを記述します。
2
NotMe

私の提案は、変更された関係のリストをエクスポートしながら、データベースの各関係にon deleteカスケードを追加するスクリプトを作成することです。次に、プロセスを逆にして、リスト内の各テーブルのon deleteカスケードコマンドを削除できます。

2
Orion Adrian

個人的には、レコードをプロダクションに残す場合は、開発にも残します。それ以外の場合は、レコードセットが小さいときにうまく機能するが、実際のレコードセットに直面するとタイムアウトするコードを作成することがあります。

しかし、これを行うと決心している場合は、まず、定義するレコードのidフィールドをメインテーブルからワークテーブルにコピーします。次に、関連する各テーブルを取得し、そのワークテーブルに結合する削除を記述して、それらのレコードのみを削除します。親テーブルで仕上げます。このiaがスクリプトで記述され、保存されていることを確認してください。次回、テストデータに対して同様のことを実行するときに、レコードを削除する必要がある関連テーブルが何であるかわからなくても簡単に実行できます。

2
HLGEM

受け入れられた答えをもう少し詳しく考えると、異なるスキーマのテーブル間でこれを行う必要がありました。出力された削除スクリプトにスキーマを含めるようにスクリプトを更新しました。

CREATE PROCEDURE usp_delete_cascade (
        @base_table_schema varchar(100), @base_table_name varchar(200), @base_criteria nvarchar(1000)
)
as begin

        -- Expects the name of a table, and a conditional for selecting rows
        -- within that table that you want deleted.
        -- Produces SQL that, when run, deletes all table rows referencing the ones
        -- you initially selected, cascading into any number of tables,
        -- without the need for "ON DELETE CASCADE".
        -- Does not appear to work with self-referencing tables, but it will
        -- delete everything beneath them.
        -- To make it easy on the server, put a "GO" statement between each line.

        declare @to_delete table (
                id int identity(1, 1) primary key not null,
                criteria nvarchar(1000) not null,
                table_schema varchar(100),
                table_name varchar(200) not null,
                processed bit not null,
                delete_sql varchar(1000)
        )

        insert into @to_delete (criteria, table_schema, table_name, processed) values (@base_criteria, @base_table_schema, @base_table_name, 0)

        declare @id int, @criteria nvarchar(1000), @table_name varchar(200), @table_schema varchar(100)
        while exists(select 1 from @to_delete where processed = 0) begin
                select top 1 @id = id, @criteria = criteria, @table_name = table_name, @table_schema = table_schema from @to_delete where processed = 0 order by id desc

                insert into @to_delete (criteria, table_schema, table_name, processed)
                        select referencing_column.name + ' in (select [' + referenced_column.name + '] from [' + @table_schema + '].[' + @table_name +'] where ' + @criteria + ')',
                                schematable.name,
                                referencing_table.name,
                                0
                        from  sys.foreign_key_columns fk
                                inner join sys.columns referencing_column on fk.parent_object_id = referencing_column.object_id 
                                        and fk.parent_column_id = referencing_column.column_id 
                                inner join  sys.columns referenced_column on fk.referenced_object_id = referenced_column.object_id 
                                        and fk.referenced_column_id = referenced_column.column_id 
                                inner join  sys.objects referencing_table on fk.parent_object_id = referencing_table.object_id 
                                inner join sys.schemas schematable on referencing_table.schema_id = schematable.schema_id
                                inner join  sys.objects referenced_table on fk.referenced_object_id = referenced_table.object_id 
                                inner join  sys.objects constraint_object on fk.constraint_object_id = constraint_object.object_id
                        where referenced_table.name = @table_name
                                and referencing_table.name != referenced_table.name

                update @to_delete set
                        processed = 1
                where id = @id
        end

        select 'print ''deleting from ' + table_name + '...''; delete from [' + table_schema + '].[' + table_name + '] where ' + criteria from @to_delete order by id desc
end

exec usp_delete_cascade 'schema', 'RootTable', 'Id = 123'
exec usp_delete_cascade 'schema', 'RootTable', 'GuidId = ''A7202F84-FA57-4355-B499-1F8718E29058'''
2
kevin_fitz

トリガーを考慮するためのcroisharpの回答の拡張。つまり、影響するすべてのトリガーを無効にし、行を削除し、トリガーを有効にするスキーマ対応ソリューション。

CREATE PROCEDURE usp_delete_cascade (
@base_table_schema varchar(100),
@base_table_name varchar(200),
@base_criteria nvarchar(1000)
)
as begin

    -- Expects the name of a table, and a conditional for selecting rows
    -- within that table that you want deleted.
    -- Produces SQL that, when run, deletes all table rows referencing the ones
    -- you initially selected, cascading into any number of tables,
    -- without the need for "ON DELETE CASCADE".
    -- Does not appear to work with self-referencing tables, but it will
    -- delete everything beneath them.
    -- To make it easy on the server, put a "GO" statement between each line.

    declare @to_delete table (
            id int identity(1, 1) primary key not null,
            criteria nvarchar(1000) not null,
            table_schema varchar(100),
            table_name varchar(200) not null,
            processed bit not null,
            delete_sql varchar(1000)
    )

    insert into @to_delete (criteria, table_schema, table_name, processed) values (@base_criteria, @base_table_schema, @base_table_name, 0)

    declare @id int, @criteria nvarchar(1000), @table_name varchar(200), @table_schema varchar(100)
    while exists(select 1 from @to_delete where processed = 0) begin
            select top 1 @id = id, @criteria = criteria, @table_name = table_name, @table_schema = table_schema from @to_delete where processed = 0 order by id desc

            insert into @to_delete (criteria, table_schema, table_name, processed)
                    select referencing_column.name + ' in (select [' + referenced_column.name + '] from [' + @table_schema + '].[' + @table_name +'] where ' + @criteria + ')',
                            schematable.name,
                            referencing_table.name,
                            0
                    from  sys.foreign_key_columns fk
                            inner join sys.columns referencing_column on fk.parent_object_id = referencing_column.object_id 
                                    and fk.parent_column_id = referencing_column.column_id 
                            inner join  sys.columns referenced_column on fk.referenced_object_id = referenced_column.object_id 
                                    and fk.referenced_column_id = referenced_column.column_id 
                            inner join  sys.objects referencing_table on fk.parent_object_id = referencing_table.object_id 
                            inner join sys.schemas schematable on referencing_table.schema_id = schematable.schema_id
                            inner join  sys.objects referenced_table on fk.referenced_object_id = referenced_table.object_id 
                            inner join  sys.objects constraint_object on fk.constraint_object_id = constraint_object.object_id
                    where referenced_table.name = @table_name
                            and referencing_table.name != referenced_table.name

            update @to_delete set
                    processed = 1
            where id = @id
    end

    select 'print ''deleting from ' + table_name + '...''; delete from [' + table_schema + '].[' + table_name + '] where ' + criteria from @to_delete order by id desc

    DECLARE @commandText VARCHAR(8000), @triggerOn VARCHAR(8000), @triggerOff VARCHAR(8000)
    DECLARE curDeletes CURSOR FOR
        select
            'DELETE FROM [' + table_schema + '].[' + table_name + '] WHERE ' + criteria,
            'ALTER TABLE [' + table_schema + '].[' + table_name + '] DISABLE TRIGGER ALL',
            'ALTER TABLE [' + table_schema + '].[' + table_name + '] ENABLE TRIGGER ALL'
        from @to_delete order by id desc

    OPEN curDeletes
    FETCH NEXT FROM curDeletes INTO @commandText, @triggerOff, @triggerOn

    WHILE(@@FETCH_STATUS=0)
    BEGIN
        EXEC (@triggerOff)
        EXEC (@commandText)
        EXEC (@triggerOn)
        FETCH NEXT FROM curDeletes INTO @commandText, @triggerOff, @triggerOn
    END
    CLOSE curDeletes
    DEALLOCATE curDeletes
end
2
Łukasz Nojek

ケビンの投稿は不完全です。彼のt-sql spは、これらのコマンドを実行するためのコマンドのみを出力し、最後にこれを追加します

DECLARE @commandText VARCHAR(8000)
        DECLARE curDeletes CURSOR FOR
            select 'delete from [' + table_name + '] where ' + criteria from @to_delete order by id desc

        OPEN curDeletes
        FETCH NEXT FROM curDeletes
        INTO
            @commandText

        WHILE(@@FETCH_STATUS=0)
        BEGIN
            EXEC (@commandText)
            FETCH NEXT FROM curDeletes INTO @commandText
        END
        CLOSE curDeletes
        DEALLOCATE curDeletes
2
croisharp

選択した後、実際の削除をビルドして実行する必要があります

declare @deleteSql nvarchar(1200)
declare delete_cursor cursor for
select table_name, criteria 
from @to_delete
order by id desc

open delete_cursor

fetch next from delete_cursor
into @table_name, @criteria

while @@fetch_status = 0
begin
 select @deleteSql = 'delete from ' + @table_name + ' where ' + @criteria
 --print @deleteSql
-- exec sp_execute @deleteSql
EXEC SP_EXECUTESQL @deleteSql

 fetch next from delete_cursor
 into @table_name, @criteria
end
close delete_cursor
deallocate delete_cursor
1
dan

外部キーを操作するスクリプトに複数の列が含まれているスクリプトをここに投稿してください。

create procedure usp_delete_cascade (
@TableName varchar(200), @Where nvarchar(1000)
) as begin

declare @to_delete table (
    id int identity(1, 1) primary key not null,
    criteria nvarchar(1000) not null,
    table_name varchar(200) not null,
    processed bit not null default(0),
    delete_sql varchar(1000)
)
            DECLARE @MyCursor CURSOR

declare         @referencing_column_name varchar(1000)
declare         @referencing_table_name varchar(1000)
 declare @Sql nvarchar(4000)
insert into @to_delete (criteria, table_name) values ('', @TableName)


declare @id int, @criteria nvarchar(1000), @table_name varchar(200)
while exists(select 1 from @to_delete where processed = 0) begin
    select top 1 @id = id, @criteria = criteria, @table_name = table_name from @to_delete where processed = 0 order by id desc
        SET @MyCursor = CURSOR FAST_FORWARD
        FOR
        select referencing_column.name as column_name,
            referencing_table.name as table_name
        from  sys.foreign_key_columns fk
            inner join sys.columns referencing_column on fk.parent_object_id = referencing_column.object_id 
                and fk.parent_column_id = referencing_column.column_id 
            inner join  sys.columns referenced_column on fk.referenced_object_id = referenced_column.object_id 
                and fk.referenced_column_id = referenced_column.column_id 
            inner join  sys.objects referencing_table on fk.parent_object_id = referencing_table.object_id 
            inner join  sys.objects referenced_table on fk.referenced_object_id = referenced_table.object_id 
            inner join  sys.objects constraint_object on fk.constraint_object_id = constraint_object.object_id
        where referenced_table.name = @table_name
            and referencing_table.name != referenced_table.name

        OPEN @MyCursor
        FETCH NEXT FROM @MYCursor
        INTO @referencing_column_name, @referencing_table_name

        WHILE @@FETCH_STATUS = 0

        BEGIN
            PRINT @referencing_column_name
            PRINT @referencing_table_name
                    update @to_delete set criteria = criteria + ' AND '+@table_name+'.'+@referencing_column_name+'='+ @referencing_table_name+'.'+@referencing_column_name
                    where table_name = @referencing_table_name

                    if(@@ROWCOUNT = 0)
                    BEGIN
                            --if(@id <> 1)
                            --BEGIN
                                insert into @to_delete (criteria, table_name)
                                VALUES( ' LEFT JOIN '+@table_name+' ON '+@table_name+'.'+@referencing_column_name+'='+ @referencing_table_name+'.'+@referencing_column_name+ @criteria,
                                @referencing_table_name
                                )
                            --END
                            --ELSE
                            --BEGIN
                                --insert into @to_delete (criteria, table_name)
                                --VALUES( ' LEFT JOIN '+@table_name+' ON '+@table_name+'.'+@referencing_column_name+'='+ @referencing_table_name+'.'+@referencing_column_name,
                                --@referencing_table_name
                                --)
                            --END
                    END
                        FETCH NEXT FROM @MYCursor
            INTO @referencing_column_name, @referencing_table_name
        END


        CLOSE @MyCursor 
        DEALLOCATE @MyCursor 
    update @to_delete set
        processed = 1
    where id = @id
end

--select 'print ''deleting from ' + table_name + '...''; delete from [' + table_name + '] where ' + criteria from @to_delete order by id desc

--select id, table_name, criteria, @Where from @to_delete order by id desc

select @id = max(id) from @to_delete
while (@id >= 1)
begin
    select @criteria = criteria, @table_name = table_name from @to_delete where id = @id
    set @Sql = 'delete [' + @table_name + '] from [' + @table_name + '] ' + @criteria+' WHERE '+@Where
    exec (@Sql)
    PRINT @Sql

    -- Next record
    set @id = @id - 1
end
end
1
Jason Zheng

このスクリプトには2つの問題があります。1.すべてのテーブルベースを削除するには、条件1 = 1を指定する必要があります。 2.これにより、基本テーブルとの直接的な関係のみが作成されます。最終テーブルに別のテーブルの親リレーションがある場合、削除は失敗します

DELETE FROM [dbo]。[table2] WHERE TableID in(select [ID] from [dbo]。[table3] where 1 = 1)

Table2に親リレーションtable1がある場合

0
prampe