2017-08-29 68 views
-2

我几个月前创建了一个数据库,实际上,这个架构很糟糕。现在,我有近200万条记录,并且因为我在开始时没有正确构建数据库,所以请求很长。 下面涉及的两个表:SQL根据其他表更改列类型[nvarchar到int(FK)]

表A:

id (PK, int) 
category (nvarchar) 
date (datetime) 

表B

id (PK, int) 
category (nvarchar) 

我想更改类别栏为 “int”,创造之间的关系表格(FK)。请看下图:

表A:

id (PK, int) 
category (FK, int) 
date (datetime) 

键:PK_TableA,FK_TableB

我不问了解决方案,但一些小技巧来构建脚本来做到这一点: - 变化 - 对于每条记录, 查看类别>取id>用id(int)替换类别名称(字符串)

感谢您的帮助:)

+0

您确定该列只有数字数据吗?如果你能容忍它,只要在查询时解决这个问题可能是一个选择。 –

+0

你使用的是MySQL还是MS SQL Server?不要标记不涉及的产品。 – jarlh

+0

@jarlh Microsoft SQL Server,错误的标签我的坏。 –

回答

1

我想你可以从这样的事情开始。 最后,在检查完成之后(无论如何在更新之前备份你的表),你可以删除tableA中的CATEGORY列和(如果你想)重命名列CATEGORY_ID。 如果你想,在开始之前,你可以做供以后使用的检查(见最后):

SELECT CATEGORY, COUNT(*) AS RC 
FROM TABLEA 
GROUP BY CATEGORY; 

示例脚本

CREATE TABLE TABLEA (ID INT, CATEGORY VARCHAR(20), DATE_A DATETIME); 


CREATE TABLE TABLEB (ID INT, CATEGORY VARCHAR(20)); 

INSERT INTO TABLEA VALUES (1,'abc', GETDATE()); 
INSERT INTO TABLEA VALUES (2,'cde', GETDATE()); 
INSERT INTO TABLEA VALUES (3,'cde', GETDATE()); 
INSERT INTO TABLEA VALUES (4,'abc', GETDATE()); 
INSERT INTO TABLEA VALUES (5,'abc', GETDATE()); 
INSERT INTO TABLEA VALUES (6,'fgh', GETDATE()); 
INSERT INTO TABLEA VALUES (7,'zzz', GETDATE()); 

INSERT INTO TABLEB VALUES (100,'abc'); 
INSERT INTO TABLEB VALUES (200,'cde'); 
INSERT INTO TABLEB VALUES (300,'fgh'); 


SELECT * FROM TABLEA; 

ALTER TABLE TABLEA ADD CATEGORY_ID INT; 

UPDATE A SET CATEGORY_ID = B.ID 
FROM TABLEA A 
LEFT JOIN TABLEB B ON A.CATEGORY = B.CATEGORY; 


--CREATE INDEX TABLEA_CATID ON TABLEA (CATEGORY_ID); 

SELECT CATEGORY_ID, COUNT(*) AS RC 
FROM TABLEA 
GROUP BY CATEGORY_ID; 

对于semplicity,我没加PK (但如你所知他们是“必要的”)。 我建议为CATEGORY_ID在TABLEA上定义FK约束。

+0

干杯队友,这是一个好的开始。我知道我现在必须做什么。 –

1

看看你如何命名你的列我想说你想要一个新的列分类id(FK,INT),而不是TableA中的类别(nvarchar)。

得到这个的天真的方式是创建一个带有nullable属性的新列,填充它,设置约束,删除可空属性并最后删除类别(varchar)列。如果您无法更改列名称,则需要添加一些额外步骤来切换列。

由于您已经有两百万行,您可能更愿意创建一个新表(TableC),使用TableC填充它并切换TableA(放置/重命名TableA,重命名TableC TableA)。

表C:

id (PK, int) 
categoryid (FK, int) 
date (datetime) 

你通常最好让新表,并用大量行的表打交道时切换出旧的。

Regards Martin

+0

感谢您的回复。我使用@etsa提供的代码(进行了一些更改),并创建了一个新表,而不是添加/重命名该列。现在,我正在做一些测试来创建一个脚本。所以我已经做了你的建议,但谢谢:) –