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 |
Henrik Svensson
Starting Member
25 Posts |
Posted - 2009-06-25 : 08:48:42
|
Hi!I'm sure this must have been done by someone. In our system we use transactional replication in SQL Server 2005 and I'm trying to build a T-SQL template for DDL changes that cannot be done without removing an article from its publication, such as changing the name of a primary key column. A requirement is that all subscriptions on the publication must be deleted before applying this script. So, what I need is a script template to:1. Select, and store in a temporary table for example, all article properties for the table in question.2. Remove the article from the publication.3. Make the DDL changes4. Add the article to the publication with the exact same settings as it had before, using the stored information from step 1 above (we don't use column filters in this case, so column level information is not important).I know there is a sysarticles view, but since there is no 1:1 correlation between sp_addarticle and the contents in sysarticles and the fact that not all parameters in sp_addarticle are present in sysarticles something more is also needed. If anyone has any suggestions or links to provide I would be very grateful. Thanks in advance.With best regards,Henrik Svensson-----"Rhubarb, that is Barbapapa backwards. It's called a palindrome." |
|
Henrik Svensson
Starting Member
25 Posts |
Posted - 2009-08-17 : 09:16:17
|
Here is one type of solution. Perhaps someone facing the same problem might have at least some use of it...------------------------------8<------------------------------/*Template script for making DDL changes to ONE article in ONE publication.The template code retreives the article properties and stores them in a temporary tableand then re-adds the article to its publication after the DDL changes have been applied.The DDL changes need to be added manually.Instructions:- Locate the row starting with "SET @TableName = 'tableName'" and set the table name.- Add code with DDL changes in the "Put your DDL changes here" section.NOTE: This script will not work if the same table is included as an article in several publications.This script will not work if column level filters are set on the article.This script will not work if the article name and table name differ.*/SET NOCOUNT ONIF EXISTS (SELECT * FROM tempdb..sysobjects WHERE name LIKE '#helparticle%' AND type = 'U') DROP TABLE #helparticleGOIF EXISTS (SELECT * FROM tempdb..sysobjects WHERE name LIKE '#helppublication%' AND type = 'U') DROP TABLE #helppublicationGOCREATE TABLE #helppublication (publication_name sysname, table_id int)GOCREATE TABLE #helparticle ( [article id] int PRIMARY KEY CLUSTERED, [article name] sysname NULL, [base object] nvarchar(257) NULL, [destination object] sysname NULL, [synchronization object] nvarchar(257) NULL, [type] smallint NULL, [status] tinyint NULL, [filter] nvarchar(257) NULL, [description] nvarchar(255) NULL, [insert_command] nvarchar(255) NULL, [update_command] nvarchar(255) NULL, [delete_command] nvarchar(255) NULL, [creation script path] nvarchar(255) NULL, [vertical partition] bit NULL, [pre_creation_cmd] tinyint NULL, [filter_clause] ntext NULL, [schema_option] binary(8) NULL, [dest_owner] sysname NULL, [source_owner] sysname NULL, [unqua_source_object] sysname NULL, [sync_object_owner] sysname NULL, [unqualified_sync_object] sysname NULL, [filter_owner] sysname NULL, [unqua_filter] sysname NULL, [auto_identity_range] int NULL, [publisher_identity_range] int NULL, [identity_range] bigint NULL, [threshold] bigint NULL, [identityrangemanagementoption] int NULL, [fire_triggers_on_snapshot] bit NULL)GODECLARE @TableName sysnameDECLARE @TableIsPublished bitDECLARE @TableId intSET @TableName = 'tableName' -- set name of table that needs to be removed from, modified, and then added to publication (if published).SELECT @TableIsPublished = is_published, @TableId = [object_id]FROM sys.objects WHERE name = @TableName AND type = 'U'IF @TableIsPublished = 1 BEGIN DECLARE @creation_script nvarchar(255) DECLARE @del_cmd nvarchar(255) DECLARE @description nvarchar(255) DECLARE @dest_table sysname DECLARE @filter int DECLARE @filter_clause sysname DECLARE @ins_cmd nvarchar(255) DECLARE @name sysname DECLARE @objid int DECLARE @pubid int DECLARE @pre_creation_cmd tinyint DECLARE @status tinyint DECLARE @sync_objid int DECLARE @type tinyint DECLARE @upd_cmd nvarchar(255) DECLARE @schema_option binary(8) DECLARE @dest_owner sysname DECLARE @ins_scripting_proc int DECLARE @del_scripting_proc int DECLARE @upd_scripting_proc int DECLARE @custom_script nvarchar(2048) DECLARE @fire_triggers_on_snapshot_bit bit DECLARE @fire_triggers_on_snapshot_nvarchar5 nvarchar(5) DECLARE @PublicationName sysname SELECT @PublicationName = syspub.name FROM sysarticles sysart INNER JOIN syspublications syspub ON sysart.pubid = syspub.pubid WHERE sysart.[objid] = @TableId INSERT INTO #helparticle EXEC sp_helparticle @PublicationName, @TableName ALTER TABLE #helparticle ADD publication_name sysname NULL, article_dropped bit INSERT INTO #helppublication SELECT @PublicationName, @TableIdENDELSEBEGIN ALTER TABLE #helparticle ADD publication_name sysname NULL, article_dropped bit ENDGOIF EXISTS (SELECT * FROM #helparticle)BEGIN DECLARE @PublicationName sysname DECLARE @TableId int DECLARE @TableName sysname SELECT @PublicationName = publication_name FROM #helppublication SELECT @TableId = table_id FROM #helppublication SELECT @TableName = name FROM sys.objects WHERE [object_id] = @TableId UPDATE #helparticle SET publication_name = @PublicationName, article_dropped = 0 IF EXISTS (SELECT * FROM syssubscriptions syssub INNER JOIN sysarticles sysart ON sysart.artid = syssub.artid WHERE sysart.[objid] = @TableId) BEGIN PRINT 'Table "'+@TableName+'" is included in publication "'+@PublicationName+'" that has at least one subscriber. Drop subscription(s) manually, then re-run this script.' UPDATE #helparticle SET article_dropped = 0 END ELSE BEGIN PRINT 'Dropping article '+@TableName+'.' EXEC sp_droparticle @publication = @PublicationName, @article = @TableName UPDATE #helparticle SET article_dropped = 1 ENDENDGO------------------------------------------------------------ Put your DDL changes here (and other changes, e.g. code to temporary store data to add after table changes have been applied). -- IMPORTANT: Check if article was dropped within EACH batch by using "IF EXISTS (SELECT * FROM #helparticle WHERE article_dropped = 1) OR NOT EXISTS (SELECT * FROM #helparticle) BEGIN [...] END"------------------------------------------------------------- Add article again:DECLARE @publication_name sysnameDECLARE @type sysnameDECLARE @article sysnameDECLARE @destination_table sysnameDECLARE @source_object sysnameDECLARE @vertical_partition nvarchar(5)DECLARE @filter nvarchar(257)DECLARE @sync_object nvarchar(257)DECLARE @ins_cmd nvarchar(255)DECLARE @upd_cmd nvarchar(255)DECLARE @del_cmd nvarchar(255)DECLARE @creation_script nvarchar(255)DECLARE @pre_creation_cmd nvarchar(10) DECLARE @filter_clause nvarchar(max)DECLARE @schema_option binary(8)DECLARE @destination_owner sysnameDECLARE @status tinyintDECLARE @source_owner sysnameDECLARE @sync_object_owner sysnameDECLARE @filter_owner sysnameDECLARE @auto_identity_range nvarchar(5)DECLARE @pub_identity_range bigintDECLARE @identity_range bigintDECLARE @threshold bigintDECLARE @force_invalidate_snapshot bitDECLARE @use_default_datatypes bitDECLARE @identityrangemanagementoption nvarchar(10)DECLARE @publisher sysnameDECLARE @fire_triggers_on_snapshot nvarchar(5)DECLARE @description nvarchar(255)IF EXISTS (SELECT * FROM #helparticle WHERE article_dropped = 1) BEGIN SELECT @publication_name = publication_name, @article = [article name], @destination_table = [destination object], @source_object = [unqua_source_object], @filter = [filter], @description = @description, --special case: this variable should be NULL if sync_object was automatically created, which will give it the prefix "syncobj_", so we look for that string on the line below: @sync_object = CASE WHEN [synchronization object] IS NOT NULL THEN CASE WHEN CHARINDEX('syncobj_',[synchronization object]) <> 0 THEN NULL ELSE [synchronization object] END ELSE [synchronization object] END, @ins_cmd = [insert_command], @upd_cmd = [update_command], @del_cmd = [delete_command], @creation_script = [creation script path], @filter_clause = [filter_clause], @schema_option = [schema_option], @destination_owner = [dest_owner], @status = [status], @source_owner = [source_owner], @pub_identity_range = [publisher_identity_range], @identity_range = [identity_range], @threshold = [threshold], @force_invalidate_snapshot = 1, --in this case we have already dropped the subscriptions, so there must be a new snapshot in any case. @use_default_datatypes = 1, --only of interest when publishing from Oracle @publisher = NULL --we only use SQL Servers as publishers, so this parameter should be set to NULL. FROM #helparticle IF NOT @sync_object IS NULL SELECT @sync_object_owner = [sync_object_owner] FROM #helparticle ELSE SET @sync_object_owner = NULL IF NOT @filter IS NULL SELECT @filter_owner = [filter_owner] FROM #helparticle ELSE SET @filter_owner = NULL IF 1 = (SELECT [vertical partition] FROM #helparticle) SET @vertical_partition = 'true' ELSE SET @vertical_partition = 'false' IF 1 = (SELECT [fire_triggers_on_snapshot] FROM #helparticle) SET @fire_triggers_on_snapshot = 'true' ELSE SET @fire_triggers_on_snapshot = 'false' SELECT @type = CASE WHEN [type] = 1 THEN 'logbased' WHEN [type] = 3 THEN 'logbased manualfilter' WHEN [type] = 5 THEN 'logbased manualview' WHEN [type] = 7 THEN 'logbased manualboth' WHEN [type] = 8 THEN 'proc exec' WHEN [type] = 24 THEN 'serializable proc exec' WHEN [type] = 32 THEN 'proc schema only' WHEN [type] = 64 THEN 'view schema only' WHEN [type] = 128 THEN 'func schema only' ELSE 'logbased' --default END FROM #helparticle SELECT @pre_creation_cmd = CASE WHEN [pre_creation_cmd] = 0 THEN 'none' WHEN [pre_creation_cmd] = 1 THEN 'delete' WHEN [pre_creation_cmd] = 2 THEN 'drop' WHEN [pre_creation_cmd] = 3 THEN 'truncate' ELSE 'drop' --default END FROM #helparticle SELECT @auto_identity_range = CASE WHEN [auto_identity_range] = 1 THEN 'true' WHEN [auto_identity_range] = 0 THEN 'false' ELSE NULL END FROM #helparticle SELECT @identityrangemanagementoption = CASE WHEN identityrangemanagementoption = 0 THEN 'none' WHEN identityrangemanagementoption = 1 THEN 'manual' WHEN identityrangemanagementoption = 2 THEN 'auto' ELSE NULL --default END FROM #helparticle PRINT 'Adding article ' + @article + '.' EXEC sp_addarticle @publication = @publication_name, @article = @article, @source_table = NULL, --do not use, use source_object instead @destination_table = @destination_table, @vertical_partition = @vertical_partition, @type = @type, @filter = @filter, @sync_object = @sync_object, @ins_cmd = @ins_cmd, @del_cmd = @del_cmd, @upd_cmd = @upd_cmd, @creation_script = @creation_script, @description = @description, @pre_creation_cmd = @pre_creation_cmd, @filter_clause = @filter_clause, @schema_option = @schema_option, @destination_owner = @destination_owner, @status = @status, @source_owner = @source_owner, @sync_object_owner = @sync_object_owner, @filter_owner = @filter_owner, @source_object = @source_object, @artid = NULL, @auto_identity_range = @auto_identity_range, @pub_identity_range = @pub_identity_range, @identity_range = @identity_range, @threshold = @threshold, @force_invalidate_snapshot = @force_invalidate_snapshot , @use_default_datatypes = @use_default_datatypes, @identityrangemanagementoption = @identityrangemanagementoption, @publisher = @publisher, @fire_triggers_on_snapshot = @fire_triggers_on_snapshotENDIF EXISTS (SELECT * FROM tempdb..sysobjects WHERE name LIKE '#helparticle%' AND type = 'U') DROP TABLE #helparticleGOIF EXISTS (SELECT * FROM tempdb..sysobjects WHERE name LIKE '#helppublication%' AND type = 'U') DROP TABLE #helppublicationGO------------------------------>8------------------------------With best regards,Henrik Svensson-----"Rhubarb, that is Barbapapa backwards. It's called a palindrome." |
|
|
|
|
|
|
|