web-dev-qa-db-fra.com

Comment changer l'ordre des colonnes?

Comment changer l'ordre des colonnes dans SQL Server 2008 R2?

Par exemple: ma commande de table est Eid ------ Ename ----- Esalary

Je sais que je veux ce format comme Eid --- Salary ---- Ename

Merci.

5
user36326

Vous ne devez pas vous soucier de l'ordre des colonnes physiques dans le tableau. Le seul cas où cela devrait être un problème est si vous utilisez SELECT * - et vous ne devriez pas faire cela , vous devez lister explicitement les noms des colonnes (et vous pouvez ensuite mettre les colonnes dans l'ordre que vous voulez).

Vous pouvez supprimer et recréer le tableau, comme d'autres l'ont dit, avec les colonnes dans votre ordre préféré. Mais cela va être très perturbant (blocage, E/S) si votre table est grande, car tous les autres utilisateurs du système devront attendre que cela se termine. Si vous voulez voir exactement ce que fait Management Studio, créez ce tableau:

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

INSERT dbo.foo(b,a,r) VALUES(1,2,3),(4,5,6);

Maintenant, dans l'Explorateur d'objets, cliquez avec le bouton droit sur la table et choisissez Conception. Cochez la case à gauche du nom de la colonne que vous souhaitez réorganiser. Faites glisser la colonne vers un autre emplacement dans le tableau. J'ai déplacé a au-dessus de b parce que je suis TOC et que je voulais les colonnes par ordre alphabétique:

enter image description here

Ensuite, j'ai cliqué sur le bouton "Générer un script de changement", et voici la monstruosité qu'il a créée (et notez qu'il s'agit d'un tas sans clés, contraintes, déclencheurs, etc. - cette recréation peut devenir assez complexe).

/*
   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

Pour le plaisir, créons quelque chose d'un peu plus complexe:

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;

Maintenant, nous essayons la même chose:

table 'flarb'
- Erreur lors de la validation de la valeur par défaut pour la colonne 'e'.
- Avertissement: les objets liés au schéma suivants seront modifiés:
- Voir 'dbo.flarb_v': la liaison de schéma sera supprimée.

Oops. Heureusement, nous pouvons toujours voir à quoi ressemblera le script:

/* 
  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

Oui, qui ressemble vraiment à quelque chose que je veux exécuter en production , même si la table est petite.

L'autre alternative est de le faire assez manuellement. Disons que vous avez ce tableau:

CREATE TABLE dbo.Employee
(
  EmployeeID INT,
  Name NVARCHAR(255),
  Salary INT
);
INSERT ...

Théoriquement, et en omettant les complications causées par les clés, les contraintes, les déclencheurs et les objets liés au schéma, vous pouvez "modifier" l'ordre des colonnes en - pour chaque colonne à gauche de celle que vous souhaitez déplacer - en créant une nouvelle colonne, déplacer les données, supprimer l'ancienne colonne et renommer la nouvelle colonne. Cela fonctionne car la nouvelle colonne est toujours ajoutée à la "fin" du tableau. Oublier la gestion des erreurs et toute autre complication:

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;

Bien sûr, cela peut être aussi perturbateur (ou pire) que l'approche de Management Studio consistant à simplement échanger la table entière, et devient vraiment compliqué si vous souhaitez déplacer plusieurs colonnes.

Maintenant, avez-vous vraiment besoin de changer l'ordre des colonnes ?

9
Aaron Bertrand

Vous ne pouvez pas modifier ce qui semble être l'ordre des colonnes physiques dans SSMS sans supprimer et recréer la table.

Pourquoi ne pas simplement modifier la requête pour sélectionner les colonnes dans un ordre différent?

De:

SELECT Eid, Ename, Esalary FROM Table

À:

SELECT Eid, Esalary, Ename FROM Table
2
Mark Sinkinson

Voulez-vous changer la table sous-jacente ou simplement les résultats?

S'il ne s'agit que des résultats, réorganisez simplement votre instruction select.

par exemple. au lieu de

SELECT Eid, Ename, Esalary FROM ThatTable;

utilisation

SELECT Eid, ESalary, EName FROM ThatTable;

Vous pouvez également configurer une vue basée sur cette table qui sélectionne dans l'ordre souhaité.

Et bien sûr, si vous en avez vraiment besoin, vous pouvez simplement supprimer et recréer la table. Assurez-vous simplement d'exporter et d'importer les données si vous souhaitez les conserver.

1
Mark

Outils> Options> Concepteurs> Concepteurs de tables et de bases de données> décochez empêcher l'enregistrement des modifications ...

Après avoir enregistré les paramètres, vous pouvez maintenant enregistrer les modifications apportées en mode Création, y compris les champs mobiles

1
Rolenn Pyx Lolarga

Ce n'est pas "FACILE" possible. Mais vous pouvez en créer une autre et réinsérer les mêmes données, comme vous le souhaitez. La façon la plus simple de changer l'ordre des instructions d'exploitation. Comme:
SELECT Eid, Salary, Ename FROM TABLE;

0
Jann Claude