我正在尝试使用脚本更改SQL Server中的表。在过去,我总是通过GUI完成这类工作,但现在我需要生成一个脚本来为客户完成。
我有一个SQL Server数据库表,如下所示:
MyTable ------- ColA int NOT NULL ColB int NOT NULL ColC int NOT NULL ColD VARCHAR(100)
主键是在ColA,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)
主键现在由ColA,ColB,ColX和ColC定义。
通过SQL Server GUI很容易做到这一点。但是当我从中生成一个脚本时,它似乎不必要地复杂。基本上,脚本使用新模式创建临时表,将旧表中的所有数据,索引和约束复制到临时表中,删除旧表,然后将新表重命名为旧表的名称。此外,它有这样的行:
ALTER TABLE dbo.Tmp_MyTable ADD CONSTRAINT
MyTable21792984_ColC_DF DEFAULT ((0)) FOR ColC
我担心这些随机数字(即21792984)在所有客户数据库实例上都不一样。它们看起来像SQL服务器在创建对每个实例唯一的数据库时生成的内容。
是否有更直接的方法通过SQL命令更改表?我在网上看过,但我发现的主要是基本的和/或通用的。
更新:根据我收到的答案,看起来困难在于将新列“置于”两列之间。我已经意识到列的顺序并不重要(如果我错了,请随意留下纠正我的答案)。在我的情况下,如果我只是将列添加到表的末尾,则更改会更简单,代码中的任何内容都不依赖于特定的列顺序。
答案 0 :(得分:9)
没有其他方法可以在“现有列之间”插入SQL Server表中的列 - 您需要构建临时表并重建旧表。也就是说,列顺序无关紧要 - 您确定需要按顺序插入列吗?
可能最好的办法是只使用GUI,编写脚本,然后将约束名称更改为脚本中合理的内容。你是对的,数字约束名称并不理想,允许SQL Server确定你的对象名称不是最佳做法。
答案 1 :(得分:4)
如果要在表的中间插入一个字段,则基本上必须删除当前表并重新创建它,这是sql server正在执行的操作。
随机数确保约束具有唯一名称。如果你保留脚本并在多个数据库上运行它们,那么它们都将是相同的。如果你打算通过gui修改每一个,那么是的,他们很可能会有所不同。
要修改主键,您需要做的就是找出主键约束名称并将其删除。只需添加一个定义主键的新约束。这假设您没有在其他位置将主键列为外键。
答案 2 :(得分:3)
我只是想指出为什么你永远不想使用GUI在现有表的中间插入一列。当你这样做时,创建一个speatare新表,从旧表移动数据,重命名旧表,将新表重命名为旧表名并删除旧表。如果你有一个小的数据集,那就太糟糕了。在表格可能非常大的生产环境中,您可以锁定用户几个小时不能访问表格。添加新列时需要重新排列数据库中列的顺序的任何数据库设计都是导致灾难的数据库。但是有些人坚持这样做,这也是为什么Select *也是一个等待发生的问题的另一个原因。您真的不希望状态显示在报表的zip列中,因为有人重新排列了表中的列,并且您依赖于列顺序中的select *。
答案 3 :(得分:2)
如果您刚刚指定的CREATE TABLE
,PRIMARY KEY (ColA, ColB, ColC)
,那么您告诉SQL Server您不关心此约束的名称,您永远不必参考直接 - 所以SQL Server完全有理由为它生成一些半随机的唯一名称,比如正确地担心你的MyTable21792984_ColC_DF
(尽管那个特定的似乎是ColC
- 具体单列约束,相同类型的命名将适用于其他约束。)
虽然这个问题可能为时已晚,无法修复您当前的架构,但如果您遵循始终命名约束的原则,将来会对您有所帮助 - 因为您通常很可能可能需要在将来引用它们,因此您希望名称完全在您的控制之下,就像任何其他模式对象(表,列等)的名称一样。在这种情况下,在CONSTRAINT PK_MyTable PRIMARY KEY (ColA, ColB, ColC)
中使用CREATE TABLE
之类的子句会有所帮助。 (如果您用于DBA任务的GUI工具不允许您控制这类事情,那么它们不适合DBA:找到更好的工具! - 。)。
答案 4 :(得分:2)
依赖于数据库表中列的任何“自然”或“固有”排序并不是一种好习惯。在任何正式生成的查询中,所有列都应引用,以按查询指定的顺序按名称返回列。如果不遵循该规则,任何未来的架构更改都是绝对的噩梦,因为每次更新数据库架构时都可能需要更改系统代码。
这里唯一令人讨厌的事情是在用户手工编码的生产/测试/开发数据库上使用SELECT * FROM ...
运行一次性查询,并在列列表的末尾显示新列。但是,我相信很多查询工具都可以让你从一种GUI重新排序列。
答案 5 :(得分:1)
如果您希望中间的列像这样,那就是您必须要做的事情。我发现它生成的脚本非常适合仅包括必要的工作。
例如,如果要在末尾添加列,则只需执行以下操作:
ALTER TABLE ADD COLUMN ColX int NOT NULL DEFAULT(0)
你会在它生成的脚本中看到这一点。
就更改主键而言,它可以被删除(在所有现有列上)并重新创建而不重写表,但如果它是聚簇的,你可能会得到一个不同的脚本。
答案 6 :(得分:1)
获取示例代码&修改它。如果您希望列在特定位置着陆,则必须执行临时表重新定义/重命名路由。您也可以按照这种方式命名索引和约束。
答案 7 :(得分:1)
您使用什么工具来生成脚本。我使用Red-Gate Sql compare tool,效果很好。
答案 8 :(得分: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.
现在说我想使用此人员表创建员工表。
create table employee as select name,salary,age from person;
当您描述员工表时,它的定义与人员表AS WELL AS DATA的定义相同。