如何更改列顺序?

6 database-design sql-server sql-server-2008-r2 alter-table ddl

如何更改 sql server 2008 R2 中的列顺序?

例如:我的餐桌顺序是开斋节------Ename-----Esalary

知道我想要这种格式,例如 Eid---Salary----Ename

谢谢。

Aar*_*and 10

您不应该足够关心现有表的物理列顺序,因为您可能希望在更改它时带来风险。这可能是一个问题的唯一情况是,如果您正在使用SELECT *并希望以某种方式排列输出 - 而您不应该这样做,您应该明确列出列名称(然后您可以将列以您想要的任何顺序,或创建一个执行此操作的视图)。

您可以删除并重新创建表,就像其他人所说的那样,按您喜欢的顺序排列列。但是如果你的表很大,这将是非常具有破坏性的(阻塞,I/O),因为系统上的所有其他用户都必须等待它完成。如果您想确切了解 Management Studio 的功能,请创建此表:

CREATE TABLE dbo.foo(b INT, a INT, r INT);

INSERT dbo.foo(b,a,r) VALUES(1,2,3),(4,5,6);
Run Code Online (Sandbox Code Playgroud)

现在,在对象资源管理器中,右键单击表并选择设计。选择要重新排序的列名称左侧的框。将该列拖到表中的另一个位置。我移到a上面b是因为我是强迫症并且想要按字母顺序排列的列:

在此处输入图片说明

然后我点击“生成更改脚本”按钮,这是它创建的怪物(注意这是一个没有键、约束、触发器等的堆 - 这种重新创建可能会变得非常复杂)。

/*
   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_foo
    (
    a int NULL,
    b int NULL,
    r int NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_foo SET (LOCK_ESCALATION = TABLE)
GO
IF EXISTS(SELECT * FROM dbo.foo)
     EXEC('INSERT INTO dbo.Tmp_foo (a, b, r)
        SELECT a, b, r FROM dbo.foo WITH (HOLDLOCK TABLOCKX)')
GO
DROP TABLE dbo.foo
GO
EXECUTE sp_rename N'dbo.Tmp_foo', N'foo', 'OBJECT' 
GO
COMMIT
Run Code Online (Sandbox Code Playgroud)

为了好玩,让我们创建一些更复杂的东西:

CREATE TABLE dbo.flarb
(
  a INT PRIMARY KEY, 
  b INT NOT NULL CHECK (b>1), 
  c ROWVERSION, 
  d DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  e UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID()
);

CREATE TABLE dbo.blarf
(
  a INT NOT NULL FOREIGN KEY REFERENCES dbo.flarb(a)
);
GO

CREATE TRIGGER dbo.flarb_tr
ON dbo.flarb
FOR UPDATE
AS
  SELECT 1;
GO

CREATE VIEW dbo.flarb_v
WITH SCHEMABINDING
AS
  SELECT a FROM dbo.flarb;
Run Code Online (Sandbox Code Playgroud)

现在我们尝试同样的事情:

'flarb' 表
- 验证列 'e' 的默认值时出错。
- 警告:将修改以下模式绑定对象:
- 查看“dbo.flarb_v”:模式绑定将被删除。

哎呀。值得庆幸的是,我们仍然可以继续查看脚本的外观:

/* 
  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
ALTER VIEW dbo.flarb_v

AS
  SELECT a FROM dbo.flarb;GO
ALTER TABLE dbo.flarb
    DROP CONSTRAINT DF__flarb__d__1B7E091A
GO
ALTER TABLE dbo.flarb
    DROP CONSTRAINT DF__flarb__e__1C722D53
GO
CREATE TABLE dbo.Tmp_flarb
    (
    a int NOT NULL,
    b int NOT NULL,
    d datetime NOT NULL,
    c timestamp NOT NULL,
    e uniqueidentifier NOT NULL
    )  ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_flarb SET (LOCK_ESCALATION = TABLE)
GO
ALTER TABLE dbo.Tmp_flarb ADD CONSTRAINT
    DF__flarb__d__1B7E091A DEFAULT (getdate()) FOR d
GO
ALTER TABLE dbo.Tmp_flarb ADD CONSTRAINT
    DF__flarb__e__1C722D53 DEFAULT (newsequentialid()) FOR e
GO
IF EXISTS(SELECT * FROM dbo.flarb)
     EXEC('INSERT INTO dbo.Tmp_flarb (a, b, d, e)
        SELECT a, b, d, e FROM dbo.flarb WITH (HOLDLOCK TABLOCKX)')
GO
ALTER TABLE dbo.blarf
    DROP CONSTRAINT FK__blarf__a__1E5A75C5
GO
DROP TABLE dbo.flarb
GO
EXECUTE sp_rename N'dbo.Tmp_flarb', N'flarb', 'OBJECT' 
GO
ALTER TABLE dbo.flarb ADD CONSTRAINT
    PK__flarb__3BD0198EF8B8CFAF PRIMARY KEY CLUSTERED 
    (
    a
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO
ALTER TABLE dbo.flarb ADD CONSTRAINT
    CK__flarb__b__1A89E4E1 CHECK (([b]>(1)))
GO
CREATE TRIGGER dbo.flarb_tr
ON dbo.flarb
FOR UPDATE
AS
  SELECT 1;
GO
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.blarf ADD CONSTRAINT
    FK__blarf__a__1E5A75C5 FOREIGN KEY
    (
    a
    ) REFERENCES dbo.flarb
    (
    a
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE dbo.blarf SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
Run Code Online (Sandbox Code Playgroud)

是的,这看起来真的很像我想在生产中运行的东西,即使表很小。

另一种选择是完全手动执行此操作。假设你有这张表:

CREATE TABLE dbo.Employee
(
  EmployeeID INT,
  Name NVARCHAR(255),
  Salary INT
);
INSERT ...
Run Code Online (Sandbox Code Playgroud)

从理论上讲,如果不考虑由键、约束、触发器和模式绑定对象引起的复杂情况,您可以通过以下方式“更改”列的顺序 - 对于要移动的列左侧的每一列 - 创建一个新列,移动数据,删除旧列,并重命名新列。这是有效的,因为新列始终添加到表的“末尾”。忽略错误处理和任何其他复杂情况:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
ALTER TABLE dbo.Employee ADD Nametmp NVARCHAR(255);
UPDATE dbo.Employee SET Nametmp = Name;
ALTER TABLE dbo.Employee DROP COLUMN Name;
EXEC sp_rename N'dbo.Employee.Nametmp', N'Name', N'COLUMN';
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)

这当然有可能与 Management Studio 仅仅交换整个表的方法一样具有破坏性(或更糟),并且如果您想要移动多个列,则变得非常复杂。

现在,您真的需要更改列顺序吗?


Mar*_*son 2

如果不删除并重新创建表,则无法更改 SSMS 中看似物理列的顺序。

为什么不直接更改查询以按不同的顺序选择列呢?

从:

SELECT Eid, Ename, Esalary FROM Table
Run Code Online (Sandbox Code Playgroud)

到:

SELECT Eid, Esalary, Ename FROM Table
Run Code Online (Sandbox Code Playgroud)

  • 我基本上同意,并且投了赞成票,但是如果你非常小心的话,你可以在不放弃桌子的情况下做到这一点(请参阅我答案的最后一点)。 (2认同)