Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
AskSQLTeam
Ask SQLTeam Question
0 Posts |
Posted - 2002-04-04 : 08:17:06
|
This article comes to us from Tim Young. Tim writes "One of the (few) very handy things about Access is the cascade delete function. If you delete a record from a parent table, all relating records in the child tables are also deleted. I couldn’t find any way of doing this in SQL Server 7, so I wrote a stored procedure for it." Thanks for the article Tim! Article Link. |
|
rkc01
Starting Member
43 Posts |
Posted - 2002-04-08 : 20:31:38
|
Tim,I gave it a test run today. Nice work.rob |
|
|
d473566
Starting Member
23 Posts |
Posted - 2002-04-09 : 10:52:06
|
This is awesome- what a timesaver!! |
|
|
Brangwyn
Starting Member
5 Posts |
Posted - 2002-04-25 : 23:16:40
|
Just wanted to say this is fantastic ! this week I had to port a database from Sql2000 back to a sql7 installation, converting all of my cascading deletes to something else would have been a nightmare without this SP, thank you very much Tim !! |
|
|
Pinchio
Starting Member
1 Post |
Posted - 2002-05-13 : 21:09:16
|
Great article, but what about SQL2000, or does that version have this "casecade update/delete" feature built in?Also what if anything would need to change to build this into a stored procedure that is called from ASP.Again, great article. |
|
|
AjarnMark
SQL Slashing Gunting Master
3246 Posts |
Posted - 2002-05-14 : 15:57:48
|
SQL 2000 has Cascading Updates and Deletes built in. Version 7.0 did not. You can find more details in BOL.As for calling it from ASP, any stored procedure, including the one listed in the article can be execute from ASP. Look into the ADO Command object. |
|
|
daviddeldave
Starting Member
28 Posts |
Posted - 2002-09-23 : 11:56:42
|
Let me add myself as another appreciative member of SQL Team and for that lovely code which has been brilliant!!!!!David Mercer |
|
|
mustak_shaikh
Starting Member
1 Post |
Posted - 2002-09-26 : 23:55:56
|
Declare @row intSet @row = 1Set rowcount 1While @row > 0 Begin Delete t from (select a,count(a) as c from t group by a ) as E Where E.c > 1 and t.a = E.a Set @row = @@rowcount End |
|
|
GreySky
Starting Member
20 Posts |
Posted - 2003-04-10 : 17:11:46
|
I greatly appreciated your code on the SQL cascade delete, and indeed it works as advertised. Unfortunately, I found that if the cascade tree was deep, it took a considerable amount of time to perform the cascade.I updated the deleter to use a temporary table to hold the primary key values as it drills down the hierarchy. This avoids highly-nested Where [fld] In (...) statements.Following is my customized version that works *much* faster for me.Assumption:--All tables' primary keys are single keys of type int (unless the last table, such as an associative entity, that does not then cascade further)CREATE PROCEDURE spCascadeDeleteLong( -- this cascade deleter uses temporary tables to avoid deep nesting issues -- requires that tables have one primary key, and its type is int @cTableName varchar(75), -- name of the table where rows are to be deleted @cCriteria varchar(255), -- criteria used to delete the rows required @bDeleteTopHierarchy int, -- delete top hierarchy? @iLevel int = 0 -- execution level (do not pass this argument))ASset nocount ondeclare @cTab varchar(255), -- name of the child table @cCol varchar(255), -- name of the linking field on the child table @cRefTab varchar(255), -- name of the parent table @cRefCol varchar(255), -- name of the linking field in the parent table @cSQL varchar(255), -- query string passed to the sp_ExecuteSQL procedure @cChildCriteria varchar(255), -- criteria to be used to delete records from the child table @iLevelNew int -- new level (for recursive calling)-- prepare the temporary table holding the pk values of the called levelIF @iLevel = 0BEGIN -- build the temporary table Create Table #tblCascadeDelete (CallLevel int NOT NULL, PKValue int NOT NULL)END-- declare the cursor containing the foreign key constraint informationDECLARE cFKey CURSOR LOCAL FORSELECT SO1.name AS Tab, SC1.name AS Col, SO2.name AS RefTab, SC2.name AS RefColFROM dbo.sysforeignkeys FKINNER JOIN dbo.syscolumns SC1 ON FK.fkeyid = SC1.id AND FK.fkey = SC1.colidINNER JOIN dbo.syscolumns SC2 ON FK.rkeyid = SC2.id AND FK.rkey = SC2.colidINNER JOIN dbo.sysobjects SO1 ON FK.fkeyid = SO1.idINNER JOIN dbo.sysobjects SO2 ON FK.rkeyid = SO2.idWHERE SO2.Name = @cTableNameOPEN cFKeyFETCH NEXT FROM cFKey INTO @cTab, @cCol, @cRefTab, @cRefCol -- if an initial fetch was successful, then add the appropriate PK values to the temporary table IF @@FETCH_STATUS = 0 BEGIN SET @cSQL = 'INSERT INTO #tblCascadeDelete ( CallLevel, PKValue ) SELECT ' + Convert(varchar(3), @iLevel) + ' As CallLevel, [' + @cRefCol + '] As PKValue FROM [' + @cTableName + '] WHERE ' + @cCriteria EXEC (@cSQL) END -- only recurse if rows inserted IF @@RowCount > 0 BEGIN WHILE @@FETCH_STATUS = 0 BEGIN -- build the criteria to pass on for the next table SET @cChildCriteria = '[' + @cCol + '] IN (SELECT [PKValue] FROM #tblCascadeDelete Where [CallLevel] = ' + Convert(varchar(3), @iLevel) + ')' -- call this procedure to delete the child rows SET @iLevelNew = @iLevel + 1 EXEC spCascadeDeleteLong @cTab, @cChildCriteria, 1, @iLevelNew -- return the next values FETCH NEXT FROM cFKey INTO @cTab, @cCol, @cRefTab, @cRefCol END ENDCLOSE cFKeyDEALLOCATE cFKey-- delete the rows from this tableIF @bDeleteTopHierarchy <> 0BEGIN SET @cSQL = 'DELETE FROM [' + @cTableName + '] WHERE ' + @cCriteria EXEC (@cSQL)END-- drop the temporary table if top level, otherwise remove values from this level to allow reuseIF @iLevel = 0 BEGIN Drop Table #tblCascadeDelete ENDELSE BEGIN SET @cSQL = 'DELETE FROM #tblCascadeDelete WHERE CallLevel = ' + Convert(varchar(3), @iLevel) EXEC (@cSQL) END |
|
|
rrb
SQLTeam Poet Laureate
1479 Posts |
Posted - 2003-04-10 : 20:31:30
|
Even though SQL 2000 has cascade deletes, I still want to see a version of this from nr without using cursors- c'mon nigel!--I hope that when I die someone will say of me "That guy sure owed me a lot of money" |
|
|
GreySky
Starting Member
20 Posts |
Posted - 2003-04-14 : 13:09:57
|
Of course you could bypass the cursor by using a counter variable and a query that involves Select Top n ... ordered descending (or another variation including Fld > LastFldValue). But why? Why use complex SQL when a cursor is clearly more appropriate Edited by - GreySky on 04/14/2003 13:21:44 |
|
|
akak1701
Starting Member
2 Posts |
Posted - 2003-09-11 : 15:17:05
|
This works great except that I've run into a limitation with SQL Server. The database I'm working with is large in the number of tables and in the depth of the relationships. In fact, I've reached the limit for nested calls:Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32).Does anyone know how to change this value? If so it will make my life much easier.I also made changes to the following vars to prevent it from erroring out.@cCriteria nvarchar(4000)@cSQL nvarchar(4000)@cChildCriteria nvarchar(4000)Thanks,Greg |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2003-09-11 : 15:19:54
|
32 is the limit for both SQL Server 7.0 and SQL Server 2000. This is not configurable.Tara |
|
|
GreySky
Starting Member
20 Posts |
Posted - 2003-09-11 : 18:23:59
|
Which version are you using? Are you using the posted version that continuously builds longer nested In ( ... ) statements? You must be using that one if you had to extend the length of the criteria string to 4000. I can just imagine how slow that design would be on your database. OMG!You can use my version to solve your problem. For example, by essentially copying the code into the location where it recurses, you can double the *effective* stack to 64 levels.I feel for you. I'm just happy my client likes the version I created.David Atkins, MCP |
|
|
Wael
Starting Member
1 Post |
Posted - 2004-05-30 : 04:51:06
|
Hi,I am a .net developer with vert weak skills in SQL and hoping someone can help me in the following question.. I am using SQL Server 2000 with VS.NET 2003 I found Tim's Article on "Performing a Cascade Delete in SQL Server 7" So Here is the question:- I would like a generic stored procedure that will loop through all tables in my database and delete records from any table that has more than say 7 or 10 records ... so in other words I want to shrink all tables making sure they will have at least some data in them i.e. the first 7 to 10 records for each table but at the same time I would like to maintain the correct records accordingly as some tables are linked just like you explained in your article, is this possible, can you pls explain how. Also the reason I need this is simply because I have a big .NET project at work with huge database and I wanted to transfer some of the database (not all of it) to my computer at home so I can work from there too..if there is a work around this I'd really appreciate it if you let meknow.Thanks for your help in advance, Wael. |
|
|
Kristen
Test
22859 Posts |
Posted - 2004-05-30 : 05:45:55
|
quote: Originally posted by Wael Also the reason I need this is simply because I have a big .NET project at work with huge database and I wanted to transfer some of the database (not all of it) to my computer at home so I can work from there too..
Wouldn't it be easier, therefore, to transfer the 10 most-recent records from the Production database to your Home database? (rather than taking a DELETE type approach)I would just make a new, temporary, database; build a SQL script to copy relevant records, BACKUP the temporary database, RESTORE it at "Home" and then drop the temporary database.Presumably you have to worry about relationships between tables - so if you have Orders, Order Items and Products, you will transfer the TOP 10 Orders, ALL the Order Items that are associated, and then ALL the Products used on any of those order items.I can't see a way to easily generate a script that will do this AutoMagically, but it is not hard to create such a script manually - you will need to know which tables relate to which though.So, perhaps something like:Use GENERATE SQL first to SCRIPT the database, run the script on the TargetDatabase (then you will have all tables, foreign keys, etc.)Then copy the data across. Note that you will have to insert data in LOGICAL order, otherwise the FOREIGN KEY relationships will prevent it. However, I've structured the script below so it will only do each table ONCE, so if you just keep re-running the script it will fill in any missing gaps on sucessive passes until it is all there - at which point every INSERT will return zero rows, and you are done! (But getting them in the right order will mean it will run easier/faster/with few steps next time you need it)-- Get most recent 10 ordersINSERT INTO TargetDatabase.dbo.ORDERSSELECT TOP 10 *FROM SourceDatabase.dbo.ORDERSWHERE NOT EXISTS (SELECT * FROM TargetDatabase.dbo.ORDERS)ORDER BY OrderDate DESC-- Get Order Items for sample Order setINSERT INTO TargetDatabase.dbo.ORDER_ITEMSSELECT *FROM SourceDatabase.dbo.ORDER_ITEMS SJOIN TargetDatabase.dbo.ORDERS T ON S.OrderID = T.OrderIDWHERE NOT EXISTS (SELECT * FROM TargetDatabase.dbo.ORDER_ITEMS)-- Get Products for sample Order Item setINSERT INTO TargetDatabase.dbo.PRODUCTSSELECT *FROM SourceDatabase.dbo.PRODUCTS SJOIN TargetDatabase.dbo.ORDER_ITEMS T ON S.ProductID = T.ProductIDWHERE NOT EXISTS (SELECT * FROM TargetDatabase.dbo.PRODUCTS) Kristen |
|
|
sqlsavior
Starting Member
1 Post |
Posted - 2004-08-30 : 14:13:55
|
quote: Originally posted by AskSQLTeam This article comes to us from Tim Young. Tim writes "One of the (few) very handy things about Access is the cascade delete function. If you delete a record from a parent table, all relating records in the child tables are also deleted. I couldn’t find any way of doing this in SQL Server 7, so I wrote a stored procedure for it." Thanks for the article Tim!<P>Article <a href="/item.asp?ItemID=8595">Link</a>.
This is a cool procedure, unfortunately it does not handle composite foriegn keys correctly. The following test code shows this:create table parent(parent_id_1 int not null,parent_id_2 int not null)goalter table parent add constraint PK_parent primary key (parent_id_1, parent_id_2)gocreate table child(parent_id_1 int not null,parent_id_2 int not null,child_number int not null)goalter table child add constraint PK_Child primary key (parent_id_1, parent_id_2, child_number)goalter table child add constraint FK_Child_Parent foreign key (Parent_id_1, parent_id_2) references parent (parent_id_1, parent_id_2)gocreate table grandchild(grandchild_id int not null primary key IDENTITY,parent_id_1 int not null,parent_id_2 int not null,child_number int not null)goalter table grandchild add constraint FK_grandchild_child foreign key (parent_id_1, parent_id_2, child_number) references child (parent_id_1, parent_id_2, child_number)gocreate table great_grandchild(grandchild_id int not null,great_grandchild_number int not null)goalter table great_grandchild add constraint PK_great_grandchild primary key (grandchild_id, great_grandchild_number)goalter table great_grandchild add constraint FK_great_grandchild_grandchild foreign key (grandchild_id) references grandchild (grandchild_id)go-- delete alldelete great_grandchilddelete grandchilddelete childdelete parent-- add test records-- add genealogy 1insert parent (parent_id_1, parent_id_2) values (1, -1)insert child (parent_id_1, parent_id_2, child_number) values (1, -1, 1)insert child (parent_id_1, parent_id_2, child_number) values (1, -1, 2)declare @first_grandchild_id intinsert grandchild (parent_id_1, parent_id_2, child_number) values (1, -1, 1)select @first_grandchild_id = @@identityselect @first_grandchild_id as 'gen 1: first grandchild_id'declare @second_grandchild_id intinsert grandchild (parent_id_1, parent_id_2, child_number) values (1, -1, 2)select @second_grandchild_id = @@identityselect @second_grandchild_id as 'gen 1: second grandchild_id'insert great_grandchild (grandchild_id, great_grandchild_number) select @first_grandchild_id, 1insert great_grandchild (grandchild_id, great_grandchild_number) select @second_grandchild_id, 1-- add genealogy 2insert parent (parent_id_1, parent_id_2) values (100, -100)insert child (parent_id_1, parent_id_2, child_number) values (100, -100, 100)insert child (parent_id_1, parent_id_2, child_number) values (100, -100, 200)declare @first_grandchild_id intinsert grandchild (parent_id_1, parent_id_2, child_number) values (100, -100, 100)select @first_grandchild_id = @@identityselect @first_grandchild_id as 'gen 1: first grandchild_id'declare @second_grandchild_id intinsert grandchild (parent_id_1, parent_id_2, child_number) values (100, -100, 200)select @second_grandchild_id = @@identityselect @second_grandchild_id as 'gen 1: second grandchild_id'insert great_grandchild (grandchild_id, great_grandchild_number) select @first_grandchild_id, 100insert great_grandchild (grandchild_id, great_grandchild_number) select @second_grandchild_id, 100-- add genealogy 3insert parent (parent_id_1, parent_id_2) values (1, -100)insert child (parent_id_1, parent_id_2, child_number) values (1, -100, 1000)insert child (parent_id_1, parent_id_2, child_number) values (1, -100, 2000)declare @first_grandchild_id intinsert grandchild (parent_id_1, parent_id_2, child_number) values (1, -100, 1000)select @first_grandchild_id = @@identityselect @first_grandchild_id as 'gen 1: first grandchild_id'declare @second_grandchild_id intinsert grandchild (parent_id_1, parent_id_2, child_number) values (1, -100, 2000)select @second_grandchild_id = @@identityselect @second_grandchild_id as 'gen 1: second grandchild_id'insert great_grandchild (grandchild_id, great_grandchild_number) select @first_grandchild_id, 333insert great_grandchild (grandchild_id, great_grandchild_number) select @second_grandchild_id, 444select * from parentselect * from childselect * from grandchildselect * from great_grandchilddeclare @iRowsAffected intselect @irowsAffected = -1exec deleteRows 'parent', ' parent_id_1 = 1 and parent_id_2 = -1 ', @iRowsAffected OUTPUTselect @iRowsAffected as 'rows affected'-- note that now *ALL* grandchild and great_grandchild entries are gone...select * from parentselect * from childselect * from grandchildselect * from great_grandchildFred <dot> Williams <at> sqlsavior <dot> com |
|
|
daniel_crowther
Starting Member
2 Posts |
Posted - 2004-12-17 : 09:36:49
|
Hi Guys,My Christmas present to you all: "My solution to Cascade Delete problem"Note 1: however, does not handle self referencing FKs - who d'ya think I am: superman??? Note 2: to the guy who ran out of nest levels, do you think Note 1 might have something to do with it Note 3: if not, what are you trying to model: the WORLD??? Merry Christmas, hope it helps, Daniel Crowther (London UK) USE [<DBNAME>]GOIF OBJECT_ID('dbo.udfGetFullQualName') IS NOT NULL DROP FUNCTION dbo.udfGetFullQualNameGOCREATE FUNCTION dbo.udfGetFullQualName( @ObjectId INTEGER)RETURNS VARCHAR(300)ASBEGIN-- writen by Daniel Crowther 17 Dec 2004 primarily to support uspCascadeDelete (makes it more readable!!!) RETURN '[' + USER_NAME(OBJECTPROPERTY(@ObjectId, 'OwnerId')) + '].[' + OBJECT_NAME(@ObjectId) + ']'ENDGOIF OBJECT_ID('dbo.udfGetOnJoinClause') IS NOT NULL DROP FUNCTION dbo.udfGetOnJoinClauseGOCREATE FUNCTION dbo.udfGetOnJoinClause( @fkNameId INTEGER)RETURNS VARCHAR(1000)ASBEGIN-- writen by Daniel Crowther 16 Dec 2004 primarily to support uspCascadeDelete (makes it more readable!!!) DECLARE @OnClauseTemplate VARCHAR(1000) SET @OnClauseTemplate = '[<@pTable>].[<@pCol>] = [<@cTable>].[<@cCol>] AND ' DECLARE @str VARCHAR(1000) SET @str = '' SELECT /* fk_name = OBJECT_NAME(constid), -- constraint name cTableId = OBJECT_NAME(fkeyid), -- child table c_col_id = COL_NAME(fkeyid, fkey), -- child table column p_table_id = OBJECT_NAME(rkeyid), -- parent table p_col_id = COL_NAME(rkeyid, rkey) -- parent table column , */ @str = @str + REPLACE( REPLACE( REPLACE( REPLACE(@OnClauseTemplate, '<@pTable>', OBJECT_NAME(rkeyid) ), '<@pCol>', COL_NAME(rkeyid, rkey) ), '<@cTable>', OBJECT_NAME(fkeyid) ), '<@cCol>', COL_NAME(fkeyid, fkey) ) FROM dbo.sysforeignkeys fk WHERE fk.constid = @fkNameId --OBJECT_ID('FK_ProductArrearsMe_ProductArrears') RETURN LEFT(@str, LEN(@str) - LEN(' AND ') )ENDGOIF OBJECT_ID('dbo.uspCascadeDelete') IS NOT NULL DROP PROCEDURE dbo.uspCascadeDeleteGOCREATE PROCEDURE dbo.uspCascadeDelete @ParentTableId VARCHAR(300), -- can also take object_id!!! @WhereClause VARCHAR(2000), @ExecuteDelete CHAR(1) = 'N', @FromClause VARCHAR(8000) = '', @Level INTEGER = 0AS-- writen by Daniel Crowther 16 Dec 2004 - handles composite primary keysSET NOCOUNT ON/* Set up debug */DECLARE @DebugMsg VARCHAR(4000), @DebugIndent VARCHAR(50)SET @DebugIndent = REPLICATE('---', @@NESTLEVEL) + '> ' IF ISNUMERIC(@ParentTableId) = 0BEGIN -- assume owner is dbo and calculate id IF CHARINDEX('dbo.', @ParentTableId) = 0 SET @ParentTableId = OBJECT_ID('[dbo].[' + @ParentTableId + ']') ELSE SET @ParentTableId = OBJECT_ID(@ParentTableId)ENDIF @Level = 0BEGIN PRINT @DebugIndent + ' **************************************************************************' PRINT @DebugIndent + ' *** Cascade delete ALL data from ' + dbo.udfGetFullQualName(@ParentTableId) IF @ExecuteDelete = 'Y' PRINT @DebugIndent + ' *** @ExecuteDelete = Y *** deleting data...' ELSE PRINT @DebugIndent + ' *** Cut and paste output into another window and execute ***'ENDDECLARE @CRLF CHAR(2)SET @CRLF = CHAR(13) + CHAR(10)DECLARE @strSQL VARCHAR(4000)IF @Level = 0 SET @strSQL = 'SET NOCOUNT ON' + @CRLFELSE SET @strSQL = ''SET @strSQL = @strSQL + 'PRINT ''' + @DebugIndent + dbo.udfGetFullQualName(@ParentTableId) + ' Level=' + CAST(@@NESTLEVEL AS VARCHAR) + ''''IF @ExecuteDelete = 'Y' EXEC ( @strSQL )ELSE PRINT @strSQLDECLARE curs_children CURSOR LOCAL FORWARD_ONLYFOR SELECT DISTINCT fkNameId = constid, -- constraint name cTableId = fkeyid -- child table/* cColId = fkey, -- child table column pTableId = rkeyid, -- parent table pColId = rkey -- parent table column*/ FROM dbo.sysforeignkeys fk WHERE fk.rkeyid <> fk.fkeyid -- WE DO NOT HANDLE self referencing tables!!! AND fk.rkeyid = @ParentTableIdOPEN curs_children DECLARE @fkNameId INTEGER, @cTableId INTEGER, @cColId INTEGER, @pTableId INTEGER, @pColId INTEGERFETCH NEXT FROM curs_children INTO @fkNameId, @cTableId --, @cColId, @pTableId, @pColIdDECLARE @strFromClause VARCHAR(1000)DECLARE @nLevel INTEGERIF @Level = 0BEGIN SET @FromClause = 'FROM ' + dbo.udfGetFullQualName(@ParentTableId)ENDWHILE @@FETCH_STATUS = 0BEGIN SELECT @strFromClause = @FromClause + @CRLF + ' INNER JOIN ' + dbo.udfGetFullQualName(@cTableId) + @CRLF + ' ON ' + dbo.udfGetOnJoinClause(@fkNameId) SET @nLevel = @Level + 1 EXEC dbo.uspCascadeDelete @ParentTableId = @cTableId, @WhereClause = @WhereClause, @ExecuteDelete = @ExecuteDelete, @FromClause = @strFromClause, @Level = @nLevel SET @strSQL = 'DELETE FROM ' + dbo.udfGetFullQualName(@cTableId) + @CRLF + @strFromClause + @CRLF + 'WHERE ' + @WhereClause + @CRLF SET @strSQL = @strSQL + 'PRINT ''---' + @DebugIndent + 'DELETE FROM ' + dbo.udfGetFullQualName(@cTableId) + ' Rows Deleted: '' + CAST(@@ROWCOUNT AS VARCHAR)' + @CRLF + @CRLF IF @ExecuteDelete = 'Y' EXEC ( @strSQL ) ELSE PRINT @strSQL FETCH NEXT FROM curs_children INTO @fkNameId, @cTableId --, @cColId, @pTableId, @pColIdENDIF @Level = 0BEGIN SET @strSQL = @CRLF + 'PRINT ''' + @DebugIndent + dbo.udfGetFullQualName(@ParentTableId) + ' Level=' + CAST(@@NESTLEVEL AS VARCHAR) + ' TOP LEVEL PARENT TABLE''' + @CRLF SET @strSQL = @strSQL + 'DELETE FROM ' + dbo.udfGetFullQualName(@ParentTableId) + ' WHERE ' + @WhereClause + @CRLF SET @strSQL = @strSQL + 'PRINT ''' + @DebugIndent + 'DELETE FROM ' + dbo.udfGetFullQualName(@ParentTableId) + ' Rows Deleted: '' + CAST(@@ROWCOUNT AS VARCHAR)' + @CRLF IF @ExecuteDelete = 'Y' EXEC ( @strSQL ) ELSE PRINT @strSQLENDCLOSE curs_children DEALLOCATE curs_children GO/*-- Example 1EXEC uspCascadeDelete @ParentTableId = 'dbo.ProductClass', @WhereClause = 'ProductClass.Class = ''RTB2'''-- ,@ExecuteDelete = 'Y'-- Example 2EXEC uspCascadeDelete @ParentTableId = 'dbo.brand', @WhereClause = 'brand.brand_name <> ''Apple'''-- ,@ExecuteDelete = 'Y'exec uspCascadeDelete @ParentTableId = 'dbo.product_type', @WhereClause = 'product_type.product_type_id NOT IN (SELECT bpt.product_type_id FROM dbo.brand_product_type bpt)'-- ,@ExecuteDelete = 'Y'*/ Thanks,Daniel Crowther |
|
|
daniel_crowther
Starting Member
2 Posts |
Posted - 2004-12-17 : 09:38:42
|
BTW. My solution handles composite foreign key references - I knew there was something good about it!!!Enjoy!Thanks,Daniel Crowther |
|
|
Gooser187
Starting Member
1 Post |
Posted - 2009-12-09 : 14:43:56
|
quote: Originally posted by GreySky I greatly appreciated your code on the SQL cascade delete, and indeed it works as advertised. Unfortunately, I found that if the cascade tree was deep, it took a considerable amount of time to perform the cascade...
Tried this. Got:Msg 217, Level 16, State 1, Procedure spCascadeDeleteLong, Line 55Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32).v/rGooserhttp://www.CafePress.com/MerryCHRISTmass |
|
|
foobar11
Starting Member
2 Posts |
Posted - 2010-03-30 : 13:27:41
|
GreySky, thanks, your solution really got me going (the original one might fail due to too many nested subqueries). I added a "tablename"-column to the temptable, so cycles can be detected when setting the child-criteria (a simple subquery checking whether the current row has already been picked up on a lower call-level). Also, by casting the pk value to varchar (instead of int) I was able to mix all kinds of primary key types (guids, etc). |
|
|
Next Page
|
|
|
|
|