Necesito migrar una base de datos local de SQL Server 2017 a una base de datos SQL de Azure, y me enfrento a algunos desafíos ya que hay muchas limitaciones por superar.
En particular, dado que una base de datos SQL de Azure funciona solo en hora UTC (sin zonas horarias) y necesitamos la hora local, tenemos que cambiar el uso de GETDATE()
todas partes en la base de datos, lo que ha demostrado ser más trabajo de lo que esperaba.
Creé una función definida por el usuario para obtener la hora local que funciona correctamente para mi zona horaria:
CREATE FUNCTION [dbo].[getlocaldate]()
RETURNS datetime
AS
BEGIN
DECLARE @D datetimeoffset;
SET @D = CONVERT(datetimeoffset, SYSDATETIMEOFFSET()) AT TIME ZONE 'Pacific SA Standard Time';
RETURN(CONVERT(datetime,@D));
END
El problema con el que tengo problemas es cambiar realmente GETDATE()
con esta función en cada vista, procedimiento almacenado, columnas calculadas, valores predeterminados, otras restricciones, etc.
¿Cuál sería la mejor manera de implementar este cambio?
Estamos en la vista previa pública de instancias administradas . Todavía tiene el mismo problema GETDATE()
, por lo que no ayuda con este problema. Mudarse a Azure es un requisito. Esta base de datos se usa (y se usará) siempre en esta zona horaria.
Yo trabajaría al revés. Convierta todas sus marcas de tiempo en la base de datos a UTC, y simplemente use UTC y siga el flujo. Si necesita una marca de tiempo en una tz diferente, puede crear una columna generada utilizando
AT TIME ZONE
(como lo hizo anteriormente) que representa la marca de tiempo en esa TZ especificada (para la aplicación). Pero, consideraría seriamente que UTC volviera a la aplicación y escribiera esa lógica, la lógica de visualización, en la aplicación.fuente
En lugar de exportar, editar manualmente y volver a ejecutar, puede intentar hacer el trabajo directamente en la base de datos con algo como:
por supuesto, extenderlo para tratar funciones, disparadores, etc.
Hay algunas advertencias:
Es posible que deba ser un poco más brillante y lidiar con espacios en blanco diferentes / adicionales entre
CREATE
yPROCEDURE
/VIEW
/<other>
. En lugar deREPLACE
eso, es posible que prefiera dejar elCREATE
lugar en su lugar y ejecutarDROP
primero, pero esto corre el riesgo de dejar a sussys.depends
amigos fuera de lugar dondeALTER
no pueda, también siALTER
falla, al menos tiene el objeto existente todavía en su lugar donde conDROP
+CREATE
puede no.Si su código tiene algún olor "inteligente", como modificar su propio esquema con TSQL ad-hoc, entonces deberá asegurarse de que la búsqueda y el reemplazo de
CREATE
->ALTER
no interfieran con eso.Querrá probar la regresión de la (s) aplicación (es) completa (s) después de la operación, ya sea que use el cursor o los métodos exportar + editar + ejecutar.
He usado este método para hacer actualizaciones similares en todo el esquema en el pasado. Es un truco y se siente bastante feo, pero a veces es la forma más fácil / rápida.
Los valores predeterminados y otras restricciones también se pueden modificar de manera similar, aunque solo se pueden eliminar y recrear en lugar de modificar. Algo como:
Un poco más de diversión con la que puede que tenga que lidiar: si está haciendo particiones por tiempo, entonces esas partes también pueden necesitar modificaciones. Si bien la partición a tiempo de forma más granular que por día es poco frecuente, podría tener problemas en
DATETIME
los que la función de partición interpreta los s como el día anterior o siguiente, dependiendo de la zona horaria, dejando sus particiones sin alinear con sus consultas habituales.fuente
sys
esquema y modificar mediante programación.CREATE OR ALTER PROCEDURE
ayuda con algunos problemas de generación de código; aún puede haber problemas, ya que la definición almacenada se leeráCREATE PROCEDURE
(¡tres! espacios) y esto no se correspondeCREATE PROCEDURE
ni conCREATE OR ALTER PROCEDURE
... ._.CREATE
que no esté dentro de un comentario y lo reemplace. No he hecho esto / similar en el pasado, pero no tengo el código de la función a mano en este momento para publicar. O si puede garantizar que ninguna de sus definiciones de objeto tiene comentarios anterioresCREATE
, ignore el problema de los comentarios y solo busque y reemplace la primera instancia deCREATE
.Realmente me gusta la respuesta de David y voté por una forma programática de hacer las cosas.
Pero puede probar esto hoy para una prueba de ejecución en Azure a través de SSMS:
Haga clic derecho en su base de datos -> Tareas -> Generar secuencias de comandos ..
[Historia de fondo] tuvimos un DBA junior que actualizó todos nuestros entornos de prueba a SQL 2008 R2 mientras que nuestros entornos de producción estaban en SQL 2008. Es un cambio que me hace temblar hasta el día de hoy. Para migrar a producción, desde la prueba, tuvimos que generar scripts dentro de SQL, usando generar scripts, y en las opciones avanzadas usamos la opción 'Tipo de datos a script: esquema y datos' para generar un archivo de texto masivo. Pudimos mover con éxito nuestras bases de datos R2 de prueba a nuestros servidores SQL 2008 heredados, donde una restauración de la base de datos a una versión anterior no hubiera funcionado. Utilizamos sqlcmd para ingresar el archivo grande, ya que los archivos a menudo eran demasiado grandes para el búfer de texto SSMS.
Lo que digo aquí es que esta opción probablemente también funcione para usted. Solo tendrá que hacer un paso adicional y buscar y reemplazar getdate () con [dbo] .getlocaldate en el archivo de texto generado. (Sin embargo, pondría su función en la base de datos antes de la migración).
(Nunca quise ser competente en este curita de una restauración de la base de datos, pero por un tiempo se convirtió en una forma de facto de hacer las cosas. Y funcionó todo el tiempo).
Si elige esta ruta, asegúrese de seleccionar el botón Avanzado y seleccione todas las opciones que necesita (lea cada una) para pasar de la base de datos anterior a la nueva, como los valores predeterminados que mencionó. Pero dale algunas pruebas en Azure. Apuesto a que encontrarás que esta es una solución que funciona, con un mínimo de esfuerzo.
fuente
Observe los sysobjects comentados . Condición de columna de tipo. Mi script alterará solo el proceso y UDF.
Este script alterará todo lo
Default Constraint
que contengaGetDate()
fuente
He votado a favor de la respuesta de Evan Carrolls, ya que creo que esta es la mejor solución. No he podido convencer a mis colegas de que deberían cambiar mucho código C #, así que tuve que usar el código que escribió David Spillett. He solucionado un par de problemas con UDF, SQL dinámico y esquemas (no todo el código usa "dbo") como este:
y las restricciones predeterminadas como esta:
UDF
La sugerencia de usar un UDF que devuelva la fecha y la hora de hoy se ve bien, pero creo que todavía hay suficientes problemas de rendimiento con los UDF, por lo que he optado por usar la solución AT ZONA HORA muy larga y fea.
fuente