В SQL Server 2005 я могу сделать каскадное удаление без установки свойства для моих таблиц? - PullRequest
34 голосов
/ 22 сентября 2008

У меня есть база данных, полная данных о клиентах. Он настолько велик, что работать с ним действительно громоздко, и я бы предпочел уменьшить его до 10% клиентов, что достаточно для разработки. У меня очень много таблиц, и я не хочу менять их все с помощью «ON DELETE CASCADE», особенно потому, что это разовая сделка.

Могу ли я выполнить операцию удаления, каскадно пронизывающую все мои таблицы, без предварительной настройки? Если нет, то какой мой лучший вариант?

Ответы [ 13 ]

1 голос
/ 21 октября 2015

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

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 голос
/ 31 марта 2011

после выбора вы должны построить и выполнить фактическое удаление

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
0 голосов
/ 26 июля 2013

Этот скрипт имеет две проблемы: 1. Вы должны указать условие 1 = 1, чтобы удалить все таблицы базы. 2. Это создает прямые отношения только с базовой таблицей. Если финальная таблица имеет другое родительское отношение таблицы, ошибка удаления

УДАЛИТЬ ИЗ [dbo]. [Table2] ГДЕ TableID in (выберите [ID] из [dbo]. [Table3], где 1 = 1)

Если таблица2 имеет родительское отношение table1

...