I have multiple columns
Dbname: dbo.Test
Column's name (example) :
ABC_1 | DEF_2 | GHI_3 | JKL_4 | MNO_5 | PQR_6 | STU_7 How can I write queries that can drop column GHI_3 until STU_7 using a loop?
I have multiple columns
Dbname: dbo.Test
Column's name (example) :
ABC_1 | DEF_2 | GHI_3 | JKL_4 | MNO_5 | PQR_6 | STU_7 How can I write queries that can drop column GHI_3 until STU_7 using a loop?
You don't need to write a loop to do this, one way is using sys.columns table to get all the columns which you want to drop.
Let say you want to drop all columns except 'Col11' and 'Col2' in that case you can write your query like following.
declare @dropstmt as nvarchar(max) ='alter table Test drop column ' + stuff((select ', ' + quotename(name) from ( select c.name from sys.columns c JOIN sys.tables t ON c.object_id = t.object_id where t.name = 'test' and c.name not in('col1','col2') )t for xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, ''); print @dropstmt exec sp_executesql @dropstmt You can use this query to delete the multiple columns from the table.
alter table Test drop column GHI_3, JKL_4, MNO_5, PQR_6, STU_7 As alternative to solution on dropping the columns directly with Alter Statement , if you want to make use of loop, you can use cursor as well.
Create a test table
Create table testdropcols (Col1 varchar(20) ,col2 varchar (30) ,col3 varchar (30) ,col4 varchar(30) ,col5 varchar(30) ,col6 varchar(30) ,col7 varchar(30) ,col8 varchar(30) ,col9 varchar(30) ,col10 varchar(30)) Use systables and syscolumns for current database to get all the columns for a given table, and select few columns just for test.
Declare @tablename varchar(30) , @colname varchar(30), @rownum int DECLARE Curstest CURSOR for select Table_name,columnname,rownum from ( select st.name as Table_name, sc.name as columnname, Row_number() over (partition by st.name order by sc.name) rownum from sys.tables st join sys.columns sc on st.object_id = sc.object_id where st.name = 'testdropcols' ) z where z.rownum between 5 and 10 Open Curstest Fetch next from Curstest into @tablename, @colname, @rownum while @@FETCH_STATUS = 0 Begin declare @sql varchar(max) set @sql = 'ALTER TABLE '+@tablename+' Drop column '+@colname+'' Print @sql Exec(@sql) Print('Dropping column '+ @colname + ' from ' + @tablename+ ' for rownumber ' +cast(@rownum as varchar(10))) Fetch next from Curstest into @tablename, @colname, @rownum end Close Curstest DEALLOCATE Curstest With the print statement inside cursor you get the output in this way with each execution.
ALTER TABLE testdropcols Drop column col4 Dropping column col4 from testdropcols for rownumber 5 ALTER TABLE testdropcols Drop column col5 Dropping column col5 from testdropcols for rownumber 6 ALTER TABLE testdropcols Drop column col6 Dropping column col6 from testdropcols for rownumber 7 ALTER TABLE testdropcols Drop column col7 Dropping column col7 from testdropcols for rownumber 8 ALTER TABLE testdropcols Drop column col8 Dropping column col8 from testdropcols for rownumber 9 ALTER TABLE testdropcols Drop column col9 Dropping column col9 from testdropcols for rownumber 10 If you select the testdropcols you will have the columns which did not exist in the drop statement in
Col1 Col2 Col3 Col10 In SQL Server, for dropping multiple columns of a table considering columns has constraints also, this is how can you do that
alter table dbo.Test drop column GHI_3, STU_7 Syntax:
DROP { [ CONSTRAINT ] constraint_name | COLUMN column_name } [ ,...n ] And there is no need to do this in loop, it can be done in a single statement.
Adding this because other answers didn't actually used a loop. I don't know how many times you would use something like this though... It surely can be improved
USE Dbname; go CREATE PROCEDURE DeleteColumnRange @table_name varchar(100), @first varchar(100), @last varchar(100) AS SET NOCOUNT ON declare @range_start int declare @range_end int SELECT ORDINAL_POSITION, COLUMN_NAME INTO #columns_to_delete FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE @table_name set @range_start = (SELECT ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE @table_name AND COLUMN_NAME LIKE @first) set @range_end = (SELECT ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE @table_name AND COLUMN_NAME LIKE @last) DECLARE @result NVARCHAR(max) IF @range_end > @range_start DECLARE @cnt INT = @range_start WHILE @cnt < @range_end BEGIN SET @cnt = @cnt + 1 SET @result = (SELECT COLUMN_NAME from #columns_to_delete where ORDINAL_POSITION = @cnt) print ('ALTER TABLE ' + @table_name + ' DROP COLUMN ' + @result) END; GO Usage:
DeleteColumnRange @table_name = 'Test', @first = 'GHI_3', @last = 'STU_7' Returns:
ALTER TABLE Test DROP COLUMN JKL_4 ALTER TABLE Test DROP COLUMN MNO_5 ALTER TABLE Test DROP COLUMN PQR_6 Just copy and execute, safer than dropping columns.
I have provided a sample script to delete a list of columns from a table. You don't need a loop, as you can delete multiple columns in a single DROP COLUMN statement.
USE tempdb go CREATE TABLE dbo.test(a int, b int, c int) DECLARE @TableName SYSNAME = N'dbo.test' -- table holding columns to drop DECLARE @ColumnNames NVARCHAR(4000) = N'b,c' -- columns to drop DECLARE @sqlDropColumnStmt NVARCHAR(4000) SET @sqlDropColumnStmt = N'ALTER TABLE ' + @TableName + N' DROP COLUMN ' + @ColumnNames; EXEC(@sqlDropColumnStmt)