2009-06-08 34 views
5

我想用脚本来改变SQL Server中的表。在过去,我总是通过GUI来完成这种事情,但现在我需要生成一个脚本来为客户做。使用脚本在SQL Server中的其他列之间插入列

我有一个SQL Server数据库表是这样的:

 
MyTable 
------- 
ColA int NOT NULL 
ColB int NOT NULL 
ColC int NOT NULL 
ColD VARCHAR(100) 

主键跨可乐,COLB和COLC定义。

我想要的SQL脚本来更改表所示:

 
MyTable 
------- 
ColA int NOT NULL 
ColB int NOT NULL 
ColX int NOT NULL (new column, default 0 for existing data) 
ColC int NOT NULL 
ColD VARCHAR(100) 

主键将目前由可乐,COLB,COLX和COLC定义。

这很容易通过SQL Server GUI来完成。但是当我从它那里生成一个脚本时,它似乎不必要的复杂。基本上,脚本使用新模式创建临时表,将旧表中的所有数据,索引和约束复制到临时表中,删除旧表,然后将新表重命名为旧表。此外,它有这样的台词:

ALTER TABLE dbo.Tmp_MyTable ADD CONSTRAINT 
    MyTable21792984_ColC_DF DEFAULT ((0)) FOR ColC 

我担心的是,这些随机找数有(即21792984)将不会对所有的客户数据库实例相同。它们看起来像是SQL Server在创建数据库时生成的,每个实例都是唯一的。

是否有更简单的通过SQL命令更改表的方法?我看过网上,但我发现大多是基本的和/或通用的。

更新:从我收到的答案,它看起来像困难在于把新列“之间”两栏。我意识到,列的顺序并不重要(如果我错了,可以随时留下一个答案来纠正我)。在我的情况下,如果我只是将列添加到表的末尾,则更改更简单,代码中的任何内容都不依赖于特定的列顺序。

回答

8

没有其他方式在SQL Server表“之间”现有列中插入列 - 您需要构建临时表并重新构建旧表。也就是说,列顺序无关紧要 - 您确定该列需要按顺序插入吗?

可能最好的办法就是使用GUI,编写脚本,然后在脚本中将约束名称更改为合理的名称。你说得对,数字约束名称并不理想,并且允许SQL Server确定你的对象名称不是一个好习惯。

+0

谢谢,经过进一步检查,列顺序并不重要(美学除外)。只有将列添加到最后才能使其变得更容易。 – Kip 2009-06-08 17:18:40

+0

如果您确实希望更改订单,则可以使用SQL Compare中的强制列顺序来执行此操作。这需要完整的表格重建,所以如果您有大量数据可能需要时间。现有数据将由SQL Compare保存。 – 2010-06-12 10:32:25

3

如果你插入一个字段到表的中间,你必须删除当前的表并重新创建它,这是SQL服务器正在做什么。

随机数字确保约束具有唯一的名称。如果你保留这个脚本并在多个数据库上运行它们,那么它们都是一样的。如果你要通过gui修改每一个,那么是的,他们很可能会有所不同。

要修改主键,您只需找到主键约束名称并将其删除即可。只需添加一个定义主键的新约束即可。假设您没有在其他地方将外键列为外键。

1

如果你想要这样的中间列,那就是你必须做的。我发现它生成的脚本非常好,仅包含了一些神奇的作品。

如果你要在最后例如添加一列,你只需要做:

ALTER TABLE ADD COLUMN ColX int NOT NULL DEFAULT(0) 

而且你会看到在它生成的脚本。

只要修改主键,它可以被删除(在所有现有的列上)并重新创建而不用重写表,但是如果它是聚集的或不是,你可能会得到一个不同的脚本。

1

以示例代码&对其进行修改。如果你想让列落在特定的地方,你必须去临时表重新定义/重命名路线。您也可以按照这种方式命名索引和约束。

1

你用什么工具生成脚本。我使用Red-Gate Sql compare tool,它的作品非常漂亮。

+0

我只是使用Microsoft SQL Server Management Studio,我认为它与SQL Server一起提供。 – Kip 2009-06-08 17:15:22

2

如果在您刚才指定的CREATE TABLE中指定了例如PRIMARY KEY (ColA, ColB, ColC),那么您告诉SQL Server您并不在意这个约束的名称,也就是说您不必直接引用它 - 所以SQL Server完全有理由为它生成一些半随机看起来的独特名称,如MyTable21792984_ColC_DF,这正确地担心你(尽管该特定的一个似乎是一个ColC特定的单列约束,相同类型的命名将适用于其他约束)。

虽然这个问题可能为时已晚修为当前的模式,它会如果你遵循的原则始终命名约束帮助你在未来的 - 因为它通常是相当可能的,你可能需要参考给他们,所以你希望这个名字完全在你的控制之下,就像任何其他模式对象(表,列等等)的名字一样。在这种情况下,在CREATE TABLE中使用CONSTRAINT PK_MyTable PRIMARY KEY (ColA, ColB, ColC)这样的条款会有所帮助。 (如果您用于DBA任务的GUI工具不允许您控制这类事情,那么它们不适合DBA的合适工具:找到更好的工具 - )。

+0

不幸的是,我正在接触现有数据,因此我无法控制数据库的创建方式。但他们至少将其主键一致地命名为PK_TableName。 – Kip 2009-06-08 17:26:59

2

依赖于数据库表中任何列的“自然”或“固有”排序是不好的做法。所有列在任何官方生成的查询中按名称引用,以按查询指定的顺序按名称返回列。如果未遵循该规则,则任何未来的模式更改都是绝对的噩梦,因为每次更新数据库模式时可能需要更改系统代码。

这里唯一令人讨厌的事情是在用户手动编码的生产/测试/开发数据库上运行使用SELECT * FROM ...的一次性查询,并让您的新列显示在列列表的末尾。不过,我相信很多查询工具可以让你重新排列来自某种GUI的列。

3

我只想指出为什么你永远不想使用GUI在现有表的中间插入一列。当你这样做时,创建一个speatare新表,移动旧表中的数据,重命名旧表,将新表重命名为旧表名并删除旧表。如果你有一个小数据库,这已经够糟糕了。在桌子可能很大的生产环境中,您可能会将用户锁定在桌子上几个小时。在添加新列时需要重新排列数据库中列的顺序的任何数据库设计都是一个以灾难为导向的数据库。因为有人坚持这样做,这也是Select *也是一个等待发生的问题的另一个原因。你真的不希望状态出现在报表的压缩列中,因为有人重新排列了表中的列,并且依赖于列顺序中的select *。

0

将新列添加到现有表中(将其添加到所有列的末尾) 然后使用此表创建一个新表,并在用于构建新表的子查询中提及列你希望他们在新表中的顺序..

例:

create table person(name varchar2(10),age number); 
alter table person add salary number; (now salary is added at last position) 
desc person 
name ... 
age ... 
salary ... so now salary is at the end. 

现在说我想用这个人表创建EMPLOYEE表。

create table employee as select name,salary,age from person; 

当您描述员工表时,它具有与人员表一样的定义以及数据。

相关问题