Семь раз ALTER один DROP

от автора

image

Все началось с того, что я начал писать стандарт оформления T-SQL для своей компании. В этой теме я остановлюсь на конструкции удаления объекта перед его созданием.

В нашей команде порядка двадцати SQL Ninja разработчиков и все описывают данную конструкцию по разному, например вот так:

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


Или так:

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

И даже так:

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

А на StackOverflow больше всего лайков собрал вот такой вариант:

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 

Звезды пошли ко мне на встречу и наткнулся я на одном из SQL-сайтов на реализацию, которая по началу возмутила меня, но потом мне подсказали что с ней «так»:

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

Дело в том что если каждый раз делать DROP и CREATE, то удаляются права на объект, а еще объект может быть в репликации и при пересоздании, из неё он удалится тоже.

Вобщем мне понравился этот лямбда декоратор способ и я решил его инкапсулировать
в процедуру под названием dbo.antidrop.

У процедуры всего два аргумента, это имя объекта и его тип. Посмотреть тип своего объекта можно вот так:

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

Вот как это будет выглядеть по итогу:

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

Ну и конечно же код самой процедуры:

IF OBJECT_ID('dbo.antidrop', 'P') IS NOT NULL     DROP PROC dbo.antidrop; 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 BEGIN SELECT 1 END'');         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 ('IF', 'TF')     BEGIN         EXEC(@if_tf);     END      ELSE IF @type = 'FN'     BEGIN         EXEC(@fn);     END          ELSE IF @type = 'P'     BEGIN         EXEC(@p);     END      ELSE IF @type = 'V'     BEGIN         EXEC(@v);     END  END GO 

Спасибо за внимание!
ссылка на оригинал статьи https://habrahabr.ru/post/327566/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *