Table 反规范化
Table denormalization
我必须对现有 table 进行反规范化并保存所有已存在的数据。
以前我的 table 结构是
TABLE A:
[id] INT IDENTITY(1,1)
[name] NVARCHAR(100)
[countryID] INT
TABLE B:
[id] INT IDENTITY(1,1)
[countryName] NVARCHAR(100)
新表A结构:
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
不同的人可能会有不同的选择。但对我来说,我会选择这个步骤来做同样的事情-
- 备份Table-A
- 更改 Table-A 并添加新列 "countryName"
- 通过左连接 Table-B
更新 countryName 列中的数据
- 将 Table-A 更改为删除列 "countryID"
- 删除 Table-B(根据要求)
注意:我会选择更改 Table-A 选项只是为了避免在数据丢失的情况下恢复 table。
我会对你的解决方案持谨慎态度。它不是 thread-safe(也就是说,如果其他线程正在修改 table,您可能会丢失数据)。如果数据库出现问题,您还 运行 有丢失备份 table 的风险——假设数据库在 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;
这两个应该是数据库中的"safe"操作。在执行它们之前,我仍然会备份生产数据库。但是,他们应该没问题。
需要注意的是,如果 TableA
真的很大,更改 table 可能需要一些时间。在生产中更改 table 之前,您可能想在 development/staging 盒子上进行测试。
我必须对现有 table 进行反规范化并保存所有已存在的数据。 以前我的 table 结构是
TABLE A:
[id] INT IDENTITY(1,1)
[name] NVARCHAR(100)
[countryID] INT
TABLE B:
[id] INT IDENTITY(1,1)
[countryName] NVARCHAR(100)
新表A结构:
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
不同的人可能会有不同的选择。但对我来说,我会选择这个步骤来做同样的事情-
- 备份Table-A
- 更改 Table-A 并添加新列 "countryName"
- 通过左连接 Table-B 更新 countryName 列中的数据
- 将 Table-A 更改为删除列 "countryID"
- 删除 Table-B(根据要求)
注意:我会选择更改 Table-A 选项只是为了避免在数据丢失的情况下恢复 table。
我会对你的解决方案持谨慎态度。它不是 thread-safe(也就是说,如果其他线程正在修改 table,您可能会丢失数据)。如果数据库出现问题,您还 运行 有丢失备份 table 的风险——假设数据库在 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;
这两个应该是数据库中的"safe"操作。在执行它们之前,我仍然会备份生产数据库。但是,他们应该没问题。
需要注意的是,如果 TableA
真的很大,更改 table 可能需要一些时间。在生产中更改 table 之前,您可能想在 development/staging 盒子上进行测试。