【问题标题】:Add a new table column to specific ordinal position in Microsoft SQL Server将新表列添加到 Microsoft SQL Server 中的特定序号位置
【发布时间】:2010-10-20 16:02:11
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 或者这就是为什么我应该在每个表的顶部创建视图的原因?
  • 想知道表定义上的“OrderBy”列的可行性是什么。这种删除和重新创建表的废话,因为需要在完全合乎逻辑的位置插入新字段,这对任何人都没有任何好处。

标签: sql-server database-table change-management


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      这实际上是 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
      

      三:顺其自然

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

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

              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)
              

              【讨论】:

                【解决方案8】:

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

                • 开放式表设计
                • 通过拖动来定位所需的列
                • 根据 KM 的回答(线程中的第二个) - 取消选中允许创建更改脚本的选项,请参阅上图。
                • 保存更改。
                • 完成。立即检查您的餐桌。

                【讨论】:

                  【解决方案9】:

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

                  【讨论】:

                    【解决方案10】:

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

                    ALTER TABLE `sakila`.`actor` 
                    CHANGE COLUMN `middle_name` `middle_name` VARCHAR(50) NULL DEFAULT NULL AFTER `first_name`; 
                    

                    【讨论】:

                    • 您的答案是特定于 MySQL。这将在 SQL Server 中工作,这是 OP 专门针对的。像这样混合 MySQL 答案只会让那些在这里寻找 SQL Server 答案的人感到困惑。
                    猜你喜欢
                    • 2011-12-15
                    • 1970-01-01
                    • 2015-10-28
                    • 1970-01-01
                    • 2016-07-23
                    • 1970-01-01
                    • 2016-06-28
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多