SQL Server'da aynı anda birden çok sütun nasıl değiştirilir


143

ALTERBir tabloda birkaç sütun veri türlerine ihtiyacım var .

Tek bir sütun için aşağıdakiler iyi çalışır:

ALTER TABLE tblcommodityOHLC
ALTER COLUMN
    CC_CommodityContractID NUMERIC(18,0) 

Ancak bir ifadede birden çok sütunu nasıl değiştirebilirim? Aşağıdakiler çalışmaz:

ALTER TABLE tblcommodityOHLC
ALTER COLUMN
    CC_CommodityContractID NUMERIC(18,0), 
    CM_CommodityID NUMERIC(18,0)

1
Tek seferde yapmanın algılanan avantajı nedir?
oneday12 Ağustos'ta

5
@onedaywhen - Böylece SQL Server, yeni veri tipine karşı gerekli doğrulamayı yapmak ve / veya değiştirilen sütunları yeni biçimde yazmak için tablodan bir geçiş yapacaktır.
Martin Smith

1
O zaman büyük bir avantaj yok!
oneday2

4
Aksine. Büyük tablolarda birden çok sütun için 24 yerine 2 saatte bir değiştirmenin olması büyük bir avantaj olacaktır.
Norbert Kardos

Yanıtlar:


135

Bu mümkün değil. Bunu tek tek yapmanız gerekecek.

Değiştirilmiş sütunlarınızı içeren bir Geçici Tablo oluşturabilir, verileri karşıya kopyalayabilir, orijinal tablonuzu bırakabilir ve Geçici Tablonuzu orijinal adınızla yeniden adlandırabilirsiniz.


5
+1, You will need to do this one by one.öyleyse, önemli olan nedir, sadece birden fazla ALTER TABLE ALTER COLUMNkomut kullanın?
KM.

6
@KM Bir sorun, büyük bir tablo değiştiriyorsanız. Her ifade yeni bir tarama anlamına gelir, ancak birden fazla sütunu değiştirebilseydiniz, tüm değişiklikler çok daha hızlı olabilirdi
erikkallen

@erikkallen, sonra SSMS araçları genellikle komut dosyalarını oluşturmak gibi yapmak: yeni bir tablo oluşturmak ve FK ve dizinleri çoğaltmak, vb, orijinal tablo bırakın ve sonra yeni tablo,
KM

Tabloları bırakmak ve yeniden oluşturmak oldukça yoğun bir işlemdir. SSMS'de varsayılan olarak devre dışı bırakıldı ve muhtemelen iyi bir nedenden dolayı.
jocull

"Each statement means a new scan": Mutlaka @erikkallen değil. Bazı durumlarda ALTER sütunu basit bir meta veri değişikliğidir. Yarın dersime "SQL Internals - Physical Table Structure under the hood, and implementation on real case scenarios pratikte görmek için "
Ronen Ariely

26

ALTER COLUMNTek bir ALTER TABLEdeyim içinde birden çok işlem yapmak mümkün değildir.

ALTER TABLESözdizimine buradan bakın

Birden fazla yapabilirsiniz ADD veya birden çok DROP COLUMN, ancak bir tane yapabilirsiniz ALTER COLUMN.


17

Diğerlerinin yanıtladığı gibi, birden fazla ALTER TABLEifadeye ihtiyacınız vardır .
Aşağıdakileri deneyin:

ALTER TABLE tblcommodityOHLC alter column CC_CommodityContractID NUMERIC(18,0);
ALTER TABLE tblcommodityOHLC alter column CM_CommodityID NUMERIC(18,0);

12

Aşağıdaki çözüm, birden çok sütunu değiştirmek için tek bir ifade değildir, ancak evet, hayatı kolaylaştırır:

  1. Bir tablonun CREATEkomut dosyasını oluşturun .

  2. İlk satır için CREATE TABLEile değiştirALTER TABLE [TableName] ALTER COLUMN

  3. İstenmeyen sütunları listeden kaldırın.

  4. Sütun veri türlerini istediğiniz gibi değiştirin.

  5. Aşağıdaki gibi bir Bul ve Değiştir… gerçekleştirin :

    1. Bul: NULL,
    2. İle değiştirin: NULL; ALTER TABLE [TableName] ALTER COLUMN
    3. Hit Değiştir düğmesine.
  6. Komut dosyasını çalıştırın.

Umarım çok zaman kazanır :))


6

Birçoğunun söylediği gibi, ALTER COLUMNdeğiştirmek istediğiniz her sütun için bir tane olmak üzere birden fazla ifade kullanmanız gerekir .

Tablonuzdaki sütunların tümünü veya birkaçını aynı veri türüne değiştirmek istiyorsanız (VARCHAR alanını 50'den 100 karaktere genişletmek gibi), aşağıdaki sorguyu kullanarak tüm ifadeleri otomatik olarak oluşturabilirsiniz. Bu teknik, aynı karakteri birden çok alanda (tüm sütunlardan \ t kaldırmak gibi) değiştirmek istiyorsanız da kullanışlıdır.

SELECT
     TABLE_CATALOG
    ,TABLE_SCHEMA
    ,TABLE_NAME
    ,COLUMN_NAME
    ,'ALTER TABLE ['+TABLE_SCHEMA+'].['+TABLE_NAME+'] ALTER COLUMN ['+COLUMN_NAME+'] VARCHAR(300)' as 'code'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'your_table' AND TABLE_SCHEMA = 'your_schema'

Bu ALTER TABLE, her sütun için sizin için bir ifade oluşturur .


1

Yönetim stüdyosundaki değişiklikleri yaparsanız ve komut dosyaları oluşturursanız, yeni bir tablo oluşturur ve değiştirilen veri türleriyle eski verileri buna ekler. İki sütunun veri türlerini değiştiren küçük bir örnek

/*
   12 August 201008:30:39
   User: 
   Server: CLPPRGRTEL01\TELSQLEXPRESS
   Database: Tracker_3
   Application: 
*/

/* 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 TABLE dbo.tblDiary
    DROP CONSTRAINT FK_tblDiary_tblDiary_events
GO
ALTER TABLE dbo.tblDiary_events SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_tblDiary
    (
    Diary_ID int NOT NULL IDENTITY (1, 1),
    Date date NOT NULL,
    Diary_event_type_ID int NOT NULL,
    Notes varchar(MAX) NULL,
    Expected_call_volumes real NULL,
    Expected_duration real NULL,
    Skill_affected smallint NULL
    )  ON T3_Data_2
     TEXTIMAGE_ON T3_Data_2
GO
ALTER TABLE dbo.Tmp_tblDiary SET (LOCK_ESCALATION = TABLE)
GO
SET IDENTITY_INSERT dbo.Tmp_tblDiary ON
GO
IF EXISTS(SELECT * FROM dbo.tblDiary)
     EXEC('INSERT INTO dbo.Tmp_tblDiary (Diary_ID, Date, Diary_event_type_ID, Notes, Expected_call_volumes, Expected_duration, Skill_affected)
        SELECT Diary_ID, Date, Diary_event_type_ID, CONVERT(varchar(MAX), Notes), Expected_call_volumes, Expected_duration, CONVERT(smallint, Skill_affected) FROM dbo.tblDiary WITH (HOLDLOCK TABLOCKX)')
GO
SET IDENTITY_INSERT dbo.Tmp_tblDiary OFF
GO
DROP TABLE dbo.tblDiary
GO
EXECUTE sp_rename N'dbo.Tmp_tblDiary', N'tblDiary', 'OBJECT' 
GO
ALTER TABLE dbo.tblDiary ADD CONSTRAINT
    PK_tblDiary PRIMARY KEY NONCLUSTERED 
    (
    Diary_ID
    ) WITH( PAD_INDEX = OFF, FILLFACTOR = 86, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON T3_Data_2

GO
CREATE UNIQUE CLUSTERED INDEX tblDiary_ID ON dbo.tblDiary
    (
    Diary_ID
    ) WITH( PAD_INDEX = OFF, FILLFACTOR = 86, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON T3_Data_2
GO
CREATE NONCLUSTERED INDEX tblDiary_date ON dbo.tblDiary
    (
    Date
    ) WITH( PAD_INDEX = OFF, FILLFACTOR = 86, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON T3_Data_2
GO
ALTER TABLE dbo.tblDiary WITH NOCHECK ADD CONSTRAINT
    FK_tblDiary_tblDiary_events FOREIGN KEY
    (
    Diary_event_type_ID
    ) REFERENCES dbo.tblDiary_events
    (
    Diary_event_ID
    ) ON UPDATE  CASCADE 
     ON DELETE  CASCADE 

GO
COMMIT

1

Her şeyi kendiniz yazmak ve tüm sütunları aynı veri türüne değiştirmek istemiyorsanız, bu daha kolay olabilir:

select 'alter table tblcommodityOHLC alter column '+name+ 'NUMERIC(18,0);'
from syscolumns where id = object_id('tblcommodityOHLC ')

Çıktıyı kopyalayıp sorgunuz olarak yapıştırabilirsiniz


0
select 'ALTER TABLE ' + OBJECT_NAME(o.object_id) + 
    ' ALTER COLUMN ' + c.name + ' DATETIME2 ' + 
    CASE WHEN c.is_nullable = 0 THEN 'NOT NULL' ELSE 'NULL' END
from sys.objects o
inner join sys.columns c on o.object_id = c.object_id
inner join sys.types t on c.system_type_id = t.system_type_id
where o.type='U'
and c.name = 'Timestamp'
and t.name = 'datetime'
order by OBJECT_NAME(o.object_id)

devio'nun izniyle


0

Evan'ın kod örneği sayesinde, daha fazla değiştirebildim ve belirli sütun adları ile başlayan tablolara daha spesifik hale geldim ve kısıtlamalar için de özellikleri işledim. Bu kodu çalıştırdıktan sonra [CODE] sütununu kopyaladım ve sorunsuz bir şekilde yürüttüm.

USE [Table_Name]
GO
SELECT
     TABLE_CATALOG
    ,TABLE_SCHEMA
    ,TABLE_NAME
    ,COLUMN_NAME
    ,DATA_TYPE
    ,'ALTER TABLE ['+TABLE_SCHEMA+'].['+TABLE_NAME+'] DROP CONSTRAINT [DEFAULT_'+TABLE_NAME+'_'+COLUMN_NAME+']; 
ALTER TABLE  ['+TABLE_SCHEMA+'].['+TABLE_NAME+'] ALTER COLUMN ['+COLUMN_NAME+'] datetime2 (7) NOT NULL 
ALTER TABLE  ['+TABLE_SCHEMA+'].['+TABLE_NAME+'] ADD CONSTRAINT [DEFAULT_'+TABLE_NAME+'_'+COLUMN_NAME+'] DEFAULT (''3/6/2018 6:47:23 PM'') FOR ['+COLUMN_NAME+']; 
GO' AS '[CODE]'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'form_%' AND TABLE_SCHEMA = 'dbo'
 AND (COLUMN_NAME = 'FormInserted' OR COLUMN_NAME = 'FormUpdated')
 AND DATA_TYPE = 'datetime'

0
-- create temp table 
CREATE TABLE temp_table_alter
(
column_name varchar(255)    
);

-- insert those coulmns in temp table for which we nee to alter size of columns 
INSERT INTO temp_table_alter (column_name) VALUES ('colm1');
INSERT INTO temp_table_alter (column_name) VALUES ('colm2');
INSERT INTO temp_table_alter (column_name) VALUES ('colm3');
INSERT INTO temp_table_alter (column_name) VALUES ('colm4');

DECLARE @col_name_var varchar(255);
DECLARE alter_table_cursor CURSOR FOR
select column_name from temp_table_alter ;

OPEN alter_table_cursor
FETCH NEXT FROM alter_table_cursor INTO @col_name_var
WHILE @@FETCH_STATUS = 0
 BEGIN

 PRINT('ALTER COLUMN ' + @col_name_var);
 EXEC ('ALTER TABLE Original-table  ALTER COLUMN ['+ @col_name_var + '] DECIMAL(11,2);')

 FETCH NEXT FROM alter_table_cursor INTO @col_name_var
 END

CLOSE alter_table_cursor
DEALLOCATE alter_table_cursor

-- at the end drop temp table
drop table temp_table_alter;

İyi bir çözüm DEĞİL. İmleç ve döngüler TÜM maliyetlerde kaçınılmalıdır !!!
Ray K.

1
Doğru değil, Ray. İmleçler ve döngüler, bazı DDL görevleri ve diğer zorunlu RBR görevleri için uygundur.
Jeff Moden

-3

Tek bir sorguda aşağıdaki gibi birden çok sütunu değiştirebiliriz:

ALTER TABLE `tblcommodityOHLC`
    CHANGE COLUMN `updated_on` `updated_on` DATETIME NULL DEFAULT NULL AFTER `updated_by`,
    CHANGE COLUMN `delivery_datetime` `delivery_datetime` DATETIME NULL DEFAULT CURRENT_TIMESTAMP AFTER `delivery_status`;

Sorguları virgülle ayrılmış olarak verin.


4
Sanırım bu MySql mi? Soru SQL Server içindi ve bu sql sunucusunda çalışmıyor
Tjipke

-4

İfadeyi ALTER COLUMNbir parantez içine koyun , çalışması gerekir.

ALTER TABLE tblcommodityOHLC alter ( column  
CC_CommodityContractID NUMERIC(18,0), 
CM_CommodityID NUMERIC(18,0) )

-4

Sorunuzu doğru anladıysam, aşağıda belirtilen sorguyu kullanarak bir tabloya birden çok sütun ekleyebilirsiniz.

Sorgu:

Alter table tablename add (column1 dataype, column2 datatype);

4
OP, EKLE değil ALTER sütununu sordu.
DR
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.