表非规范化

时间:2019-05-15 15:09:07

标签: sql sql-server denormalization

我必须对现有表进行非规范化并保存已经存在的所有数据。 以前我的表结构是

TABLE A:
[id] INT IDENTITY(1,1)
[name] NVARCHAR(100)
[countryID] INT

TABLE B:
[id] INT IDENTITY(1,1)
[countryName] NVARCHAR(100)

新的TableA结构:

TABLE A:
[id] INT IDENTITY(1,1)
[name] NVARCHAR(100)
[countryName] NVARCHAR(100)

我想知道是否有比这更优雅的解决方案

--BACKUP TABLE TO VARIABLE
DECLARE @backup TABLE (
            [Id] INT NOT NULL,
            [Name] NVARCHAR (1000) NOT NULL,
            [CountryId] INT NULL,
INSERT INTO @backup SELECT * FROM [dbName].[TableA]

--RECREATE THE TABLE WITH NEW STRUCTURE
DROP TABLE [dbName].[TableA]
CREATE TABLE [dbName].[TableA]
        (
            [Id] INT IDENTITY(1, 1) NOT NULL,
            [Name] NVARCHAR (1000) NOT NULL,
            [CountryId] NVARCHAR (100) NULL,
            CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED 
            (
                [Id] ASC
            ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]

SET IDENTITY_INSERT [dbName].[TableA] ON --Required to save original Id's

--INSERT DATA FROM BACKUP TABLE
INSERT INTO [dbName].[TableA]([Id],[Name],[CountryId])
SELECT 
backup.[Id],
backup.[Name],
[dbName].[TableB].[Name],
FROM @backup backup
LEFT JOIN [dbName].[TableB] on backup.[CountyId] = [dbName].[TableB].[Id]

SET IDENTITY_INSERT [dbName].[TableA] ON

2 个答案:

答案 0 :(得分:3)

不同的人可能有不同的选择。但是对我来说,我将选择此步骤以进行相同操作-

  1. 备份表A
  2. 更改表A并添加新列“ countryName”
  3. 通过与表B左连接来更新countryName列中的数据
  4. 将表A更改为DROP列“ countryID”
  5. DROP表B(根据要求)

注意:我会选择Alter Table-A选项,以避免数据丢失的情况下还原表。

答案 1 :(得分:1)

我会对您的解决方案保持谨慎。它不是线程安全的(也就是说,如果其他线程正在修改表,则可能会丢失数据)。如果数据库发生问题,您还冒着丢失备份表的风险-例如,如果数据库在drop之后但在insert之前关闭了。

您实际上只是在TableA中添加了新列。好吧,您可以直接这样做:

alter tableA add column countryName varchar(100);

update a
    set countryName = b.countryName
    from tableA a join
         tableB b
         on a.CountyId = b.id;

这两个都应该是数据库中的“安全”操作。在执行它们之前,我仍然会备份生产数据库。但是,它们应该没问题。

一个警告是,如果TableA确实很大,则更改表可能需要一些时间。在更改生产表之前,您可能需要在开发/登台框中进行测试。