2013-07-31 8 views
0

Я пытаюсь вычислить код для генерации, который проходит через содержимое таблицы и проверяет, действительно ли он является допустимым столбцом и удаляет все столбцы, которые больше недействительны.удалять столбцы из таблицы

declare @counter int 
declare @col_count int 
declare @col_name char(100) 
declare @temp_sql char(100) 
set @counter = 0 

SELECT @col_count = COUNT(*) from sys.columns 
where Object_ID = Object_ID(N'test') 
AND name <> 'pk_test' 

while @counter < @col_count 
begin 
    with CTE as (
    select name, row_number() over (order by column_id) as ColNo 
    from sys.columns where object_id = object_id('test') AND name <> 'pk_test' 
) 
    select @col_name = name from CTE where ColNo = ((@counter) + 1) 

    SET @temp_sql = 'ALTER TABLE test DROP column ' + @col_name + ';' 
    EXECUTE (@temp_sql); 

    set @counter = @counter + 1 
end 

по какой-то причине EXECUTE вызывает код, чтобы пропустить любой другой вызов, но если я вывезти выполнить с комментарием и бросить в печати, он будет показывать все действительные заявления падения.

Я попытался сделать это:

SET @temp_sql = @temp_swl + 'ALTER TABLE test DROP column ' + @col_name 
enter code here 

Я пытался объединить все изменения таблиц сразу, но это не похоже на работу.

Я чувствую, что мне не хватает чего-то маленького!

+0

Просто любопытно, почему бы не толкнуть допустимые столбцы в новую таблицу, а затем отбросить старую таблицу и переименовать новую? – brian

+1

@brian может быть много данных, и может быть много внешних ключей, указывающих на сохраненный столбец. –

+0

откровенно, потому что я не думал об этом :-), также я хочу сохранить данные, если это возможно, у меня есть флаг «reset», если разработчик хочет полностью отказаться от таблицы или просто хочет «обновить», Это. Я все еще собираюсь и дорабатываю все. Я буду помнить об этом! – Krum110487

ответ

1

Вот более простой подход, который не требует курсора (который является другим именем для цикла while) и не имеет возможности пропускать что-либо. Обратите внимание, что я делаю предположение, что «недействительный» означает «не имеет имени pk_test». Если «недействительно» означает что-то еще, просим пояснить. Конечно, вы, вероятно, хотите убедиться, что стол столбец называется pk_test, иначе последний ALTER не сработает - ваш код в настоящее время не проверяет его.

DECLARE @t NVARCHAR(512), -- the table we're affecting 
     @c SYSNAME;  -- the column we want to keep 

SELECT @t = N'dbo.test', @c = N'pk_test'; 


IF EXISTS 
(
    SELECT 1 FROM sys.columns 
    WHERE [object_id] = OBJECT_ID(@t) 
    AND name = @c 
) 
BEGIN 

    DECLARE @sql NVARCHAR(MAX); 

    SET @sql = N''; 

    SELECT @sql = @sql + N' 
    ALTER TABLE ' + @t + ' DROP COLUMN ' + QUOTENAME(name) + ';' 
    FROM sys.columns WHERE [object_id] = OBJECT_ID(@t) AND name <> @c; 

    PRINT @sql; 
    -- EXEC sp_executesql @sql; 
END 
ELSE 
BEGIN 
    PRINT 'Sorry, can't delete all columns from ' + @t + '.'; 
END 
+0

Мне действительно нужно изучить T-SQL, это очень помогает, все, что мне нужно сделать, это генерировать список текущих столбцов в таблице, и это приведет к удалению всех из них, которые не перечислены! Великий! также существует ли более простой способ сделать список элементов вместо простого И (имя <> 'столбец 1 ИЛИ имя <>' column2 'ИЛИ имя <>' column3 '), это то, что я планирую генерировать, Я предполагаю, что я мог бы просто создать это для переменной «c». – Krum110487

+0

@ Krum110487 какая версия SQL Server? Если в 2008 году вы не могли существовать против параметра table-value. Если раньше вы могли просто заполнить таблицу #temp вручную и сделать это не существует. –

2

Вы каждый раз регенерируете таблицу счетчиком - за исключением того, что вы удаляете одну строку (например, колонку) иногда с помощью инструкции alter table.

Вместо этого сначала создайте таблицу, а затем пропустите ее. Так, замените это:

while @counter < @col_count 
begin 
    with CTE as (
    select name, row_number() over (order by column_id) as ColNo 
    from sys.columns where object_id = object_id('test') AND name <> 'pk_test' 
) 
    select @col_name = name from CTE where ColNo = ((@counter) + 1) 

    SET @temp_sql = 'ALTER TABLE test DROP column ' + @col_name + ';' 
    EXECUTE (@temp_sql); 

    set @counter = @counter + 1 
end 

С этим:

declare @columns table (colnum int not null identity(1, 1), colname varchar(255)); 

insert into @columns(colname) 
    select name 
    from sys.columns 
    where object_id = object_id('test') AND name <> 'pk_test'; 

set @col_count = max(colnum) from @columns; 

while @counter < @col_count 
begin 

    select @col_name = name from @columns where ColNo = ((@counter) + 1); 

    SET @temp_sql = 'ALTER TABLE test DROP column ' + @col_name + ';' 
    EXECUTE (@temp_sql); 

    set @counter = @counter + 1; 
end; 

Я не собираюсь комментировать то, что вы делаете, но это должно исправить «пропуском» проблему путем предварительного вычисления списка колонны. Таким образом, на этот список не влияет заявка alter table.

+0

AH, это имеет смысл! Точка к этому коду предназначена для генерации базы данных, поэтому в основном только для разработчиков, а не для производственного сценария, просто для облегчения моей жизни, спасибо! – Krum110487

Смежные вопросы