2009-10-29 22 views
40

Cuando se trata de crear procedimientos almacenados, vistas, funciones, etc., ¿es mejor hacer un DROP ... CREATE o un ALTER sobre el objeto?DROP ... CREAR vs ALTER

He visto numerosos documentos de "estándares" indicando hacer una GOTA ... CREAR, pero he visto numerosos comentarios y argumentos que abogan por el método ALTER.

El método ALTER conserva la seguridad, mientras que he escuchado que el método DROP ... CREAR fuerza una recompilación en todo el SP la primera vez que se ejecuta en lugar de solo una recompilación de nivel de instrucciones.

¿Puede alguien decirme por favor si hay otras ventajas/desventajas de usar uno sobre el otro?

+0

Seguimiento pregunta: ¿es DROP ... CREAR todavía atómica? Asumo que ALTER es atómico ya que es una declaración única, pero vale la pena verificar esto también. – gzak

Respuesta

37

ALTER forzará también la recompilación de todo el procedimiento. La compilación del nivel de estado de cuenta se aplica a las declaraciones dentro de los procedimientos, ej. un único SELECT, que se recompila porque las tablas subyacentes cambian, sin ningún cambio en el procedimiento. Ni siquiera sería posible recompilar selectivamente solo ciertas afirmaciones sobre el procedimiento ALTER, con el fin de comprender lo que cambió en el texto SQL después de un procedimiento ALTER que el servidor debería ... compilar.

Para todos los objetos, ALTER siempre es mejor porque conserva toda la seguridad, todas las propiedades extendidas, todas las dependencias y todas las restricciones.

+0

Errores corregidos: "stetemnts" a "declaraciones" –

+2

+1 Aborda las dos preocupaciones/puntos que planteé en la pregunta. – NYSystemsAnalyst

8

La alteración es generalmente mejor. Si suelta y crea, puede perder los permisos asociados con ese objeto.

+0

Nono! WITH RECOMPILE le dice a SQL Server que elimine el plan de consulta en ** cada ejecución ** del sproc. Todos los ALTERS dan como resultado la recompilación cuando el sproc se ejecuta a continuación. – Andomar

+0

En defensa de Andomar, alteré la respuesta, después de que él hiciera un comentario. Él escribe, y yo estaba respondiendo a una parte diferente de la pregunta y mi respuesta no estaba clara. – kemiller2002

0

Ha hecho una pregunta específicamente relacionada con los objetos de BD que no contienen ningún dato y, teóricamente, no debería modificarse con tanta frecuencia.

Es probable que necesite editar estos objetos pero no cada 5 minutos. Debido a esto, creo que ya has golpeado el martillo en la cabeza, permisos.

Respuesta corta, no es un problema, siempre y cuando los permisos no son un problema

48

Esto es cómo lo hacemos:

if object_id('YourSP') is null 
    exec ('create procedure dbo.YourSP as select 1') 
go 
alter procedure dbo.YourSP 
as 
... 

El código crea un "trozo" procedimiento almacenado si él doesn todavía existe, de lo contrario hace un alter. De esta forma, se conservan los permisos existentes sobre el procedimiento, incluso si ejecuta el script de forma repetida.

+1

+1 buen truco .. –

+4

Mejor hacer object_id ('dbo.YourSP') de lo contrario, puede terminar ALTERing una tabla que no existe, excepto con otro propietario – MartW

+8

CREAR O ALTER sería realmente bueno para SQL Server .... ... –

-1

Desde el punto de vista de la usabilidad, un drop and create es mejor que un alter. Alter fallará en una base de datos que no contenga ese objeto, pero que tenga un IF EXISTS DROP y luego un CREATE funcionará en una base de datos con el objeto ya existente o en una base de datos donde el objeto no existe. En Oracle y PostgreSQL normalmente crea funciones y procedimientos con la instrucción CREATE OR REPLACE que hace lo mismo que un SQL SERVER IF EXISTS DROP y luego un CREATE. Sería bueno si SQL Server recogiera esta sintaxis pequeña pero muy útil.

Así es como lo haría. Pon todo esto en una secuencia de comandos para un objeto dado.

IF EXISTS (SELECT 1 
      FROM information_schema.routines 
      WHERE routine_schema = 'dbo' 
       AND routine_name = '<PROCNAME' 
       AND routine_type = 'PROCEDURE') 
BEGIN 
    DROP PROCEDURE <PROCNAME> 
END 
GO 


CREATE PROCEDURE <PROCNAME> 
AS 
BEGIN 
END 
GO 

GRANT EXECUTE ON <PROCNAME> TO <ROLE> 
GO 
+0

¿Puedes explicar el -1? Tengo curiosidad de cómo esto no tiene valor? – Kuberchaun

+1

Creo que obtuviste un -1 porque tu declaración fue refutada en una pregunta diferente. Básicamente, alguien no estuvo de acuerdo contigo. – jcollum

1

Si tiene una función/proceso almacenado que se llama con frecuencia de un sitio web, por ejemplo, puede causar problemas.

El proceso almacenado se eliminará durante unos milisegundos/segundos, y durante ese tiempo, todas las consultas fallarán.

Si realiza una modificación, no tiene este problema.

Las plantillas para el procedimiento almacenado recién creado son por lo general esta forma:

IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = '<name>') 
    BEGIN 
     DROP PROCEDURE <name> 
    END 
GO 

CREATE PROCEDURE <name> 
...... 

Sin embargo, lo contrario es mejor, la OMI:

Si no existe la storedproc/función/etc, lo crea con una declaración de selección ficticia. Entonces, el alter siempre funcionará, nunca se descartará.

Tenemos un procedimiento almacenado para eso, por lo que nuestros procedimientos almacenados/funciones generalmente como esto:

EXEC Utils.pAssureExistance 'Schema.pStoredProc' 
GO 

ALTER PROCECURE Schema.pStoredProc 
... 

y utilizamos el mismo procedimiento almacenado para funciones:

EXEC Utils.pAssureExistance 'Schema.fFunction' 
GO 

ALTER FUNCTION Schema.fFunction 
... 

En Utils.pAssureExistance hacemos una IF y vemos el primer caracter después del ".": si es una "f", creamos una función ficticia, si es "p", creamos un proceso almacenado ficticio.

Tenga cuidado, si crea una función escalar ficticia, y su ALTER está en una función con valores de tabla, ALTER FUNCTION fallará, diciendo que no es compatible.

Una vez más, Utils.pAssureExistance puede ser práctico, con un parámetro opcional adicional

EXEC Utils.pAssureExistance 'Schema.fFunction', 'TableValuedFunction' 

creará una función con valores de tabla ficticia,

Adicionalmente, puede que me equivoque, pero creo que si hacer un procedimiento de caída y una consulta actualmente está utilizando el proceso almacenado, fallará.

Sin embargo, un procedimiento alternativo esperará a que todas las consultas dejen de usar el proceso almacenado y luego lo modifique. Si las consultas "bloquean" el proceso almacenado durante demasiado tiempo (digamos un par de segundos), el ALTER dejará de esperar el bloqueo y alterará el proceso almacenado de todos modos: las consultas que usan el proceso almacenado probablemente fallarán en ese punto.

+0

¿por qué no simplemente marca "sys.procedures" en lugar de usar sysobjects (que está en desuso) y tener que especificar el tipo? –

+0

"sysobjects" está en desuso a partir de SQL Server 2008: http://msdn.microsoft.com/en-us/library/ms143729.aspx –

+0

bien ... Creé un proceso almacenado utilizando la plantilla de SQL Server 2008, y copiar-pegarlo. ¡Microsoft debería seguir sus propias pautas, supongo! – Kevin

0

DROP generalmente pierde permisos Y cualquier propiedad extendida.

En algunas UDF, ALTER también perderá propiedades extendidas (definitivamente en las funciones SQL Server 2005 con valores de tabla de varias sentencias).

Normalmente no hago DROP y CREATE a menos que también esté recreando esas cosas (o sepa que quiero perderlas).

0

Solíamos utilizar alter mientras estábamos trabajando en el desarrollo ya sea creando nuevas funcionalidades o modificando la funcionalidad. Cuando terminamos con nuestro desarrollo y prueba, haríamos un drop y crearíamos. Esto modifica la marca de fecha y hora en los procesos para que pueda ordenarlos por fecha/hora.

También nos permitió ver lo que estaba entretenido por fecha para cada entregable que enviamos.

1

No sé si es posible hacer un comentario tan general y decir "ALTER is better". Creo que todo depende de la situación. Si necesita este tipo de permiso granular hasta el nivel de procedimiento, probablemente deba manejar esto en un procedimiento separado. Hay beneficios de tener que dejar caer y recrear.Limpia la seguridad existente y restablece lo que es predecible.

Siempre he preferido usar drop/recrear. También me pareció más fácil almacenarlos en control de fuente. En lugar de hacer .... si existe, hazlo y si no existe, crea.

Con eso dicho ... si sabes lo que estás haciendo ... no creo que importe demasiado.

0

Añadir con una gota si existe es mejor porque si tiene varios entornos cuando mueve la secuencia de comandos a QA o prueba o prueba, no sabe si la secuencia de comandos ya existe en ese entorno. Al agregar una gota (si ya existe) y luego agregar, estará cubierto independientemente de si existe o no. Luego debe volver a aplicar los permisos, pero es mejor que escuchar el script de instalación sin errores.

0

Comenzando con SQL Server 2016 SP1, ahora tiene la opción de utilizar la sintaxis CREATE OR ALTER para procedimientos almacenados, funciones, disparadores y vistas. Consulte CREATE OR ALTER – another great language enhancement in SQL Server 2016 SP1 en el blog del Motor de base de datos de SQL Server. Por ejemplo:

CREATE OR ALTER PROCEDURE dbo.MyProc 
AS 
BEGIN 
    SELECT * FROM dbo.MyTable 
END;