如何在SQL Server中删除多列

时间:2019-02-28 03:27:06

标签: sql sql-server

我有多列

数据库名称:dbo.Test

列名(示例):

ABC_1 | DEF_2 | GHI_3 | JKL_4 | MNO_5 | PQR_6 | STU_7

如何编写使用循环将列GHI_3删除到STU_7的查询?

6 个答案:

答案 0 :(得分:3)

您无需编写循环来执行此操作,一种方法是使用sys.columns表来获取要删除的所有列。

假设您要删除除“ Col11”和“ Col2”以外的所有列,在这种情况下,您可以像下面这样编写查询。

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  

答案 1 :(得分:1)

作为使用Alter语句直接删除列的解决方案的替代方法,如果要使用循环,也可以使用游标。

创建测试表

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))  

对当前数据库使用systables和syscolumns可以获取给定表的所有列,并仅选择几列进行测试。

    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 

将print语句置于光标内,每次执行时都以这种方式获得输出。

  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

如果选择testdropcols,您将拥有

的drop语句中不存在的列。
Col1 Col2 Col3 Col10 

答案 2 :(得分:0)

您可以使用此查询从表中删除多列。

alter table Test
    drop column GHI_3, JKL_4, MNO_5, PQR_6, STU_7

答案 3 :(得分:0)

SQL Server 中,如果要考虑到列也有约束的情况下删除表的多列,这是怎么做的

alter table dbo.Test
    drop column GHI_3, STU_7

语法:

DROP { [ CONSTRAINT ] constraint_name | COLUMN column_name } [ ,...n ] 

并且无需循环执行此操作,它可以在单个语句中完成。

答案 4 :(得分:0)

添加此内容是因为其他答案实际上并未使用循环。 我不知道您会用多少次这样的东西... 当然可以改善

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 

用法:

DeleteColumnRange @table_name = 'Test', @first = 'GHI_3', @last = 'STU_7'

返回:

ALTER TABLE Test DROP COLUMN JKL_4
ALTER TABLE Test DROP COLUMN MNO_5
ALTER TABLE Test DROP COLUMN PQR_6

只需复制和执行,比删除列更安全。

答案 5 :(得分:0)

我提供了一个示例脚本,用于从表中删除列列表。您不需要循环,因为您可以在单个DROP COLUMN语句中删除多个列。

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)