Der vorherige Blog Eintrag befasste sich mit dem Nachbau von "Create Or Alter" in MS_Sql-Server.
Da bei jener Lösung wird versucht, den Namen des Schema und den Namen des Objektes aus dem Statement zu parsen, was jedoch nur gelingt wenn das Statement einigermaßen vernünftig formatiert
wird.
Der nun zweite Vorschlag umgeht das Probelm, indem drei weitere Parameter eingeführt werden, in denen der Name des Schema, der Name des Typen des Datenbankobjektes und der Name des Objektes
angegeben werden muß. Dafür dürfen diese Angaben im SQL-Statement nicht mehr enthalten sein.
Im Kommentar am Anfang des Prozedur-textes werden verschiedene Kommentarkategorien in XML-Tags gesetzt, welche anschließend beim Beisepiel aus dem Quelltext der Prozedur kopiert weren, mit
XML-Query analysiert werden und aausgeben, bzw. ausgeführt werden.
USE master;
IF ( SELECT OBJECT_ID ('dbo.sp_CreateOrAlter', 'P') ) IS NOT NULL
DROP PROCEDURE dbo.sp_CreateOrAlter;
GO
/*=======================================================================================
<Created> 26.09.2009 by Eberhard Meisel 2009 by Eberhard Meisel All rights preserved"
</Created>
<Idea> 25.09.2009 by Olaf Helper: http://olafhelper.over-blog.de/article-36504172.html
</Idea>
<Purpose> Create or Alter an T-SQL-Database-Object in dependency of its existence.
</Purpose>
<Remarks> Procedure is created in the master database with prefix "sp_", so that it
can be called from every other database on the server.
So you must have the right to create database-objects in the master database.
</Remarks>
<Changelog>
-- 0001 03.10.2009 ENH EM Adding Documentation, Changelog and Example in XML
-- 0000 26.09.2009 ADD EM created
</Changelog>
<Example> -- Example for dbo.sp_CreateOrAlter
BEGIN TRANSACTION; SET NOCOUNT ON;
DECLARE @Debug BIT; Set @Debug = 1;
USE AdventureWorks ;
SELECT * FROM Sys.Objects WHERE Name = 'spTestSp';
EXEC sp_CreateOrAlter
@Schema = dbo
, @Object = spTestSp
, @Type = [PROCEDURE]
, @Sql =
N' ( @AddressID INTEGER = NULL
) AS
BEGIN; SELECT *
FROM Person.Address WHERE AddressID = @AddressID
OR @AddressID IS NULL; RETURN; END; -- EOF PROCEDURE dbo.spTestSp ' , @Dbg = @Debug ;
SELECT * FROM Sys.Objects WHERE Name = 'spTestSp'; EXEC dbo.spTestSp;
ROLLBACK TRANSACTION;
</Example> -- Example dbo.sp_CreateOrAlter */ --======================================================================================
BEGIN; SET NOCOUNT ON;
DECLARE @SchemaObject NVARCHAR(257);
SET @SchemaObject = PARSENAME (@Schema, 1) + NCHAR(46) + PARSENAME (@Object,1);
-- in dependency of existence of the object CREATE or ALTER the object
SET @Sql = CASE WHEN ( SELECT OBJECT_ID (@SchemaObject) ) IS NULL
THEN N'CREATE ' ELSE N'ALTER '
END + @Type +SPACE(1)+ @SchemaObject +SPACE(1)+NCHAR(10)+NCHAR(13)+ @Sql;
IF @Dbg != 0 -- Debug ouptut when Parameter @Dbg is not 0
SELECT CAST ( (SELECT N'ObjectName = ' + QUOTENAME(@SchemaObject)
+ NCHAR(13)+NCHAR(13) + @Sql FOR XML PATH ('')
) AS XML) AS [Debug (sp_CreateOrAlter)];
EXEC sp_executeSQL @Statement = @SQL; -- Execute the statement
END; -- EOF PROCEDURE sp_CreateOrAlter
GO
SET NOCOUNT ON;
DECLARE @Procid INTEGER; SET @Procid = OBJECT_ID ('master..sp_CreateOrAlter')
DECLARE @Comments TABLE
( Created NVARCHAR(128)
, Idea NVARCHAR(333)
, Purpose NVARCHAR(4000)
, Remarks NVARCHAR(4000)
, Example NVARCHAR(MAX)
, Changelog NVARCHAR(MAX)
);
DECLARE @Comment XML ;
SET @Comment =
( SELECT CAST (N'<Comments>' + Z.Comment + N'</Comments>' AS XML) AS Comment
FROM (SELECT CASE WHEN x.Start > 0
THEN SUBSTRING (x.Def, x.Start, x.[End]-X.Start)
ELSE 'No Comments found'
END AS Comment
FROM ( SELECT y.Def
, CHARINDEX (Y.STag, y.Def, 1) AS Start
, CHARINDEX (Y.ETag, y.Def, 1) + LEN (Y.ETag) AS [End]
FROM (SELECT OBJECT_Definition (@ProcID) AS Def
, N'<Created>' AS STag
, N'</Example>' AS ETag
) AS Y
) AS X
) AS Z
);
SELECT @Comment;
INSERT INTO @Comments
SELECT x.value(N'Created[1]' , N'NVARCHAR(128)') AS Created
, x.value(N'Idea[1]' , N'NVARCHAR(333)') AS Idea
, x.value(N'Purpose[1]' , N'NVARCHAR(4000)') AS Purpose
, x.value(N'Remarks[1]' , N'NVARCHAR(4000)') AS Remarks
, x.value(N'Example[1]' , N'NVARCHAR(MAX)') AS Example
, x.value(N'Changelog[1]' , N'NVARCHAR(MAX)') AS Changelog
FROM @Comment.nodes('//Comments') n(x);
DECLARE @Line SYSNAME ; SET @Line = REPLICATE (NCHAR(45), 100);
DECLARE @Test NVARCHAR(MAX);
SET @Test = @Line +NCHAR(13)
+ (SELECT N'-- Created: ' + Created FROM @Comments)+ + (SELECT N'-- Idea : ' + Idea FROM @Comments)+
+ (SELECT N'-- Purpose: ' + Purpose FROM @Comments)+
+ (SELECT N'-- Remarks: ' + REPLACE (SUBSTRING(Remarks, 1, LEN(Remarks)-1)
,NCHAR(10),NCHAR(13)+NCHAR(45)+NCHAR(45))
+ NCHAR(13) FROM @Comments)
+ @Line +NCHAR(13)
+ (SELECT Changelog FROM @Comments)+@Line;
PRINT @Test ;
SET @Test = REPLACE (REPLACE ( (SELECT Example FROM @Comments)
, NCHAR(10) , NCHAR(13))
,NCHAR(13)+NCHAR(13), NCHAR(13));
PRINT @Test;
EXEC sp_ExecuteSQL @Test;
GO
Kommentar hinzufügen - Kommentare () - empfehlen