【问题标题】:How to change column order in a table using sql query in sql server 2005?如何在 sql server 2005 中使用 sql 查询更改表中的列顺序?
【发布时间】:2010-12-08 23:24:02
【问题描述】:

如何在 SQL Server 2005 中使用 SQL 查询更改表中的列顺序?

我想使用 SQL 查询重新排列表中的列顺序。

【问题讨论】:

  • 如果您指的是更改表中存在的列的 位置,则需要使用首选顺序创建一个新表,插入旧表中的数据,然后删除原始表。没有其他方法(据我所知)可以做到这一点。
  • 你说的是SELECT语句中的列顺序,还是表定义中的列顺序?

标签: sql sql-server-2005


【解决方案1】:

你不能。列顺序只是我们人类关心的“装饰”事物——对于 SQL Server,它几乎总是绝对无关紧要。

当您更改列顺序时,SQL Server Management Studio 在后台执行的操作是使用新的 CREATE TABLE 命令从头开始重新创建表,复制旧表中的数据,然后将其删除。

没有用于定义列排序的 SQL 命令。

【讨论】:

  • 不,在 SQL Server 中没有这样的东西 - 并且不应该在任何真正的 RBDMS 中 - 列顺序不是与 SQL 表相关的概念
  • @marc_s 没有充分的理由反对支持列顺序。哪怕只是视觉上的。当您进行“SELECT *”时,它只是可以更轻松地查看具有给定列顺序的表中的数据。我是一名开发人员,一直在做这种查询。您可以使用良好的预定义列顺序腾出一些时间。当然,从任何其他角度来看,它没有任何意义:任何东西都不应该依赖于列顺序。顺便说一句,当您查询“INFORMATION_SCHEMA.COLUMNS”时,有一个 ORDINAL_POSITION 列。我不知道这意味着什么……但它一定与此有关。
  • 列顺序是相关的,例如在使用 INSERT INTO 而不指定列名时。另一个例子是 ORDER BY 列索引而不是列名。显然这两种做法都不推荐,但 SQL Server 允许这样做,因此有人可能在某处使用过它,可能会在更改列顺序时破坏 T-SQL 代码。
  • @Carvelis:您应该绝不使用INSERT,而无需明确指定您的列!
  • @marc_s:当然,但我通常不是唯一一个从事项目的人。我见过不少项目中人们使用了这种代码。
【解决方案2】:

您必须按照您希望它们返回的顺序明确列出字段,而不是使用 * 作为“默认”顺序。

原始查询:

select * from foobar

返回

foo bar
--- ---
  1   2

现在写

select bar, foo from foobar

bar foo
--- ---
  2   1

【讨论】:

  • 上面的答案是错的吧?这个答案从字面上显示了如何对列进行排序,为什么前一个有复选标记而这个没有?
  • @Agent Lu 问题是原始问题的措辞。 Marc 和我对 OP 的“更改列的顺序”的问题进行了不同的解释。他提出了一个强有力的论点,为什么列顺序在存储表中是不相关的(虽然名称是)。我展示了如何以不同的列顺序提取数据。根本不是一回事!
【解决方案3】:

根据https://docs.microsoft.com/en-us/sql/relational-databases/tables/change-column-order-in-a-table

使用 Transact-SQL 语句不支持此任务。

嗯,可以做到,使用create/复制/drop/重命名,正如komma8.komma1所回答的那样

或者您可以使用 SQL Server Management Studio

  1. 对象资源管理器中,右键单击包含要重新排序的列的表,然后单击设计(在 2005 SP1 或更早版本中修改)
  2. 选择要重新排序的列名称左侧的框。 (您可以通过按住 [shift] 或 键盘上的 [ctrl] 键。)
  3. 将列拖到表格中的另一个位置。

然后点击保存。此方法实际上是删除并重新创建表,因此可能会出现一些错误。

如果为数据库和表启用了更改跟踪选项,则不应使用此方法。

如果禁用,阻止保存需要重新创建表的更改选项应在工具菜单>选项>设计器中清除,否则“不允许保存更改” 会发生错误。

  • Microsoft 强烈建议不要禁用 防止保存需要重新创建表的更改 选项,因为它会导致在重新创建表时删除现有的更改跟踪信息,因此如果启用了更改跟踪,您应该永远不要禁用此选项!

在主键和外键创建过程中也可能出现问题。

如果发生上述任何错误,保存将失败,保留原始列顺序。

【讨论】:

  • 文档中的“This task cannot be performed using Transact-SQL statements.”语句有误。我解释了作者,让他改成“This task is not supported using Transact-SQL statements.”。大约一天前,作者同意了,文件就修好了。 You can follow the discussion we had on GitHub.
  • @RonenAriely 干得好,感谢您告诉我。我更新了我的答案
  • 不客气@robotik ?。我希望所有来这里看到投票最多的人都会明白这是一个完全错误的错误。不幸的是,社区通常表现得像一群(牛),一旦社区中的领导者和顶级贡献者(被认为是顶级专家)犯了错误,那么其他人就会跟随他,就像这个线程中发生的那样。如果已经获得了很多票,人们继续投票给错误(方法:“既然大家都这么说,那就是真的”),其他会来论坛的人会认为这是正确的答案。
  • @RonenAriely 这就是为什么我总是向下滚动 :)
【解决方案4】:

这类似于在查询结果中对记录进行排序的问题......通常没有人喜欢正式正确的答案;-)

就这样吧:

  • 根据 SQL 标准,表中的列不是“有序的”
  • 因此,select * 不会强制以特定顺序返回列
  • 通常,每个 RDBMS 都有一种“默认”顺序(通常是列添加到表中的顺序,或者在 create table' or in thealter 表中添加`语句
  • 因此,如果您依赖列的顺序(因为您正在使用查询结果从列的位置填充其他数据结构),请按照您想要的顺序显式列出列。

【讨论】:

    【解决方案5】:

    在 SQLServer Management Studio 中:

    工具 -> 选项 -> 设计器 -> 表和数据库设计器

    • 取消选择“防止保存需要重新创建表的更改”。

    然后:

    • 右键单击要对其列重新排序的表。
    • 点击“设计”。
    • 将列拖动到所需的顺序。
    • 最后,点击保存。

    SQLServer Management Studio 将删除表并使用数据重新创建它。

    【讨论】:

    • 完美运行
    【解决方案6】:

    您当然可以更改 sql 语句中列的顺序。但是,如果您想抽象表的物理列顺序,您可以创建一个视图。即

    CREATE TABLE myTable(
        a int NULL,
        b varchar(50) NULL,
        c datetime NULL
    );
    
    
    CREATE VIEW vw_myTable
    AS
    SELECT c, a, b
      FROM myTable;
    
    select * from myTable;
    a  b  c
    -  -  -
    
    select * from vw_myTable
    c  a  b
    -  -  -
    

    【讨论】:

    • 这会改变查询时间吗?
    • @blindguy 不,它不会改变您的查询时间
    【解决方案7】:

    您可以通过创建一个新表,复制所有数据,删除旧表,然后重命名新表来替换旧表来做到这一点。

    您还可以向表中添加新列,逐列复制数据,删除旧列,然后重命名新列以匹配旧列。下面是一个简单的例子: http://sqlfiddle.com/#!3/67af4/1

    CREATE TABLE TestTable (
        Column1 INT,
        Column2 VARCHAR(255)
    );
    GO
    
    insert into TestTable values(1, 'Test1');
    insert into TestTable values(2, 'Test2');
    GO
    
    select * from TestTable;
    GO
    
    ALTER TABLE TestTable ADD Column2_NEW VARCHAR(255);
    ALTER TABLE TestTable ADD Column1_NEW INT;
    GO
    
    update TestTable 
    set Column1_NEW = Column1, 
        Column2_NEW = Column2;
    GO
    
    ALTER TABLE TestTable DROP COLUMN Column1;
    ALTER TABLE TestTable DROP COLUMN Column2;
    GO
    
    sp_rename 'TestTable.Column1_NEW', 'Column1', 'COLUMN';
    GO
    sp_rename 'TestTable.Column2_NEW', 'Column2', 'COLUMN';
    GO
    
    select * from TestTable;
    GO
    

    【讨论】:

    【解决方案8】:

    在 SQLServer Management Studio 中:

    Tools -> Options -> Designers -> Table and Database Designers

    取消选择Prevent saving changes that require table re-creation

    现在您可以重新排列表格。

    【讨论】:

      【解决方案9】:

      如果您的表格有足够的列,那么您可以试试这个。首先创建一个具有首选列顺序的新表。

          create table new as select column1,column2,column3,....columnN from table_name;
      

      现在使用 drop 命令删除表

          drop table table_name;
      

      现在将新创建的表重命名为旧表名。

          rename new to table_name;
      

      现在选择表格,您的列已按照您之前的喜好重新排列。

          select * from table_name;
      

      【讨论】:

      • 这个和新建表一样,把已有表的数据复制到新表,删除旧表,重命名新表。所以严格来说,这并没有改变表格的列顺序。由于这会从旧表创建/复制,因此大型表需要时间。最后但同样重要的是,建议的语法在 t-sql 中不起作用。
      【解决方案10】:

      Sql server 内部构建脚本。它创建一个带有新更改的临时表并复制数据并删除当前表,然后从临时表重新创建表插入。我从“生成更改脚本”选项 ssms 2014 中找到它。像这样的脚本。来自Here: How to change column order in a table using sql query

      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_emps
          (
          id int NULL,
          ename varchar(20) NULL
          )  ON [PRIMARY]
      GO
      ALTER TABLE dbo.Tmp_emps SET (LOCK_ESCALATION = TABLE)
      GO
      IF EXISTS(SELECT * FROM dbo.emps)
           EXEC('INSERT INTO dbo.Tmp_emps (id, ename)
              SELECT id, ename FROM dbo.emps WITH (HOLDLOCK TABLOCKX)')
      GO
      DROP TABLE dbo.emps
      GO
      EXECUTE sp_rename N'dbo.Tmp_emps', N'emps', 'OBJECT' 
      GO
      COMMIT
      

      【讨论】:

        【解决方案11】:

        归根结底,您根本无法在 MS SQL 中执行此操作。我最近使用从查找表中读取的存储过程在旅途中(应用程序启动)创建了表。当我创建一个将这些与我之前手动创建的另一个表(相同的模式,带有数据)组合在一起的视图时,它失败了 - 仅仅是因为我使用 ''Select * UNION Select * ' 作为视图。同时,如果我只使用那些通过存储过程创建的,我就成功了。

        结论:如果有任何应用程序依赖于列的顺序,那真的不是很好的编程,而且肯定会在未来产生问题。列应该“随意”放在任何地方并用于任何数据处理(INSERT、UPDATE、SELECT)。

        【讨论】:

          【解决方案12】:

          您可以通过以下步骤实现:

          1. 删除原表的所有外键和主键。

          2. 重命名原始表。

          3. 使用 CTAS 按您想要的顺序创建原始表。

          4. 删除旧表。

          5. 将所有约束应用回原始表

          【讨论】:

            【解决方案13】:

            如果要重新排序的列是最近创建的并且是空的,则可以删除这些列并以正确的顺序重新添加。

            这件事发生在我身上,手动扩展数据库以添加新功能,我漏掉了一列,当我添加它时,顺序不正确。

            在这里找不到合适的解决方案后,我只是使用以下命令更正了表格。

            ALTER TABLE  tablename  DROP COLUMN  columnname; 
            ALTER TABLE  tablename  ADD columnname columntype;
            

            注意:仅当您要删除的列中没有数据时才这样做。

            人们说列顺序无关紧要。我经常使用 SQL Server Management Studio“生成脚本”来创建数据库架构的文本版本。为了有效地控制这些脚本 (git) 并比较它们 (WinMerge),兼容数据库的输出必须相同,突出显示的差异是真正的数据库差异。

            列顺序很重要;但只是对某些人,而不是对所有人!

            【讨论】:

              【解决方案14】:

              如果您尚未将任何数据添加到表中,则有一种方法可以移动列。 试试这个:

              1. 在 SSMS 中,点击 Tools > Options > Designers > Table and Database Designers > 取消选中下一步防止保存需要重新创建表的更改 > 点击确定
              2. 在对象树中,右键单击您的表格并在 左侧 的细列中选择 Design > >列名称列,您可以单击并拖动列到您想要的任何位置。完成后,只需转到关闭“设计”选项卡,SSMS 会询问您是否要保存更改,点击确定

              可选: 3. 重新启用第 1 步中选项的复选框以重新保护您的表。

              希望这对某人有所帮助!

              感谢微软: https://docs.microsoft.com/en-us/troubleshoot/sql/ssms/error-when-you-save-table#more-information

              【讨论】:

                【解决方案15】:

                使用

                SELECT * FROM TABLE1
                

                显示表格的默认列顺序。

                如果你想改变列的顺序。

                指定对应显示的列名

                SELECT COLUMN1, COLUMN5, COLUMN4, COLUMN3, COULMN2 FROM TABLE1
                

                【讨论】:

                • 问题不在于临时订购。当您更改表格并添加新列时,问题是关于表格设计结构。
                【解决方案16】:

                你可以使用索引..索引后,如果从XXXX结果中选择*应该是根据索引,但只有结果集..不是表的结构

                【讨论】:

                  【解决方案17】:

                  为了有一个特定的列顺序,您需要按照您希望的顺序逐列选择。 选择顺序决定了列在输出中的排序方式。

                  【讨论】:

                    【解决方案18】:

                    试试这个命令:

                    alter table students modify age int(5) first; 
                    

                    这会将年龄的位置更改为第一个位置。

                    【讨论】:

                    • 这不是 MSSQL 中的有效 SQL。也许是 MySQL 或其他方言,但不适用于 SQL Server 2005
                    【解决方案19】:

                    我想您想在特定位置添加一个新列。您可以通过将当前列向右移动来创建新列。

                    +---+---+---+
                    | A | B | C |
                    +---+---+---+
                    

                    删除所有受影响的索引和外键引用。添加一个与最后一列具有完全相同数据类型的新列,并将数据复制到那里。

                    +---+---+---+---+
                    | A | B | C | C |
                    +---+---+---+---+
                              |___^
                    

                    Change data type 第三列的类型与上一列相同,并在那里复制数据。

                    +---+---+---+---+
                    | A | B | B | C | 
                    +---+---+---+---+
                          |___^
                    

                    相应地重命名列,重新创建已删除的索引和外键引用。

                    +---+---+---+---+
                    | A | D | B | C | 
                    +---+---+---+---+
                    

                    更改第二列的数据类型。

                    请记住,列顺序只是像 marc_s said 这样的“装饰”。

                    【讨论】:

                      【解决方案20】:

                      您可以使用 SQL 查询更改此设置。这是改变列顺序的sql查询。

                      ALTER TABLE table name 
                      CHANGE COLUMN `column1` `column1` INT(11) NOT NULL COMMENT '' AFTER `column2`;
                      

                      【讨论】:

                      • 我想知道这是否会像 SSMS 一样删除并重新创建表。无论哪种方式,我都不会在生产数据库上掷骰子,尽管这种方法看起来很有趣并且值得研究。
                      • 此功能在 OP 指定的 SQL Server 中不起作用。希望是这样。
                      • 这是 MySQL 语法,不是 SQL Server。
                      【解决方案21】:

                      alter table name modify columnname int(5) first; 将列放在第一位 alter table name modify columnname int(5) after (tablename);

                      【讨论】:

                        【解决方案22】:

                        这在 Oracle DB 上对我有用:

                        select column1, column2, t.* from table t
                        

                        【讨论】:

                          【解决方案23】:

                          示例:更改表状态中 field_price 后 field_priority 的位置。

                          ALTER TABLE `status` CHANGE `priority` `priority` INT(11) NULL DEFAULT NULL AFTER `price`;
                          

                          【讨论】:

                          • 这是 MySQL 语法,不是 SQL Server。
                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 2010-09-08
                          • 2011-06-29
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多