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


109

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

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


3
如果要更改表中存在的列的位置,则需要创建具有首选顺序的新表,从旧表中插入数据,然后删除原始表。(据我所知)没有其他方法可以做到这一点。
迈克尔·托德

您是在谈论SELECT语句上的列顺序,还是表定义上的列顺序?
marc_s

Answers:


111

你不能。列顺序只是我们人类关心的“美容”问题-对于SQL Server,几乎总是绝对不相关的。

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

没有SQL命令来定义列顺序。


4
不,SQL Server没有这种东西-不应以任何实际的RBDMS出现-列顺序不是与SQL表相关的概念
marc_s 2009年

68
@marc_s没有充分的理由反对支持列顺序。即使只是视觉上的。只需执行“ SELECT *”,就可以更轻松地查看具有给定列顺序的表中的数据。我是一名开发人员,一直在进行此类查询。您可以使用良好的预定义列顺序来节省一些时间。当然,从任何其他角度来看,这都是没有意义的:没有任何事情应该取决于列的顺序。顺便说一句,当您查询“ INFORMATION_SCHEMA.COLUMNS”时,会有一个ORDINAL_POSITION列。我不知道这意味着什么...但是它必须与此有关。
JotaBe 2013年

18
列顺序很重要,例如在不指定列名的情况下使用INSERT INTO时。另一个示例是ORDER BY列索引而不是列名。两种方法显然都不推荐这样做,但是SQL Server允许这样做,因此有人可能在某个地方使用了它,可能在更改列顺序时破坏了T-SQL代码。
Carvellis 2014年

12
@Carvelis:无论如何,除非明确指定列,否则切勿使用INSERT
marc_s 2014年

2
@marc_s:绝对可以,但是我通常不是唯一从事项目工作的人。我已经看到很多项目,人们在其中使用了这种代码。
Carvellis 2014年

30

您必须按照希望它们返回的顺序显式列出这些字段,而不是在“默认”顺序中使用*。

原始查询:

select * from foobar

退货

foo bar
--- ---
  1   2

现在写

select bar, foo from foobar

bar foo
--- ---
  2   1

上面的答案是错误的,不是吗?这个答案从字面上显示了如何对列进行排序,为什么前一个列有一个选中标记,而这个列没有?
特工Lu

1
@Agent Lu问题是原始问题的措辞。Marc和我对OP的问题提出了不同的解释,即“更改列的顺序”。他提出了一个强有力的论据,为什么列顺序在存储的表中无关紧要(尽管有名称)。我展示了如何以不同的列顺序提取数据。根本不一样!
lexu

23

根据http://msdn.microsoft.com/en-us/library/aa337556.aspx

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

好吧,可以使用create/ copy drop// rename 来完成,如komma8.komma1回答

或者您可以使用SQL Server Management Studio

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

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

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

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

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

在创建主键和外键时也可能会出现问题。

如果发生以上任何错误,保存将失败,这将使您保持原始列顺序。


1
This task cannot be performed using Transact-SQL statements.文件中的「」陈述有误。我解释了作者,并要求他将其更改为“ This task is not supported using Transact-SQL statements.”。大约一天前,作者同意,并且文件已修复。您可以关注我们在GitHub上进行的讨论
罗尼·阿里

@RonenAriely做得很好,谢谢您让我知道。我更新了答案
robotik,

不客气@robotik😀。我希望所有来到这里并以最高票数看到答复的人都将理解这是完全错误的。不幸的是,社区通常表现得像牛群(牛),一旦社区的领导者和杰出贡献者(被认为是最高专家)犯了一个错误,然后其他人就会跟随他,就像在此线程中发生的那样。如果错误得到了很多投票,人们会继续投票(如果这样,那就是:“因为每个人都这样说,那么这是真的”),其他将来到论坛的人会认为这是正确的答案。
罗南·阿里

1
@RonenAriely这就是为什么我总是向下滚动的原因:)
robotik

13

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

因此,它去了:

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

11

您当然可以更改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
-  -  -

这会改变查询时间吗?
blindguy16年

@blindguy不,它不会改变您的查询时间
mevdiven

9

在SQLServer Management Studio中:

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

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

然后:

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

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


6

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

您还可以将新列添加到表中,逐列复制数据,删除旧列,然后重命名新列以匹配旧列。下面是一个简单的示例: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

1
我写了一个类似的存储过程。它使用动态SQL自动执行表重建。caseyplummer.wordpress.com/2013/07/22/...
凯西直立

6

在SQLServer Management Studio中:

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

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

现在您可以重新排序表格了。


2

SQL Server在内部构建脚本。它创建具有新更改的临时表,然后复制数据并删除当前表,然后从temp表中重新创建表插入。我从“ Generate Change script”选项ssms 2014中找到它。这样的脚本。从这里开始:如何使用SQL查询更改表中的列顺序

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

1

如果表中有足够的列,则可以尝试此操作。首先创建一个具有首选列顺序的新表。

    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中不起作用。
让·弗朗索瓦·

0

最终,您根本无法在MS SQL中执行此操作。我最近使用从查找表中读取的存储过程在旅途中(应用程序启动)创建了表。当我创建一个将这些与另一个表结合在一起的视图时,我手动创建了一个先前的表(相同的架构,带有数据),但是失败了-仅仅是因为我在视图中使用了“ Select * UNION Select *”。同时,如果仅使用通过存储过程创建的内容,则表示成功。

结论:如果有任何依赖于列顺序的应用程序,那确实不是一个好的编程方法,并且肯定会在将来造成问题。列应该“随意”在任何地方,并可以用于任何数据处理(INSERT,UPDATE,SELECT)。


0

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

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

  2. 重命名原始表。

  3. 使用CTAS按所需顺序创建原始表。

  4. 放下旧桌子。

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


0

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

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

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

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

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

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

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


0

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

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

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

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

将第三列的数据类型更改为与上一列相同的类型,然后在其中复制数据。

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

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

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

更改第二列的数据类型。

请记住,列顺序就像marc_s 所说的那样只是一种“美容”的事情。


-1

SELECT * FROM TABLE1

显示表的默认列顺序。

如果要更改列的顺序。

指定要显示的列名

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

问题不在于临时订购。问题是关于更改表并添加新列时的表设计结构。
vikas Chaturvedi

-1

索引后,如果从XXXX中选择*,则结果应与索引相同,但只能是结果集。.不是表的结构


-1

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

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

我不知道这是否会像SSMS中那样删除并重新创建表。无论哪种方式,我都不会在生产数据库上掷骰子,尽管这种方法似乎很有趣并且值得研究。
samis

该功能在OP中指定的SQL Server中不起作用。希望它做到了。
比尔

1
这是MySQL语法,而不是SQL Server。
乔恩·施耐德

-1

为了具有特定的列顺序,您需要按希望的顺序逐列选择。选择顺序指示如何在输出中对列进行排序。



-2

修改表名首先修改int(5)的列名;将列带到第一个alter table name修改(tablename)之后的columnname int(5);


-3

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

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

2
这是MySQL语法,而不是SQL Server。
乔恩·施耐德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.