sql >> Base de Datos >  >> RDS >> Database

Mejor ALTERAR que DROP

En este artículo, proporcionaré una construcción para eliminar un objeto antes de crearlo.

En nuestro equipo, hay una veintena de desarrolladores de SQL Ninja. Todos ellos describen esta construcción de diferentes maneras.

Nuestro equipo consta de una veintena de SQL Ninjas y todos ellos usan la siguiente declaración de una manera diferente:

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

O:

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

O:

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

En StackOverflow, a los usuarios les gustó esta versión:

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

Las estrellas están alineadas y encontré una implementación adecuada en uno de los sitios de SQL. Al principio, me sorprendió, pero luego la gente me ayudó a ver por qué funciona bien.

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

El punto es que si usa las declaraciones DROP y CREATE cada vez, entonces elimina los permisos del objeto. Además, el objeto puede estar en la replicación y también se eliminará una vez que se vuelva a crear.

Entonces, me gustó esta versión y decidí envolverla en dbo.antidrop procedimiento.

El procedimiento toma solo dos argumentos:el nombre del objeto y su tipo. Para verificar el tipo de objeto, ejecute la siguiente instrucción:

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

Así es como se verá:

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

Finalmente, el código del procedimiento es el siguiente:

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

¡Gracias por su atención!