sql >> Database >  >> RDS >> Database

Beter ALTER dan DROP

In dit artikel ga ik een constructie geven voor het verwijderen van een object voordat het wordt gemaakt.

In ons team werken zo'n twintig SQL Ninja-ontwikkelaars. Ze beschrijven deze constructie allemaal op verschillende manieren.

Ons team bestaat uit zo'n twintig SQL Ninja's en ze gebruiken allemaal het volgende statement op een andere manier:

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

Of:

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

Of:

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 ..

Op StackOverflow vonden gebruikers deze versie leuk:

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

De sterren zijn uitgelijnd en ik vond een passende implementatie in een van de SQL-sites. In het begin was ik geschokt, maar toen hielpen mensen in te zien waarom het goed werkt.

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 ..

Het punt is dat als u elke keer de DROP- en CREATE-instructies gebruikt, u objectmachtigingen verwijdert. Bovendien kan het object zich in de replicatie bevinden en wordt het ook verwijderd zodra het opnieuw is gemaakt.

Dus ik vond deze versie leuk en besloot het in de dbo.antidrop . te stoppen procedure.

De procedure heeft slechts twee argumenten:objectnaam en zijn type. Voer de volgende instructie uit om het objecttype te controleren:

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

Hier is hoe het eruit zal zien:

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

Ten slotte is de code van de procedure als volgt:

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

Bedankt voor uw aandacht!


  1. Alleen database-back-ups in WHM

  2. Herstel de mysql-database vanuit .frm-bestanden

  3. Waarom kan ik geen aggregatiefunctie uitvoeren op een expressie die een aggregatie bevat, maar wel door er een nieuwe select-instructie omheen te maken?

  4. SQL Server datetime LIKE selecteren?