63

是否可以在 Microsoft SQL Server 的特定序号位置向表中添加列?

例如,我们的表在每个表定义的“末尾”总是有 CreatedOn、CreatedBy、LastModifiedOn、LastModifiedBy 列?我希望新列显示在这些列上方的 SSMS 中。

如果我正在编写所有数据库更改的脚本,有没有办法在表的末尾保留这个顺序?

仅供参考,我并不想就是否应该这样做进行一场激烈的战争。如果您想了解一个快速退化的线程,这里有一个很好的:

http://www.developersdex.com/sql/message.asp?p=581&r=5014513

4

10 回答 10

37

您必须创建一个临时表,该表反映原始表的架构但具有您想要的列顺序,然后将原始表的内容复制到 temp。删除原始文件并重命名临时文件。

这就是 SQL Management Studio 在幕后所做的。

使用模式同步工具,您可以自动生成这些脚本。

于 2009-04-20T19:54:34.730 回答
30

进入 SQL Server 管理工作室,并“设计”一个现有的表。在中间插入一列,在空白区域右击并选择Generate Change Script...

现在看看它创建的脚本。它基本上会创建一个具有正确列顺序的临时表,从原始表中插入数据,删除原始表,然后重命名临时表。这可能是您需要做的。

在此处输入图像描述

您可能还需要取消选中此选项以允许创建更改脚本

在此处输入图像描述

于 2009-04-20T19:56:59.497 回答
7

答案是肯定的,技术上是可行的,但是这样做你会很头疼,而且执行和设置需要很长时间。

一:创建/复制/删除/重命名

这实际上是 SQL Server 在图形界面中所做的:这是一个脚本示例,当您在表的开头添加新列后单击“保存”按钮时,它正在生成和执行的脚本。

/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_SomeTable
    (
    MyNewColumn int NOT NULL,
    OriginalIntColumn int NULL,
    OriginalVarcharColumn varchar(100) NULL
    )  ON [PRIMARY]
     TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_SomeTable SET (LOCK_ESCALATION = TABLE)
GO
SET IDENTITY_INSERT dbo.Tmp_SomeTable ON
GO
IF EXISTS(SELECT * FROM dbo.SomeTable)
     EXEC('INSERT INTO dbo.Tmp_SomeTable (OriginalIntColumn, OriginalVarcharColumn FROM dbo.SomeTable WITH (HOLDLOCK TABLOCKX)')
GO
SET IDENTITY_INSERT dbo.Tmp_SomeTable OFF
GO
DROP TABLE dbo.SomeTable
GO
EXECUTE sp_rename N'dbo.Tmp_SomeTable', N'SomeTable', 'OBJECT' 
GO

GO
COMMIT

二:添加列/更新/删除列/重命名

此方法基本上涉及创建要添加到新列“右侧”的任何现有列的副本,将数据传输到新列,然后删除原始列并重命名新列。这将对您拥有的任何索引或约束造成严重破坏,因为您必须重新指向它们。这在技术上是可行的,但在开发和执行方面同样耗时。

CREATE TABLE MyTest (a int, b int, d int, e int)

INSERT INTO MyTest (a,b,d,e) VALUES(1,2,4,5)

SELECT * FROM MyTest -- your current table

ALTER TABLE MyTest ADD c int -- add a new column
ALTER TABLE MyTest ADD d_new int -- create copies of the existing columns you want to move
ALTER TABLE MyTest ADD e_new int

UPDATE MyTest SET d_new = d, e_new = e -- transfer data to the new columns

ALTER TABLE MyTest DROP COLUMN d -- remove the originals
ALTER TABLE MyTest DROP COLUMN e

EXEC SP_RENAME 'MyTest.d_new', 'd'; -- rename the new columns
EXEC SP_RENAME 'MyTest.e_new', 'e';

SELECT * FROM MyTest 

DROP TABLE MyTest -- clean up the sample

三:与它一起生活

这极大地冒犯了我的秩序感……但有时,它不值得重新洗牌。

于 2014-10-16T18:59:06.000 回答
5

据我所知,没有已知的方法可以更改列的顺序。在幕后,SQL Management Studio 执行 Jose Basilio 所说的操作。如果你有一张大桌子,那么像这样改变列顺序是不切实际的。

您可以使用“视图”。使用 SQL 视图,您可以使用任何您喜欢的顺序,而不会受到表列更改的影响。

于 2009-04-20T20:01:31.263 回答
1

我正在使用 SSMS 18。我以简单的方式做到了

  • 开放式桌子设计
  • 通过拖动来定位所需的列
  • 根据 KM 的回答(线程中的第二个) - 取消选中允许创建更改脚本的选项,请参阅上图。
  • 保存更改。
  • 完毕。现在检查你的桌子。
于 2021-08-18T12:56:25.857 回答
0

TFS 2013 会自动为您执行此操作

以您喜欢的方式将新列添加到您的表中,然后将您的更改提交到 TFS。从那里您可以在 Visual Studio 中打开表的 sql 文件并手动移动 T-SQL CREATE 脚本中的列顺序。然后,您可以使用工具 > SQL Server > 新架构比较下的 VS 架构比较工具来更新目标数据库。选择您的数据库项目,将您的更改作为源,将要更新的数据库作为目标。比较,选择表的脚本,然后更新。VS 会自动删除和添加。您的所有数据和索引都是安全的。

于 2016-07-14T19:18:39.710 回答
0

我认为很简单的是添加列 ALTER TABLE table1 ADD .. 然后从 select like 中创建一个像 tmp_table1 这样的 tmp 表 SELECT col1,col2,col5,col3,col4 into tmp_table1 from table1; ,然后删除 table1 并将 tmp_table1 重命名为 table1,就是这样。我希望它会帮助某人

于 2018-03-13T20:14:30.927 回答
0

将所有列选择到临时表中,并使用所需的新列创建一个新表。然后删除旧表,从临时表中选择所有列,并将它们插入到具有重新排序列的新表中。没有数据丢失。

SELECT * FROM TEMP
SELECT * FROM originaltbl
SELECT * FROM #Stagintbl

DECLARE @ColumnName nvarchar(max);
SET @ColumnName=(SELECT
    DISTINCT STUFF((
        SELECT ',' + a.COLUMN_NAME
        FROM (
            SELECT Column_name 
            FROM INFORMATION_SCHEMA.COLUMNS 
            WHERE TABLE_NAME='originaltbl') a
        for xml path('')
    ),1,1,'') AS ColumnName)

DECLARE @Sqlquery nvarchar(max)
SET @Sqlquery = 'SELECT ' + @ColumnName + ' FROM #Stagintbl' + '';
INSERT INTO originaltbl
EXECUTE(@Sqlquery)
于 2018-12-21T12:51:53.057 回答
-2

肮脏而简单。
将表格导出为 csv。
在所需位置插入新数据。
丢表。
创建具有所需列规范的新表。
将列从 csv 加载到新表。

于 2017-08-18T09:26:40.477 回答
-2

我不确定线程​​是否仍然处于活动状态。我对 MySQL 数据库进行了相同的查询。右键单击表格并选择“ALTER”自动生成以下代码。sakila db 提供的样本,它有效。只需找出要放置新列的列并使用“AFTER”关键字

ALTER TABLE `sakila`.`actor` 
CHANGE COLUMN `middle_name` `middle_name` VARCHAR(50) NULL DEFAULT NULL AFTER `first_name`; 
于 2018-08-26T19:29:51.440 回答