2008-09-22 15 views
32

Tengo una base de datos llena de datos de clientes. Es tan grande que es muy difícil de operar, y prefiero limitarlo al 10% de los clientes, que es mucho para el desarrollo. Tengo muchísimas mesas y no quiero alterarlas con "ON DELETE CASCADE", especialmente porque es un trato de una sola vez.En SQL Server 2005, ¿puedo hacer una eliminación en cascada sin establecer la propiedad en mis tablas?

¿Puedo hacer una operación de eliminación que conecte en cascada a través de todas mis tablas sin configurarlas primero? Si no, ¿cuál es mi mejor opción?

Respuesta

52

Combinando su consejo y un script que encontré en línea, hice un procedimiento que producirá SQL puede ejecutar para realizar una cascada borrar independientemente de ON DELETE CASCADE. Probablemente fue una gran pérdida de tiempo, pero pasé un buen rato escribiéndolo. Una ventaja de hacerlo de esta manera es que puede poner una declaración GO entre cada línea, y no tiene por qué ser una transacción grande. El original fue un procedimiento recursivo; este desenrolla la recursión en una tabla de pila.

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' 
+0

¡Buen script! ¡Gracias! – splattne

+0

¿Esta secuencia de comandos me permite enviar, por ejemplo, 'code = ABC AND name = dave' – ThePower

+1

Ha pasado un tiempo, pero creo que sí! –

2

Normalmente solo escribo a mano las consultas para eliminar los registros que no quiero y guardo eso como un archivo .sql para referencia futura. El pseudocódigo es:

  1. id Seleccione de registros de la tabla principal que quiero eliminar en una tabla temporal
  2. escribir una consulta de eliminación para cada tabla relacionada que se une a la tabla temporal.
  3. escribe una consulta de eliminación para la tabla principal que se une a mi tabla temporal.
2

Mi sugerencia es seguir adelante y escribir un script que agregará la cascada de eliminación a cada relación en la base de datos al exportar una lista de relaciones modificadas. Luego puede invertir el proceso y eliminar el comando borrar cascada en cada tabla de la lista.

2

Personalmente, si va a dejar los registros en producción, también los dejaría en desarrollo. De lo contrario, puede escribir un código que funciona bien cuando el conjunto de registros es pequeño pero agota el tiempo cuando se enfrenta al conjunto de registros real.

Pero si está decidido a hacer esto, copiaría el campo de identificación de los registros que desea detectar de la tabla principal primero a una tabla de trabajo. Luego tomaría cada tabla relacionada y escribiría una unión de eliminación en esa tabla de trabajo para eliminar solo esos registros. Termine con la tabla padre. Asegúrese de que está escrito en un script y guardado para que la próxima vez que quiera hacer algo similar a sus datos de prueba, pueda ejecutarlo fácilmente sin tener que averiguar cuáles son las tablas procesadas que necesitan registros eliminados de ellos.

5

Vaya a SQL Server Management Studio y haga clic con el botón derecho en la base de datos. Seleccione Tareas-> Generar secuencias de comandos. Haga clic en Siguiente dos veces. En la ventana Opciones, elija establecerlo para generar solo sentencias CREATE y poner todo en False, excepto para las claves externas. Haga clic en Siguiente. Seleccione Tablas y haga clic en Siguiente nuevamente. Haga clic en el botón "Seleccionar todo" y haga clic en Siguiente y luego en Finalizar y envíe el script a su elección de una ventana o archivo de consulta (no use el portapapeles, ya que podría ser un script grande). Ahora elimine todo el script que agrega las tablas y le debe dejar una secuencia de comandos para crear sus claves foráneas.

Haga una copia de esa secuencia de comandos porque es la forma de restaurar la base de datos a su estado actual. Use una búsqueda y reemplace para agregar ON DELETE CASCADE al final de cada restricción. Esto puede variar dependiendo de cómo estén configurados tus FK y es posible que debas hacer alguna edición manual.

Repita la generación de scripts, pero esta vez configúrelo para generar instrucciones DROP solamente. Asegúrese de eliminar manualmente las gotas de la tabla generadas. Ejecute las gotas, luego ejecute las creaciones editadas para hacer que todas sean en cascada al eliminar. Haga sus borrados, ejecute el guión drop nuevamente y luego ejecute el script que guardó al inicio.

También - ¡HAGA UNA COPIA DE SEGURIDAD DE SU BASE PRIMERO! Aunque solo sea una base de datos de desarrollo, le ahorrará algo de dolor de cabeza si parte de la secuencia de comandos no es del todo correcta.

Espero que esto ayude!

BTW - definitivamente debe hacer algunas pruebas con los datos de su prueba completa como sugirió otro afiche, pero puedo ver por qué es posible que no lo necesite para el desarrollo inicial. Simplemente no olvide incluir eso como parte de QA en algún momento.

7

A menos que desee mantener todas las consultas relacionadas propuestas por Chris, ON DELETE CASCADE es, de lejos, la solución más rápida y directa. Y si no quiere que sea permanente, ¿por qué no tienen un código T-SQL que se cambie esta opción dentro y fuera como aquí

  1. quitar el Tbl_A_MyFK restricción original (sin el ON DELETE CASCADE)

    ALTER TABLE Tbl_A DROP CONSTRAINT Tbl_A_MyFK

  2. establece la restricción Tbl_A_MyFK con el ON DELETE CASCADE

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

  3. Aquí usted puede hacer su borrado

    DELETE FROM Tbl_A WHERE ...

  4. deje caer su limitación Tbl_A_MyFK

    ALTER TABLE Tbl_A DROP CONSTRAINT Tbl_A_MyFK

  5. establecer la restricción Tbl_A_MyFK sin la ON DELETE CASCADE

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

1

después seleccione usted tiene que construir y ejecutar eliminar el actual

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

agregar esto después de seleccionar la instrucción – dan

2

Tomando un poco más la respuesta aceptada, tuve la necesidad de hacer esto a través de tablas de diferentes esquemas. He actualizado la secuencia de comandos para incluir el esquema en las secuencias de comandos de eliminación de salida.

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 post es incompleta, el T-SQL sp sólo imprime el comando, para ejecutar estos comandos, antes del último fin añadir esta

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 
5

Aquí hay una versión de la respuesta aceptada optimizado para baja densidad de población modelos de datos. Comprueba la existencia de datos en una cadena FK antes de agregarlo a la lista de eliminación.Lo uso para limpiar datos de prueba.

No lo utilice en un db transaccional activo: mantendrá los bloqueos demasiado tiempo.

/* 
-- ============================================================================ 
-- 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 
2

Expansión de la respuesta de croisharp para tomar en consideración los factores desencadenantes, es decir, la solución de esquema consciente de que desactiva todos los factores desencadenantes que afectan, elimina filas, y permite a los factores desencadenantes.

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 
0

Este script tiene dos problemas: 1. Se debe indicar la condición 1 = 1 con el fin de eliminar toda base de la mesa. 2. Esto crea las relaciones directas solo con la tabla base. Si la mesa final tiene otra relación tabla padre, el la eliminación fallará

Eliminar en [dbo]. [Tabla 2] DONDE TableID en (seleccione [ID] de [dbo]. [Cuadro 3], donde 1 = 1)

Si table2 tiene una tabla de relación primaria1

1

Publique aquí una secuencia de comandos que funcionará con claves externas que contienen más de una columna.

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 '[email protected]_name+'.'[email protected]_column_name+'='+ @referencing_table_name+'.'[email protected]_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 '[email protected]_name+' ON '[email protected]_name+'.'[email protected]_column_name+'='+ @referencing_table_name+'.'[email protected]_column_name+ @criteria, 
           @referencing_table_name 
           ) 
          --END 
          --ELSE 
          --BEGIN 
           --insert into @to_delete (criteria, table_name) 
           --VALUES(' LEFT JOIN '[email protected]_name+' ON '[email protected]_name+'.'[email protected]_column_name+'='+ @referencing_table_name+'.'[email protected]_column_name, 
           [email protected]_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 '[email protected] 
    exec (@Sql) 
    PRINT @Sql 

    -- Next record 
    set @id = @id - 1 
end 
end 
Cuestiones relacionadas