Database
 sql >> Datenbank >  >> RDS >> Database

Besser ALTER als DROP

In diesem Artikel werde ich eine Konstruktion zum Löschen eines Objekts bereitstellen, bevor es erstellt wird.

In unserem Team gibt es ungefähr zwanzig SQL Ninja-Entwickler. Alle beschreiben diese Konstruktion auf unterschiedliche Weise.

Unser Team besteht aus ungefähr zwanzig SQL-Ninjas und alle verwenden die folgende Anweisung auf unterschiedliche Weise:

IF OBJECT_ID('dbo.Function', 'TF') IS NOT NULL
	DROP FUNCTION dbo.Function;
GO
CREATE FUNCTION dbo.Function ..

Oder:

IF EXISTS (
    SELECT * 
    FROM sys.objects 
    WHERE name = 'Procedure'
        AND type = 'P' 
)
    DROP PROCEDURE dbo.Procedure;
GO
CREATE PROCEDURE dbo.Procedure ..

Oder:

IF EXISTS (
    SELECT 1
    FROM sys.objects 
    WHERE object_id = OBJECT_ID(N'dbo.Function')
        AND type IN (N'FN', N'IF', N'TF', N'FS', N'FT')
)
    DROP FUNCTION dbo.Function;
GO
CREATE FUNCTION dbo.Function ..

Auf StackOverflow mochten Benutzer diese Version:

IF EXISTS (
    SELECT * FROM sysobjects WHERE id = object_id(N'function_name') 
    AND xtype IN (N'FN', N'IF', N'TF')
)
    DROP FUNCTION function_name
GO

Die Sterne sind ausgerichtet und ich habe eine geeignete Implementierung in einer der SQL-Sites gefunden. Zuerst war ich schockiert, aber dann halfen mir die Leute zu sehen, warum es gut funktioniert.

IF OBJECT_ID('dbo.Function', 'TF') IS NULL
    EXEC('CREATE FUNCTION dbo.Function() RETURNS @t TABLE(i INT) BEGIN RETURN END');
GO
ALTER FUNCTION dbo.Function ..

Der Punkt ist, dass Sie Objektberechtigungen löschen, wenn Sie jedes Mal die Anweisungen DROP und CREATE verwenden. Außerdem kann sich das Objekt in der Replikation befinden und wird nach dem erneuten Erstellen ebenfalls gelöscht.

Diese Version gefiel mir also und ich beschloss, sie in dbo.antidrop einzupacken Verfahren.

Die Prozedur nimmt nur zwei Argumente entgegen:den Objektnamen und seinen Typ. Um den Objekttyp zu überprüfen, führen Sie die folgende Anweisung aus:

SELECT type 
FROM sys.objects 
WHERE name = 'Name'

So wird es aussehen:

EXEC dbo.antidrop('dbo.Name', 'FN');
GO
ALTER FUNCTION dbo.Name ..

Schließlich lautet der Code der Prozedur wie folgt:

IF OBJECT_ID('dbo.antidrop', 'P') IS NULL
    EXEC('CREATE PROC dbo.antidrop AS');
GO
CREATE PROC dbo.antidrop @name SYSNAME, @type SYSNAME
AS
BEGIN

    DECLARE @if_tf NVARCHAR(512) = '
        IF OBJECT_ID(''' + @name + ''', ''' + @type + ''') IS NULL
            EXEC(''CREATE FUNCTION ' + @name + '() RETURNS @t TABLE(i INT) BEGIN RETURN END'');
        GO
    ';
    DECLARE @fn NVARCHAR(512) = '
        IF OBJECT_ID(''' + @name + ''', ''' + @type + ''') IS NULL
            EXEC(''CREATE FUNCTION ' + @name + '(@i INT) RETURNS INT AS BEGIN RETURN @i + 1 END'');
        GO
    ';
    DECLARE @p NVARCHAR(512) = '
        IF OBJECT_ID(''' + @name + ''', ''' + @type + ''') IS NULL
            EXEC(''CREATE PROC ' + @name + 'AS'');
        GO
    ';
    DECLARE @v NVARCHAR(512) = '
        IF OBJECT_ID(''' + @name + ''', ''' + @type + ''') IS NULL
            EXEC(''CREATE VIEW ' + @name + ' AS SELECT 1 AS i'');
        GO
    ';

    IF @type in (N'IF', N'TF')
    BEGIN
        EXEC(@if_tf);
    END

    ELSE IF @type = N'FN'
    BEGIN
        EXEC(@fn);
    END
    
    ELSE IF @type = N'P'
    BEGIN
        EXEC(@p);
    END

    ELSE IF @type = N'V'
    BEGIN
        EXEC(@v);
    END

END
GO

Vielen Dank für Ihre Aufmerksamkeit!