Bagaimana mengubah beberapa kolom sekaligus dalam SQL Server


143

aku ingin ALTER tipe data dari beberapa kolom dalam sebuah tabel.

Untuk satu kolom, berikut ini berfungsi dengan baik:

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

Tetapi bagaimana cara mengubah beberapa kolom dalam satu pernyataan? Berikut ini tidak berfungsi:

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

1
Apa keuntungan yang dirasakan untuk melakukannya dalam sekali jalan?
onedaywhen

5
@onedaywhen - Sehingga SQL Server hanya akan membuat satu melewati tabel untuk melakukan validasi yang diperlukan terhadap tipe data baru dan / atau menulis kolom yang diubah dalam format baru.
Martin Smith

1
Tidak ada keuntungan besar kalau begitu!
onedaywhen

4
Kebalikan. Ini akan menjadi keuntungan besar untuk menjalankan alter dalam 2 jam, bukan 24 untuk beberapa kolom pada tabel besar.
Norbert Kardos

Jawaban:


135

Ini tidak mungkin. Anda harus melakukan ini satu per satu.

Anda bisa membuat Tabel Sementara dengan kolom yang dimodifikasi di, salin data, letakkan tabel asli Anda dan ganti nama Tabel Sementara Anda dengan nama asli Anda.


5
+1, You will need to do this one by one.jadi, apa masalahnya, cukup gunakan beberapa ALTER TABLE ALTER COLUMNperintah?
KM.

6
@ KM Satu masalah adalah jika Anda mengubah tabel besar. Setiap pernyataan berarti pemindaian baru tetapi jika Anda dapat mengubah banyak kolom, semua perubahan bisa jadi lebih cepat
erikkallen

@ erikkallen, maka lakukan seperti alat SSMS biasanya menghasilkan skrip mereka: membuat tabel baru dan meniru FK dan indeks, dll, letakkan tabel asli dan kemudian ganti nama tabel baru,
KM.

Menjatuhkan dan membuat ulang tabel adalah operasi yang cukup intensif. Ini dinonaktifkan secara default di SSMS sekarang, dan mungkin karena alasan yang bagus.
jocull

"Each statement means a new scan": Tidak harus @erikkallen. Dalam beberapa kasus, kolom ALTER adalah perubahan metadata sederhana. Anda dipersilakan untuk bergabung dengan kuliah saya besok tentang " SQL Internals - Physical Table Structure under the hood, and implementation on real case scenarios" untuk melihat semuanya secara praktis :-)
Ronen Ariely

26

Melakukan beberapa ALTER COLUMNtindakan di dalam satu ALTER TABLEpernyataan tidak dimungkinkan.

Lihat ALTER TABLEsintaks di sini

Anda dapat melakukan banyak ADDatau banyak DROP COLUMN, tetapi hanya satu ALTER COLUMN.


17

Seperti yang dijawab orang lain, Anda perlu beberapa ALTER TABLEpernyataan.
Coba ikuti:

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

12

Solusi berikut bukan pernyataan tunggal untuk mengubah beberapa kolom, tapi ya, itu membuat hidup menjadi sederhana:

  1. Buat CREATEskrip tabel .

  2. Ganti CREATE TABLEdengan ALTER TABLE [TableName] ALTER COLUMNuntuk baris pertama

  3. Hapus kolom yang tidak diinginkan dari daftar.

  4. Ubah tipe data kolom yang Anda inginkan.

  5. Lakukan Cari dan Ganti ... sebagai berikut:

    1. Cari: NULL,
    2. Ubah dengan: NULL; ALTER TABLE [TableName] ALTER COLUMN
    3. Tekan tombol Ganti .
  6. Jalankan skrip.

Semoga ini akan menghemat banyak waktu :))


6

Seperti yang banyak orang lain katakan, Anda perlu menggunakan beberapa ALTER COLUMNpernyataan, satu untuk setiap kolom yang ingin Anda modifikasi.

Jika Anda ingin mengubah semua atau beberapa kolom di tabel Anda ke tipe data yang sama (seperti memperluas bidang VARCHAR dari 50 hingga 100 karakter), Anda bisa membuat semua pernyataan secara otomatis menggunakan kueri di bawah ini. Teknik ini juga berguna jika Anda ingin mengganti karakter yang sama di beberapa bidang (seperti menghapus \ t dari semua kolom).

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'

Ini menghasilkan ALTER TABLEpernyataan untuk setiap kolom untuk Anda.


1

Jika Anda melakukan perubahan di studio manajemen dan menghasilkan skrip, ia membuat tabel baru dan memasukkan data lama ke dalamnya dengan tipe data yang diubah. Berikut adalah contoh kecil mengubah tipe data dua kolom

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

Jika Anda tidak ingin menulis semuanya sendiri dan mengubah semua kolom ke tipe data yang sama, ini dapat mempermudah:

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

Anda dapat menyalin dan menempelkan output sebagai permintaan Anda


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)

milik devio


0

Berkat sampel kode Evan, saya dapat memodifikasinya lebih banyak dan membuatnya lebih spesifik untuk tabel yang dimulai dengan, nama kolom spesifik DAN menangani spesifik untuk kendala juga. Saya menjalankan kode itu dan kemudian menyalin kolom [KODE] dan menjalankannya tanpa masalah.

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;

BUKAN solusi yang baik. Kursor dan loop harus dihindari dengan biaya SEMUA !!!
Ray K.

1
Itu tidak benar, Ray. Kursor dan loop baik untuk tugas DDL tertentu dan tugas RBR lainnya.
Jeff Moden

-3

Kami dapat mengubah beberapa kolom dalam satu kueri seperti ini:

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`;

Cukup berikan pertanyaan sebagai dipisahkan koma.


4
Saya pikir ini MySql? Pertanyaannya adalah untuk SQL Server, dan ini tidak berfungsi di sql server
Tjipke

-4

Masukkan ALTER COLUMNpernyataan di dalam braket, itu harus bekerja.

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

-4

Jika saya memahami pertanyaan Anda dengan benar, Anda dapat menambahkan beberapa kolom dalam sebuah tabel dengan menggunakan kueri yang disebutkan di bawah ini.

Pertanyaan:

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

4
OP bertanya tentang kolom ALTER, bukan ADD.
DR
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.