Lam*_*mak 27 sql-server azure-sql-database sql-server-2017
我需要将本地 SQL Server 2017 数据库迁移到 Azure SQL 数据库,但我面临着一些挑战,因为要克服很多限制。
特别是,由于 Azure SQL 数据库仅在 UTC 时间(无时区)下工作,而我们需要本地时间,因此我们必须更改数据库中GETDATE() 各处的使用,事实证明,这比我预期的要多。
我创建了一个用户定义的函数来获取适合我的时区的本地时间:
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
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是GETDATE()在每个视图、存储过程、计算列、默认值、其他约束等中实际更改此函数。
实施此更改的最佳方法是什么?
我们正处于托管实例的公共预览版中。它仍然有同样的问题GETDATE(),所以它对这个问题没有帮助。迁移到 Azure 是一项要求。这个数据库总是在这个时区使用(并将被使用)。
AMG*_*AMG 17
使用 SQL Server 工具将数据库对象定义导出到 SQL 文件,其中应包括:表、视图、触发器、SP、函数等
使用任何允许您查找文本"GETDATE()"并将其替换为的文本编辑器编辑 SQL 文件(首先进行备份)"[dbo].[getlocaldate]()"
在 Azure SQL 中运行编辑的 SQL 文件以创建数据库对象...
执行数据迁移。
您可以在此处获得 azure 文档中的参考:Generating Scripts for SQL Azure
Eva*_*oll 15
实施此更改的最佳方法是什么?
我会反过来工作。将数据库中的所有时间戳转换为 UTC,只需使用 UTC 即可。如果您需要不同 tz 中的时间戳,您可以使用AT TIME ZONE(如上所述)创建一个生成的列,该列在指定的 TZ(对于应用程序)中呈现时间戳。但是,我会认真考虑让 UTC 返回到应用程序,并在应用程序中编写该逻辑 - 显示逻辑。
与其导出、手动编辑和重新运行,您还可以尝试直接在数据库中执行以下操作:
DECLARE C CURSOR FOR
SELECT sm.definition, so.type
FROM sys.objects so
JOIN sys.all_sql_modules sm ON sm.object_id = so.object_id
WHERE so.type IN ('P', 'V')
ORDER BY so.name
DECLARE @SQL NVARCHAR(MAX), @ojtype NVARCHAR(MAX)
OPEN C
FETCH NEXT FROM C INTO @SQL, @ojtype
WHILE @@FETCH_STATUS = 0 BEGIN
IF @objtype = 'P' SET @SQL = REPLACE(@SQL, 'CREATE PROCEDURE', 'ALTER PROCEDURE')
IF @objtype = 'V' SET @SQL = REPLACE(@SQL, 'CREATE VIEW' , 'ALTER VIEW' )
SET @SQL = REPLACE(@SQL, 'GETDATE()', '[dbo].[getlocaldate]()')
--PRINT @SQL
EXEC (@SQL)
FETCH NEXT FROM C INTO @SQL, @ojtype
END
CLOSE C
DEALLOCATE C
Run Code Online (Sandbox Code Playgroud)
当然扩展它来处理函数、触发器等等。
有几个注意事项:
您可能需要有点明亮和处理之间的不同/额外的空格CREATE和PROCEDURE/ VIEW/ <other>。而不是REPLACE为您可能更愿意代替离开CREATE的地方,执行DROP第一,但这个风险让sys.depends朋友外出失衡的地方ALTER可能没有,也如果ALTER失败,你至少可以替代现有的对象仍然在那里与DROP+CREATE你可能不是。
如果你的代码有任何“聪明”的味道,比如用临时 TSQL 修改自己的架构,那么你需要确保搜索和替换CREATE->ALTER不会干扰它。
无论您使用游标还是导出+编辑+运行方法,您都希望在操作后对整个应用程序进行回归测试。
我过去曾使用这种方法进行类似的架构范围更新。这有点黑客,感觉很丑陋,但有时它是最简单/最快的方法。
默认值和其他约束也可以类似地修改,尽管它们只能删除和重新创建而不是更改。就像是:
DECLARE C CURSOR FOR
SELECT AlterDefaultSQL = 'ALTER TABLE [' +st.name+ '] DROP CONSTRAINT [' + si.name + '];'
+ CHAR(10)
+ 'ALTER TABLE [' +st.name+ '] ADD CONSTRAINT [' + si.name + '] DEFAULT '+REPLACE(si.definition, 'GETDATE()', '[dbo].[getlocaldate]()')+' FOR '+sc.name+';'
FROM sys.tables st
JOIN sys.default_constraints si ON si.parent_object_id = st.object_id
JOIN sys.columns sc ON sc.default_object_id = si.object_id
DECLARE @SQL NVARCHAR(MAX)
OPEN C
FETCH NEXT FROM C INTO @SQL
WHILE @@FETCH_STATUS = 0 BEGIN
--PRINT @SQL
EXEC (@SQL)
FETCH NEXT FROM C INTO @SQL
END
CLOSE C
DEALLOCATE C
Run Code Online (Sandbox Code Playgroud)
您可能需要应对一些更有趣的事情:如果您按时间进行分区,那么这些部分也可能需要更改。虽然按时间分区比按天分区的情况很少见,但您可能会遇到问题,DATETIME分区函数将 s 解释为前一天或下一天,具体取决于 timezine,使您的分区与您通常的查询不一致。
我真的很喜欢大卫的回答,并赞成以程序化的方式做事。
但是,您今天可以尝试通过 SSMS 在 Azure 中进行测试:
右键单击您的数据库 --> 任务 --> 生成脚本..
[背景故事] 我们有一个初级 DBA,他将我们所有的测试环境升级到 SQL 2008 R2,而我们的生产环境是 SQL 2008。这一变化让我至今都感到畏缩。为了从测试迁移到生产,我们必须在 SQL 中生成脚本,使用生成脚本,在高级选项中,我们使用“数据类型到脚本:架构和数据”选项来生成大量文本文件。我们成功地将我们的测试 R2 数据库移动到了我们的旧版 SQL 2008 服务器——在那里将数据库还原到较低版本是行不通的。我们使用 sqlcmd 来输入大文件——因为这些文件对于 SSMS 文本缓冲区来说通常太大了。
我在这里要说的是,此选项可能也适用于您。您只需要执行一个额外的步骤并在生成的文本文件中搜索并用 [dbo].getlocaldate 替换 getdate()。(不过,我会在迁移之前将您的函数放入数据库中)。
(我从不想精通数据库恢复的这种创可贴,但有一段时间它成为了一种事实上的做事方式。而且,它每次都有效。)
如果您选择这条路线,请确保选择“高级”按钮并选择您需要的所有选项(阅读每个选项)以从旧数据库移动到新数据库——就像您提到的默认设置一样。但是请在 Azure 中对其进行一些测试。我敢打赌,您会发现这是一种行之有效的解决方案——只需稍加努力。
| 归档时间: |
|
| 查看次数: |
10140 次 |
| 最近记录: |